1. 文件上传漏洞攻防实战笔记
作为一名长期从事Web安全研究的从业者,我经常遇到各种文件上传漏洞的实战场景。今天要分享的是基于iwebsec靶场的七种典型文件上传绕过手法,这些技术在实际渗透测试中具有极高的实用价值。文件上传漏洞位列OWASP Top 10,是Web应用中最危险的安全问题之一,攻击者利用该漏洞可直接获取服务器控制权。
在开始前需要明确:本文所有测试均在授权环境下进行,旨在帮助开发者和安全人员理解防御原理。我们将从最简单的客户端校验绕过开始,逐步深入到条件竞争等高级技巧,每种手法都会配合靶场源码和Burp Suite实操截图进行详解。
2. 前端JS校验绕过
2.1 漏洞原理分析
这是最基础的文件上传漏洞类型,关键缺陷在于仅依赖前端JavaScript进行文件类型校验。查看靶场HTML源码会发现类似这样的校验逻辑:
javascript复制function checkFile() {
var file = document.getElementById("upfile").value;
if (!/\.(jpg|png|gif)$/.test(file)) {
alert("仅允许上传图片文件!");
return false;
}
}
这种校验存在致命问题:攻击者通过Burp Suite等工具拦截请求后,可直接修改文件后缀名。因为服务器端未做任何校验,导致任意文件上传成为可能。
2.2 实战绕过步骤
- 准备一个包含恶意代码的test.php文件
- 上传时使用Burp Suite拦截HTTP请求
- 修改filename参数为"shell.php"
- 放行请求完成上传
关键提示:现代浏览器开发者工具也能直接禁用JavaScript,但Burp Suite更适用于复杂场景
2.3 防御方案
必须实施服务端校验:
php复制$allowed = ['jpg', 'png'];
$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
if (!in_array(strtolower($ext), $allowed)) {
die("非法文件类型!");
}
3. 文件名黑名单绕过
3.1 漏洞代码解读
当开发者使用简单的黑名单过滤时(如下列代码),存在多种绕过方式:
php复制$type = substr($name, strrpos($name, '.')+1);
if($type == "php") {
die("禁止上传PHP文件!");
}
3.2 六种绕过技巧
- 大小写变异:pHp、PhP等
- 特殊后缀:php5、phtml、phps
- 双重后缀:shell.php.jpg
- 空字节注入:shell.php%00.jpg
- 点号截断:shell.php......(Windows特性)
- 空格截断:shell.php (末尾空格)
实测发现:Windows系统对文件名解析更为宽松,上述手法成功率更高
3.3 终极防御方案
采用白名单机制+强制小写转换:
php复制$allowed = ['jpg', 'png'];
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if (!in_array($ext, $allowed)) {
die("非法文件类型!");
}
4. Content-Type校验绕过
4.1 检测原理分析
部分系统通过HTTP头的Content-Type字段校验文件类型:
php复制switch ($_FILES['file']['type']) {
case 'image/jpeg': $ok = true; break;
case 'image/png': $ok = true; break;
default: die("非法文件类型!");
}
4.2 绕过实操演示
- 上传PHP文件时Burp拦截请求
- 修改Content-Type为image/png
- 放行请求完成上传

4.3 防御深度建议
应结合多种校验方式:
- 文件头校验(magic number)
- 文件扩展名白名单
- 文件内容检测(如getimagesize())
5. 文件头校验绕过
5.1 文件头特征库
常见文件类型的魔术数字:
| 文件类型 | 文件头(HEX) |
|---|---|
| JPEG | FFD8FF |
| PNG | 89504E47 |
| GIF | 47494638 |
| ZIP | 504B0304 |
5.2 使用010 Editor构造
- 用010 Editor打开正常图片
- 在文件末尾添加PHP代码
- 保持原始文件头不变
- 保存为shell.php.jpg
经验之谈:PHP的exif_imagetype()函数就是检测文件头,但可以被伪造
5.3 防御方案升级
应进行完整文件内容校验:
php复制if (!@imagecreatefromstring(file_get_contents($_FILES['file']['tmp_name']))) {
die("非法的图片文件!");
}
6. .htaccess攻击手法
6.1 攻击原理
通过上传.htaccess文件修改Apache解析规则:
htaccess复制AddHandler application/x-httpd-php .jpg
6.2 完整攻击链
- 上传恶意.htaccess文件
- 上传包含PHP代码的jpg文件
- 访问jpg文件时会被当作PHP执行
6.3 服务器防护
禁用上传目录的.htaccess生效:
apache复制<Directory "/var/www/uploads">
AllowOverride None
</Directory>
7. 条件竞争漏洞
7.1 漏洞产生流程
text复制上传文件 -> 保存到临时目录 -> 校验文件 -> 删除非法文件
\___________________________/
竞争窗口
7.2 自动化攻击脚本
使用Python多线程快速请求:
python复制import requests
import threading
def upload():
files = {'file': open('shell.php', 'rb')}
requests.post('http://target/upload.php', files=files)
def access():
while True:
r = requests.get('http://target/uploads/shell.php')
if r.status_code == 200:
print("Success!")
break
threads = [threading.Thread(target=upload),
threading.Thread(target=access)]
[t.start() for t in threads]
7.3 终极防御方案
采用原子化操作:
- 先校验后移动
- 使用随机临时文件名
- 设置严格的目录权限
8. 文件上传安全体系
根据OWASP建议,完整的防护应包含:
-
前端防护:
- 文件类型提示
- 大小限制提醒
-
服务端防护:
- 白名单校验(扩展名、Content-Type、文件头)
- 病毒扫描(ClamAV等)
- 文件重命名(避免目录遍历)
- 权限控制(不可执行)
-
系统层防护:
- 单独的上传域名
- 容器化隔离
- 文件存储到CDN
在实战中发现,90%的文件上传漏洞都源于开发者过度信任客户端提交的数据。最有效的防御策略就是遵循"永不信任、始终验证"的原则,对上传文件实施层层校验。