文件上传漏洞是Web应用中常见的安全风险之一,攻击者通过上传恶意文件可能导致服务器被控制、数据泄露等严重后果。以下是几种典型的文件上传漏洞示例及分析:
漏洞代码示例(PHP):
<?php
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "文件 ". basename($_FILES["fileToUpload"]["name"]). " 上传成功";
} else {
echo "上传失败";
}
?>
漏洞分析: - 直接使用用户提供的文件名,无任何过滤 - 攻击者可上传.php、.jsp等可执行脚本文件 - 上传后可直接访问执行恶意代码
前端代码示例:
<input type="file" name="file" accept=".jpg,.png">
漏洞分析: - 仅依赖前端验证,攻击者可绕过前端限制直接发送POST请求 - 服务器端无任何验证机制 - 可上传任意类型文件
漏洞代码示例:
$denied_ext = array("php", "php5", "php4", "php3", "phtml", "jsp", "asp", "aspx");
$file_ext = pathinfo($_FILES["file"]["name"], PATHINFO_EXTENSION);
if (!in_array($file_ext, $denied_ext)) {
// 允许上传
}
漏洞分析: - 黑名单可能不完整(如遗漏.php7、.pht等) - 大小写绕过(.PhP、.PHP) - 特殊字符绕过(.php%00.jpg) - 双扩展名绕过(.jpg.php)
漏洞代码示例:
if ($_FILES["file"]["type"] == "image/jpeg") {
// 允许上传
}
漏洞分析: - 攻击者可伪造Content-Type头 - 实际文件内容与声明类型不符 - 例如上传PHP文件但设置Content-Type为image/jpeg
漏洞场景: - Apache/IIS/Nginx等服务器解析漏洞 - 例如:上传test.php.xxx,服务器可能仍按PHP解析
白名单验证:只允许特定扩展名
$allowed_ext = array("jpg", "png", "gif");
文件内容验证:检查文件头、MIME类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES["file"]["tmp_name"]);
重命名文件:使用随机生成文件名
$new_name = md5(uniqid()) . '.' . $file_ext;
设置权限:上传目录禁止执行脚本
chmod 755 uploads/
文件隔离:将上传文件存储在非Web目录或使用CDN
文件大小限制:防止DoS攻击
病毒扫描:对上传文件进行安全扫描
文件上传漏洞的防御需要多层防护,不能仅依赖单一验证机制。开发者应结合白名单验证、内容检查、重命名、权限控制等多种手段,才能有效降低安全风险。