兄弟们,今天咱们来盘一个经典但永远能要命的漏洞------文件上传。
很多开发觉得"我加了后缀校验,应该没事了吧?"结果被黑客用个图片马或者解析漏洞直接拿下服务器权限。处置文件上传攻击,先把四条红线刻在脑子里,严禁执行以下操作:
- 不要直接删除恶意文件了事:删了就没法取证了,你不知道黑客是怎么传进来的,也不知道他传了几个,更不知道他有没有留其他后门。
- 不要只加后缀黑名单 :
.php禁了,他传.php5、.phtml、.Php,黑名单永远绕得完,堵不干净的。 - 不要忽略已上传的其他恶意文件:黑客传WebShell往往不止传一个,他可能传了个连接用的,又传了个提权用的,只删你看到的那个等于没清。
- 不要只看扩展名不看文件内容 :现在伪造文件头太容易了,看着是个
.jpg,里面其实全是PHP代码。
处置总原则 :"先确认上传入口与恶意文件范围,再隔离清除;先溯源利用方式,再修复校验"。
一、 正确开局:先搞清楚文件是怎么进来的
接到告警说服务器有异常文件,第一件事是确认恶意文件的进入途径。是上传功能本身有漏洞?还是配合了后台弱口令?或者是其他漏洞(比如SSRF)把文件写进来的?
先摸清上传功能全貌:系统里有哪些接口/页面能传文件?文件最终存到了哪个目录?是本地磁盘还是OSS?
按 "上传入口 → 文件落地 → 执行利用" 三层往下收敛,明确区分三类情况:
- 恶意文件已执行 :最严重,WebShell已经跑起来了,直接按主机入侵事件流程处置。
- 恶意文件已上传未执行:文件躺在目录里,但没被访问过,立即隔离清除。
- 上传功能有漏洞未利用:黑客在试探,或者被WAF拦了,赶紧加固修复。
二、 排查主链路:可复制的命令和操作
别靠猜,靠日志和系统命令。以下是排查主链路的标准动作:
1. 查上传目录文件(找异常文件)
bash
# 查找上传目录下最近1天内修改或新增的文件
find /var/www/uploads -type f -mtime -1 -ls
# 重点筛查可疑的脚本扩展名(包括各种变种)
find /var/www/uploads -type f \( -name "*.php*" -o -name "*.jsp*" -o -name "*.asp*" -o -name "*.aspx*" \)
现象对应 :如果在不该有脚本的目录(如图片目录)发现了 .php 或 .jsp 文件,100%是被传了WebShell。
2. 分析恶意文件内容(看是脚本还是图片马)
bash
# 查看文件真实类型(不只看后缀)
file /var/www/uploads/1.jpg
# 查看文件头十六进制,确认是否伪造
hexdump -C /var/www/uploads/1.jpg | head -n 5
# 搜索文件内容里有没有PHP/JSP脚本特征
strings /var/www/uploads/1.jpg | grep -iE "eval|base64_decode|assert|Runtime.getRuntime|ProcessBuilder"
现象对应 :如果 file 命令说是 PHP script,但后缀是 .jpg,说明是纯脚本伪装;如果 file 说是 GIF image,但 strings 搜出了 eval,说明是图片马(文件头是图片,后面拼接了代码)。
3. 查访问日志(找上传请求和执行记录)
bash
# 查上传接口的请求记录,看是谁传的、传的什么文件名
grep -i "upload" /var/log/nginx/access.log | grep -vE "\.(css|js|jpg|png)"
# 查恶意文件是否被访问过(确认是否已执行)
grep "1.jpg" /var/log/nginx/access.log
现象对应 :如果看到上传请求的响应码是200,且随后有对该 .jpg 文件的GET请求(甚至带了POST参数),说明WebShell已经被连接并执行了。
4. 查文件是否被执行(进程关联)
bash
# 查当前正在运行的PHP/Java进程,看有没有异常的脚本在执行
ps -ef | grep -E "php|java" | grep -v grep
# 如果是PHP,查php-fpm的慢日志或执行日志
tail -n 50 /var/log/php-fpm/www-slow.log
5. 查其他目录(防遗漏)
bash
# 查系统临时目录、备份目录有没有隐藏的可疑文件
find /tmp /var/tmp /var/www/backup -type f -name ".*" -mtime -1
find /tmp /var/tmp -type f \( -name "*.php" -o -name "*.sh" -o -name "*.pl" \)
6. 拉出攻击者的完整上传时间线
结合第一步找到的文件修改时间(mtime)和第三步的日志时间,画出攻击者的操作轨迹:什么时候探测的接口、什么时候传的文件、什么时候连的WebShell。
三、 高频现场逐个拆
1. 扩展名绕过
- 现象 :传
.php被拒,但传.Php、.phtml、.php5、.php.(Windows特性)、.php%00.jpg(截断)成功了。 - 排查命令 :
find /var/www/uploads -type f -iregex ".*\.ph[ppt5]*" - 处理 :废弃黑名单,改用严格的白名单 (只允许
.jpg,.png,.pdf等),并且统一转小写后再比对。
2. 内容校验绕过(图片马)
- 现象 :代码里校验了文件头(如前几个字节必须是
GIF89a),但黑客在图片文件末尾追加了<?php eval($_POST['cmd']);?>。 - 排查命令 :
hexdump -C 1.jpg | tail -n 10(看文件尾部) - 处理 :对于图片文件,不要只做字节头校验,必须用图像处理库(如GD库、ImageMagick)进行重绘/重编码,把附加的恶意代码直接"洗"掉。
3. 上传目录可执行脚本
-
现象 :文件确实传到了
/uploads/目录,后缀也是.php,但原本以为这个目录不能执行脚本,结果一访问直接运行了。 -
排查命令 :
curl -I http://yoursite.com/uploads/1.php(看返回状态码和Content-Type) -
处理 :在Web服务器配置中,显式禁止上传目录执行脚本 。
nginx# Nginx配置示例:禁止uploads目录下执行PHP location ~* ^/uploads/.*\.(php|php5|jsp)$ { deny all; }[!WARNING] 生产环境风险:加这条配置后,一定要测试一下正常的图片上传和访问是否受影响,别把正则写错了导致全站图片403。
4. 前端校验绕过
- 现象 :前端页面用JS限制了只能传
.jpg,但黑客用Burp Suite抓包,把文件名改成1.php直接发过去,后端居然也接收了。 - 排查命令 :查Web日志,看该请求的
Content-Type和文件名,确认后端没做二次校验。 - 处理 :前端校验只是为了用户体验,绝对不能当安全措施! 后端必须重新校验扩展名和文件内容。
5. 配合解析漏洞
-
现象 :传了
1.php.jpg,在老版本IIS下被当成PHP解析;或者传了.htaccess/.user.ini,改变了目录的解析规则,导致普通图片被当脚本执行。 -
排查命令 :
bash# 查有没有上传这些特殊配置文件 find /var/www/uploads -name ".htaccess" -o -name ".user.ini" -o -name "web.config" -
处理 :白名单里绝对不要 放行
.htaccess、.user.ini等配置文件后缀;及时升级中间件修复解析漏洞。
6. 批量上传(自动化工具)
-
现象 :同一个IP或IP段,短时间内高频发起上传请求,User-Agent可能是
Burp、sqlmap或空。 -
排查命令 :
bash# 统计上传接口访问最频繁的IP grep "upload" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -n 10 -
处理 :上传接口必须加图形验证码 或滑块验证;对高频IP限流;WAF开启防自动化扫描策略。
7. 上传文件被用来钓鱼或挂马(存储型)
- 现象 :黑客传了个带有恶意宏的
.docx,或者伪造的.exe、假PDF,诱导其他用户下载运行。 - 排查命令:查下载日志,看哪些用户下载了这些文件;提取文件Hash去微步在线/ VirusTotal 查杀。
- 处理 :文件存储到OSS或独立域名,不要和主站同域(防止Cookie被偷);接入云沙箱或杀毒引擎,上传后异步扫描,有毒直接删。
8. 上传即WebShell(上传入口就是后门入口)
-
现象:传了冰蝎、哥斯拉、蚁剑的Shell,流量特征明显(如特定的加密Payload,或者固定的密码参数)。
-
排查命令 :
bash# 查流量里有没有WebShell连接特征(以哥斯拉为例,查特定参数名和Base64特征) grep -iE "pass=|pwd=|antSword|Behinder|Godzilla" /var/log/nginx/access.log -
处理:按主机入侵处置。清除WebShell,排查系统账号、计划任务、SSH公钥有没有被篡改,修复上传漏洞。
四、 处置与修复:分场景给策略
第一档:隔离(停上传功能/禁止目录执行)
- 如果攻击正在发生,立刻在网关层把上传接口封掉,或者在Nginx层把上传目录的脚本执行权限干掉(参考上面的Nginx配置)。
- 把上传目录的权限改为
755或750,属主设为www,绝对不要给777。
第二档:清除(删恶意文件)
-
先取证! 把恶意文件拷贝到隔离区(如
/tmp/evidence/),记录好文件Hash、大小、修改时间。 -
然后批量删除:
bash# 确认无误后,批量删除上传目录下的所有PHP文件 find /var/www/uploads -type f -name "*.php" -delete[!WARNING] 生产环境风险:执行-delete前,一定要先用-ls打印出来看看,别把正常业务的PHP文件(如果有的话)给误删了。
第三档:修复(校验+存储策略)
- 修复优先级 :能直接传
.php并执行的 > 能传图片马的 > 只能传文件但不能执行的。 - 修复后验证 :用各种绕过Payload(
.php5、.phtml、图片马、.htaccess)重新传一遍,确认全部被拦截。
如果恶意文件已执行 :
别光删文件了,直接走主机入侵处置流程:查权限维持(有没有留后门账号)、查横向移动(有没有扫内网)、查数据影响(有没有拖库)。
五、 根因分析:到底是怎么漏的
用日志时间线+文件mtime+代码 git blame,一抓一个准:
- 只校验扩展名不校验内容:后缀对了,里面是啥不管,图片马就是这么进来的。
- 黑名单过滤可绕过 :只禁了
.php,没禁.php5、.phtml。 - 上传目录可执行脚本:Web服务器没配置禁止上传目录解析脚本。
- 存储与执行未分离:上传的文件和Web代码放在同一个域名、同一个目录下,一旦传了脚本就能直接访问执行。
- 文件类型判断不可靠 :只信前端传的
Content-Type(image/jpeg),或者只看了文件头,没做深度检测。 - 前端校验被当安全措施:以为加了JS限制就万事大吉,后端直接"裸奔"。
定位责任:拉出恶意文件写入磁盘的时间点,去Git里查对应上传接口文件的最后修改人,直接定位到具体开发。
六、 事后加固要点
吃一堑长一智,处置完必须做系统性加固:
- 白名单校验:扩展名白名单 + 文件内容深度检测 + 文件头校验,三管齐下。
- 随机文件名 :上传后的文件必须重命名(用UUID或时间戳+随机数),绝对不要保留用户原始文件名,防止文件名包含特殊字符导致解析漏洞或目录穿越。
- 上传目录禁止执行脚本:Nginx/Apache/Tomcat 必须配置禁止上传目录执行任何脚本。
- 存储与Web服务分离 :上传的文件存到OSS、CDN或独立的静态资源域名,不要和业务系统同域,从物理上切断执行路径。
- 图片类文件重编码处理:如果是图片,后端用GD库或ImageMagick重新读取并保存一次,洗掉所有附加代码。
- 访问控制:敏感的上传接口(如后台管理系统的文件上传)必须加严格的登录鉴权和RBAC权限控制。
- 防护规则:WAF开启文件上传防护规则,拦截常见的WebShell特征和危险后缀。
- 上传日志留存与告警:记录每次上传的操作人、IP、文件名、文件Hash。配置HIDS或云安全中心,上传目录出现新增脚本文件立刻报警。
七、 总结:处置过程中高频踩坑
最后,盘点几个咱们在现场经常踩的坑,大家引以为戒:
- 只删文件不修校验 :删了
1.php,没修代码,黑客换个名字传个2.php,继续拿权限。 - 黑名单绕过方式没堵全 :禁了
.php,没禁.php.(Windows)或.php::$DATA(IIS),被轻松绕过。 - 上传目录能执行脚本 :以为传到了
uploads目录就安全了,结果Nginx没配禁止解析,脚本照样跑得欢。 - 没查其他恶意文件:只清了告警报出来的那一个文件,没去扫整个目录,漏了黑客留的第二个后门。
- 文件类型判断只看后缀 :被
Content-Type: image/jpeg骗了,后端没做二次校验。 - 把前端校验当安全措施:前端JS限制形同虚设,抓包改个后缀直接传。
- 存储执行不分离:上传的文件直接放在Web根目录下,和代码混在一起,一旦传了脚本直接就能访问执行。
文件上传漏洞,核心就在于"永远不要信任用户上传的任何东西"。把上面这套排查和处置流程跑熟,下次遇到服务器被传了奇怪文件,照着做,快速止血,把损失降到最低。
觉得这篇复盘实用的话,点个赞、收藏一下,后续还会继续更新一线实战系列。有遇到过奇葩文件上传绕过手法的兄弟,欢迎评论区聊聊,咱们一起交流!