一、文件上传漏洞概述文件上传漏洞(File Upload Vulnerability)是Web应用程序中常见的高危漏洞之一,攻击者通过上传恶意文件(如Webshell、恶意脚本、病毒等)来获取服务器控制权或执行任意代码。由于文件上传功能广泛应用于各类Web系统(如CMS、社交平台、企业OA系统等),一旦存在漏洞,往往会导致严重的安全问题。
二、文件上传漏洞的成因文件上传漏洞通常由以下原因导致:
未校验文件类型:仅依赖客户端(如JavaScript)检查文件扩展名,攻击者可绕过。黑名单过滤不完善:仅禁止.php、.jsp等扩展名,但未考虑.phtml、.php5等变种。MIME类型伪造:仅检查Content-Type(如image/jpeg),但攻击者可伪造该值。文件内容未检测:未检查文件内容是否真实匹配其扩展名(如GIF头部检测)。目录遍历漏洞:上传路径可控,攻击者可写入Web目录之外的位置(如../../../malicious.php)。解析漏洞:服务器错误解析文件(如Apache解析test.php.jpg为PHP)。条件竞争漏洞:上传后未及时删除临时文件,导致攻击者利用时间差执行恶意代码。三、 文件上传漏洞的利用方式1、绕过前端校验前端通常使用JavaScript检查文件扩展名,但攻击者可通过以下方式绕过:
禁用JavaScript(浏览器设置或Burp Suite拦截修改)。直接发送恶意请求(如使用curl或Python脚本上传)。示例:前端校验绕过
function validateFile(input) {
if (!input.value.endsWith('.jpg') && !input.value.endsWith('.png')) {
alert("仅允许JPG/PNG文件!");
input.value = "";
}
}
绕过方法:
使用Burp Suite拦截请求,修改文件名shell.php→ shell.jpg,再改回shell.php。2、绕过服务端黑名单如果服务端仅检查扩展名黑名单(如禁止.php),攻击者可尝试:
大小写绕过:shell.PHp(Windows不区分大小写)。双扩展名绕过:shell.php.jpg(Apache可能解析为PHP)。空字节截断(PHP 5.2以下):shell.php%00.jpg→ 服务器解析为shell.php。特殊扩展名:.phtml、.php5、.phar等。示例:黑名单绕过
$deny_ext = array("php", "jsp", "asp");
$filename = $_FILES['file']['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if (in_array($ext, $deny_ext)) {
die("禁止上传该类型文件!");
}
绕过方法:
上传shell.phtml(PHP仍可解析)。上传shell.php.(Windows自动去除末尾点)。3、绕过MIME类型检测部分系统仅检查Content-Type,攻击者可伪造:
POST /upload.php HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary123
------WebKitFormBoundary123
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: image/jpeg
防御方法:
应结合文件头检测(如GIF文件头部GIF89a)。4、利用解析漏洞某些Web服务器存在特殊解析逻辑:
Apache解析漏洞:shell.php.xxx可能被解析为PHP。IIS 6.0目录解析:/upload/shell.asp;.jpg→ 解析为ASP。Nginx畸形文件名:shell.jpg%00.php→ 截断解析。示例:Apache解析漏洞
上传文件:shell.php.jpg
服务器解析:仍执行PHP代码
(5) 条件竞争攻击(Race Condition)如果服务器先保存文件再检查,攻击者可利用时间差执行恶意代码:
import requests
while True:
r = requests.post("http://target/upload.php", files={"file": open("shell.php", "rb")})
if "success" in r.text:
requests.get("http://target/uploads/shell.php?cmd=id")
break
防御方法:
先检查再保存,或使用临时随机文件名。四、高级利用技巧1、结合XXE(XML外部实体注入)如果上传XML文件(如SVG),可尝试XXE攻击:
]>
2、结合文件包含(LFI/RFI)如果存在本地文件包含(LFI),上传.txt文件后包含执行。
// 存在LFI漏洞的代码
include($_GET['file']);
// 攻击者上传log.txt,内容为PHP代码
// 访问:/index.php?file=uploads/log.txt
3、上传.htaccess覆盖解析规则在Apache服务器上,可上传.htaccess文件强制解析任意文件为PHP:
AddType application/x-httpd-php .jpg
然后上传shell.jpg即可执行PHP代码。
五、防御方案白名单校验:仅允许指定扩展名(如.jpg, .png)。文件头检测:检查文件魔数(如GIF头部GIF89a)。重命名文件:使用随机文件名(如a3f8b.jpg)。存储到非Web目录:禁止直接访问上传文件。禁用危险函数:如exec()、system()。WAF防护:拦截恶意文件上传请求。六、总结文件上传漏洞危害极大,攻击者可借此获取服务器权限。防御需采用多层校验(扩展名+文件头+随机存储),并定期审计代码。企业应加强安全测试,避免因小失大。