文件上传绕过
后缀校验、内容校验、解析差异——绕过成立的根本原因,是两套解析器读同一个字段。
绕过成立的根本原因
不是「过滤写得不够严」,是两套解析器对同一段内容的读法不一样。
WAF 读 filename 字段,用一套 RFC 解析;应用服务器读同一个字段,用另一套。两边读出来的后缀不同,绕过就成立了。这跟 XSS 的编码绕过是同一类问题:过滤器和解释器的理解不一致。
记住这句话,比记住 payload 有用。
后缀校验的几种绕法
shell.jsp → 直接拦
shell.jspx → 拦(黑名单里有)
shell.jsp;.jpg → 可能过
shell.jsp%00.jpg → 可能过(老版本 PHP)
shell.jsp:.jpg → Windows 下可能过
shell.jsp/ → 可能过
shell.pHp → 大小写
shell.php5 .phtml .pht → 别名后缀
; 这一条来自一个实际案例:WAF 取整个 filename 字段,看到后缀是 .jspx;.jpg,不在黑名单里就放过;而 Tomcat 解析到 ; 就停止,认为文件名是 shell.jspx。两边都「正确」,结果就是绕过。
内容校验
后缀过了还有内容检测。常见的是检查文件头(magic bytes)和图片二次渲染。
- 文件头:在 webshell 前面加
GIF89a,或者用图片马(正常图片末尾追加 PHP 代码)。 - 二次渲染:图片被 GD 重新生成,追加的代码会被清掉。这种情况要找渲染后仍保留的区域,比如调色板、EXIF 注释段。
- 解析漏洞:Apache 的
shell.php.jpg会按 PHP 解析(多后缀),Nginx 的shell.jpg/x.php也有类似问题,IIS 6 的shell.asp;.jpg同理。这些是配置问题,不是过滤问题。
传上去之后
上传成功不等于拿到 shell。要确认三件事:
- 文件落在哪个目录,这个目录能不能通过 URL 访问。
- 这个目录的脚本执行权限开没开。很多站点上传目录配了
php_flag engine off,传上去也只是个静态文件。 - 文件有没有被重命名。重命名成随机串的话,得先找到新路径。
什么时候不该继续
授权测试里,上传 webshell 这一步要提前确认。
多数授权书写的是「验证漏洞存在」,不是「获取服务器权限」。稳妥的做法是传一个只打印 phpinfo() 或执行 id 的文件,证明代码能执行,然后删掉。
真需要验证横向影响,先跟客户口头确认,留下记录。
修复
- 白名单后缀,且只认白名单。
- 上传目录禁止脚本执行。
- 文件重命名为随机串,不保留原后缀。
- 内容校验用文件头 + 真实解析,不要只看后缀。
- 上传目录和 Web 根目录分开,最好放到独立域名或对象存储。
参考
- 《几个有趣的 bypass 挖洞案例》,公众号 渗透安全HackTwo