文件上传漏洞是指用户上传了一个可执行脚本文件,并通过此文件获得了执行服器端命令的能力。在大多数情况下,文件上传漏洞一般是指上传 WEB 脚本能够被服务器解析的问题,也就是所谓的 webshell 问题。完成这一攻击需要这样几个条件,一是上传的文件能够被 WEB 容器执行,其次用户能从 WEB 上访问这个文件,最后,如果上传的文件被安全检查、格式化、图片压缩等功能改变了内容,则可能导致攻击失败。
move_uploaded_file()核心上传函数,若未验证文件名和内容,直接保存用户输入的文件名,可能导致恶意文件执行。
move_uploaded_file($_FILES['file']['tmp_name'], "uploads/" . $_POST['filename']);copy() / rename()若操作未经验证的用户文件名,可能覆盖敏感文件或写入恶意内容。
copy($_FILES['file']['tmp_name'], "uploads/" . $_FILES['file']['name']);file_put_contents()直接写入用户可控内容到文件,可能导致代码执行。
file_put_contents("uploads/" . $_POST['name'], $_FILES['file']['tmp_name']);$upload_dir = 'uploads/';
$target_file = $upload_dir . $_FILES['file']['name'];
move_uploaded_file($_FILES['file']['tmp_name'], $target_file);$deny_ext = array("php", "php5");
$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
if (!in_array($ext, $deny_ext)) {
move_uploaded_file(...);
}绕过方法:使用.phtml、.phar、.htaccess(Apache)或大小写如.PHP。
if ($_FILES['file']['type'] == 'image/jpeg') {
move_uploaded_file(...);
}绕过方法:伪造HTTP请求的Content-Type为image/jpeg,上传实际为PHP的文件。
$target = "uploads/" . $_GET['dir'] . "/" . $_FILES['file']['name'];- 双扩展名:shell.jpg.php(Apache可能解析为PHP)。
- 特殊扩展名:.php5、.phtml、.phar。
- 大小写混淆:.PHP、.PhP。
- 空格/点号结尾:shell.php.(Windows自动去除末尾点)。
- 添加图片头(如GIF89a)绕过内容检测。
- 利用Exif注释嵌入PHP代码。
在Apache服务器环境中,攻击者通过上传恶意.htaccess文件可篡改目录解析规则,将非可执行文件(如图片)强制解析为PHP脚本,从而绕过文件上传防护。
强制将.jpg文件作为PHP脚本解析。
AddType application/x-httpd-php .jpg
<FilesMatch "\.jpg$">
SetHandler application/x-httpd-php
</FilesMatch>
- Apache:上传shell.php.jpg配合.htaccess设置AddType application/x-httpd-php .jpg。
- Nginx:路径解析错误(如/uploads/shell.jpg/xxx.php被解析为JPG)。
快速访问临时文件(需结合文件包含漏洞)。