浅谈常见的文件上传的检测方式与绕过方法
字数 2005 2025-08-26 22:12:02
文件上传漏洞检测与绕过技术详解
前言
文件上传漏洞是渗透测试中最直接有效的攻击方式之一,攻击者通过上传恶意文件可直接获取webshell。本文将全面分析常见的文件上传检测机制及相应的绕过方法。
前端检测与绕过
JavaScript检测
检测原理:
前端通过JavaScript验证文件扩展名,通常检查文件后缀是否在白名单内。
示例代码:
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
var allow_ext = ".jpg|.png|.gif";
var ext_name = file.substring(file.lastIndexOf("."));
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
绕过方法:
- 使用Burp Suite等工具拦截并修改上传请求
- 直接禁用浏览器JavaScript功能
- 修改前端HTML代码移除验证逻辑
后端检测与绕过
1. 文件类型检测
1.1 检测Content-Type
检测原理:
检查HTTP请求头中的Content-Type字段,如image/jpeg、image/png等。
示例代码:
$allow_content_type = array("image/gif", "image/png", "image/jpeg");
$type = $_FILES["myfile"]["type"];
if (!in_array($type, $allow_content_type)) {
die("File type error!<br>");
}
绕过方法:
- 拦截请求修改Content-Type为允许的类型(如
image/jpeg)
1.2 检测文件头
检测原理:
使用getimagesize()等函数读取文件真实类型,检查文件头标志。
常见文件头:
- GIF:
47 49 46 38 39 61(GIF89a) - JPEG:
FF D8 FF - PNG:
89 50 4E 47 0D 0A
示例代码:
$allow_mime = array("image/gif", "image/png", "image/jpeg");
$imageinfo = getimagesize($_FILES["myfile"]["tmp_name"]);
if (!in_array($imageinfo['mime'], $allow_mime)) {
die("File type error!<br>");
}
绕过方法:
- 使用十六进制编辑器在恶意文件前添加图片文件头
- 制作图片马(将代码插入图片元数据中)
2. 文件扩展名检测
2.1 黑名单检测
检测原理:
禁止特定危险扩展名(如php、asp、jsp等)的文件上传。
示例代码:
$blacklist = array('php', 'asp', 'aspx', 'jsp');
$type = array_pop(explode('.', $_FILES['myfile']['name']));
if (in_array(strtolower($type), $blacklist)) {
die("File type errer!<br>");
}
绕过方法:
- 使用替代扩展名:
- PHP:
.php3,.php4,.php5,.phtml - ASP:
.asa,.cer,.cdx - JSP:
.jspx
- PHP:
- 大小写混淆:
.pHp,.AsP - 特殊字符:
- 空格:
shell.php - 点号:
shell.php. ::$DATA:shell.php::$DATA
- 空格:
- 双扩展名:
shell.jpg.php
2.2 白名单检测
检测原理:
只允许特定安全扩展名(如jpg、png等)的文件上传。
示例代码:
$whitelist = array('png', 'jpg', 'jpeg', 'gif');
$type = array_pop(explode('.', $_FILES['myfile']['name']));
if (!in_array(strtolower($type), $whitelist)) {
die("File type errer!<br>");
}
绕过方法:
- 结合%00截断(需PHP<5.3.4且magic_quotes_gpc关闭)
- 利用服务器解析漏洞
- 上传图片马配合文件包含漏洞
- 上传.htaccess文件控制解析规则
3. 文件内容检测
3.1 内容替换过滤
检测原理:
替换文件内容中的危险字符(如PHP标签<?)。
示例代码:
$content = file_get_contents($_FILES['myfile']['tmp_name']);
$content = str_replace('?', '!', $content);
file_put_contents($file, $content);
绕过方法:
- 使用替代PHP标签:
<script language='php'>system('ls');</script> - 使用短标签:
<?= system('ls'); ?>(需short_open_tag开启)
3.2 图片二次渲染
检测原理:
使用GD库等重新生成图片,过滤嵌入的恶意代码。
示例代码:
$im = imagecreatefromjpeg($target_path);
imagejpeg($im,$img_path);
绕过方法:
- 将代码插入图片EXIF等元数据区域
- 使用特定工具生成绕过二次渲染的图片马(如jpg_payload.php)
服务器解析漏洞利用
1. IIS解析漏洞
IIS 6.0
- 目录解析:
/xxx.asp/1.jpg(xxx.asp目录下的所有文件都作为ASP解析) - 分号解析:
test.asp;.jpg(被当作ASP文件解析)
IIS 7.0/7.5
- PHP CGI解析漏洞:
http://test.com/a.jpg/.php(需cgi.fix_pathinfo=1)
2. Apache解析漏洞
扩展名解析特性
- 从右向左解析:
a.php.xxx(xxx不可识别,向左识别为php) - 可绕过黑名单检测
CVE-2017-15715
- 上传文件名包含换行符:
a.php\x0A - 可绕过黑名单正则匹配
3. %00截断
利用条件:
- PHP < 5.3.4
- magic_quotes_gpc关闭
示例:
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
// 传入save_path="../upload/shell.php%00"
绕过方法:
- POST传参:使用Burp Suite修改hex值为00或URL解码%00
- GET传参:直接传入%00(浏览器自动URL解码)
4. .htaccess利用
利用条件:
- Apache配置AllowOverride All
- 可上传.htaccess文件
配置方式:
- 指定文件名解析:
<FilesMatch "test">
SetHandler application/x-httpd-php
</FilesMatch>
- 指定扩展名解析:
AddType application/x-httpd-php .jpg
防御建议
- 使用白名单而非黑名单
- 文件重命名(避免用户控制文件名)
- 限制上传目录执行权限
- 检查文件真实类型(MIME+扩展名+内容)
- 对上传文件进行病毒扫描
- 及时更新服务器软件修补解析漏洞
总结
文件上传漏洞的检测与绕过是攻防对抗的典型场景,实际环境中往往需要结合多种技术手段。渗透测试时应先进行充分的信息收集,了解服务器环境、脚本语言版本等,再选择适当的绕过方法。防御方则应采取多层次防护措施,避免单一检测机制被绕过。