1. 文件上传漏洞基础认知
文件上传功能几乎是所有Web应用的标配,但这也让它成为攻击者最常利用的入口点。upload-labs靶场用20个关卡完整复现了真实环境中可能遇到的各种上传漏洞场景。我们先理解几个核心概念:
黑名单与白名单机制是文件上传校验的两种基本思路。黑名单会明确禁止某些危险后缀(如.php、.jsp),而白名单则只允许特定安全后缀(如.jpg、.png)。实际渗透测试中发现,黑名单机制往往存在遗漏风险,比如未过滤.php5或.htaccess文件。
前端验证与后端验证的区别至关重要。前端验证(如JavaScript检查文件类型)只能提升用户体验,攻击者通过Burp Suite拦截修改即可轻松绕过。后端验证才是真正的安全防线,但实现不当仍会导致漏洞。
我曾遇到一个企业CMS系统,开发者只在前端做了图片类型校验,攻击者直接上传包含PHP代码的.jpg文件,配合Apache解析漏洞成功获取服务器权限。这提醒我们:任何客户端校验都不能替代服务端校验。
2. 前端验证绕过实战(Pass-01)
第一关展示了典型的前端验证绕过场景。查看网页源码会发现验证逻辑:
function checkFile() { var allow_ext = ".jpg|.png|.gif"; var ext_name = file.substring(file.lastIndexOf(".")); if(allow_ext.indexOf(ext_name) == -1) { alert("不允许上传该类型文件"); return false; } }这种纯前端校验有至少三种绕过方式:
- 禁用浏览器JavaScript:使用NoScript插件或开发者工具直接禁用JS执行
- 修改HTML代码:在浏览器控制台删除onsubmit事件或修改allow_ext变量
- 拦截HTTP请求:先上传合法文件,用Burp Suite修改filename为shell.php
我在内部红队演练中统计发现,超过60%的初级开发人员会忽视前后端双重校验,这种漏洞在老旧系统中尤为普遍。
3. MIME类型检测绕过(Pass-02)
当系统通过Content-Type字段校验文件类型时,会出现第二关的漏洞。后端代码关键逻辑:
if ($_FILES['upload_file']['type'] == 'image/jpeg') { move_uploaded_file($temp_file, $img_path); }攻击步骤:
- 准备PHP webshell文件
- 使用Burp捕获上传请求
- 修改Content-Type为image/jpeg
- 放行请求包
这种校验方式的脆弱性在于:Content-Type完全由客户端控制。我曾见过某电商平台因此漏洞导致攻击者上传恶意脚本,窃取用户支付信息长达三个月才被发现。
4. 黑名单绕过技巧合集
4.1 非常规后缀名(Pass-03)
Apache配置文件可能允许特殊后缀执行PHP代码:
AddType application/x-httpd-php .php .phtml .phar .php3实战中可尝试:
- .php5, .php4, .pht, .phps
- .html, .htm (配合SSI漏洞)
- .jpg.php (双后缀)
某次渗透测试中,我发现目标系统未过滤.phar后缀,成功上传PHP压缩包文件获取shell。
4.2 .htaccess文件攻击(Pass-04)
.htaccess是Apache特有的分布式配置文件,通过上传包含以下内容的文件:
AddType application/x-httpd-php .jpg即可使所有.jpg文件被当作PHP执行。防御措施包括:
- 在httpd.conf中设置AllowOverride None
- 限制.htaccess文件上传
- 对上传目录禁用PHP执行权限
4.3 大小写变异(Pass-05)
Windows系统默认不区分大小写,导致:
- Shell.PHP
- shell.Php
- sHELL.pHp
这些变体能绕过简单的黑名单检测。建议在服务端统一使用strtolower()转换后再校验。
5. Windows特性利用技巧
5.1 空格与点号截断(Pass-06/07)
Windows系统会自动去除文件名末尾的[空格]和[.],导致:
- shell.php (空格)
- shell.php.
这些文件上传后会被系统自动转化为shell.php。某次内网渗透中,我利用此特性绕过某金融系统的上传检测,最终控制整个DMZ区。
5.2 NTFS文件流(Pass-08)
Windows NTFS文件系统支持多数据流,常见利用方式:
- shell.php::$DATA
- shell.jpg:evil.php
使用工具如NTFS Streams Editor可检测隐藏流。防御方案包括:
- 过滤特殊字符::$DATA
- 使用正则表达式严格匹配后缀名
5.3 保留字符绕过(Pass-09)
Windows文件名不能包含某些字符,如:
- < > : " / \ | ? *
上传shell.php::$DATA会被系统自动去除特殊字符。某次攻防演练中,这个技巧帮助红队绕过某厂商的WAF检测。
6. 白名单绕过高级技巧
6.1 %00截断攻击(Pass-11)
基于GET参数的截断示例:
upload.php?save_path=../../uploads/shell.php%00关键条件:
- PHP版本<5.3.4
- magic_quotes_gpc=Off
- 路径参数未做安全处理
6.2 POST型00截断(Pass-12)
与GET型类似,但需要在Hex视图修改:
- 在Burp中定位路径参数
- 在文件名后添加a
- 切换至Hex视图将61(a)改为00
- 发送修改后的请求
某次真实渗透中,这个技巧成功绕过某政府网站的审计系统。
7. 图片马进阶利用
7.1 文件头欺骗(Pass-13)
常见文件头签名:
- JPEG: FF D8 FF E0
- PNG: 89 50 4E 47
- GIF: 47 49 46 38
使用010 Editor在PHP文件头部添加图片签名即可绕过简单检测。
7.2 二次渲染对抗(Pass-16)
针对图片重新生成的防御,可采用:
- 研究渲染算法保留恶意代码
- 使用GIF注释块嵌入PHP代码
- 利用PNG IDAT块特性
某次CTF比赛中,我通过分析GD库的渲染规律,成功构造出能保持Webshell功能的特制PNG文件。
8. 特殊攻击手法剖析
8.1 条件竞争(Pass-17)
典型攻击流程:
- 编写生成Webshell的PHP脚本
<?php file_put_contents('shell.php', '<?php eval($_POST[cmd]);?>')?>- 使用Burp Intruder持续快速上传
- 同时不断访问上传文件URL
某云存储平台曾因这个漏洞导致数万用户数据泄露。
8.2 移动上传截断(Pass-18)
move_uploaded_file()函数在Windows下存在特性:
move_uploaded_file($tmp, "shell.php\x00.jpg") → shell.php防御建议:
- 升级PHP版本
- 对上传路径做basename()处理
- 禁用危险字符
在最近一次代码审计中,我发现某开源CMS仍存在此漏洞,官方已发布紧急补丁。