文件上传及其bypass
字数 1878 2025-08-11 08:35:47

文件上传漏洞及其Bypass技术详解

1. 基础环境搭建

使用Docker部署upload-labs靶场环境:

docker pull c0ny1/upload-labs

2. 文件上传漏洞基础绕过技术

Pass-01: 前端JS验证绕过

漏洞分析
前端JavaScript验证文件类型,仅允许.jpg|.png|.gif扩展名。

绕过方法

  1. 直接修改前端代码或禁用JS
  2. 使用Burp Suite拦截请求并修改文件名

关键代码

function checkFile() {
    var file = document.getElementsByName('upload_file')[0].value;
    var allow_ext = ".jpg|.png|.gif";
    var ext_name = file.substring(file.lastIndexOf("."));
    if (allow_ext.indexOf(ext_name) == -1) {
        alert("该文件不允许上传");
        return false;
    }
}

Pass-02: Content-Type验证绕过

漏洞分析
服务器检查Content-Type是否为image/jpegimage/pngimage/gif

绕过方法

  1. 拦截请求修改Content-Type为允许的类型
  2. 在MacOS上,修改文件扩展名可能自动修改Content-Type

关键代码

if (($_FILES['upload_file']['type'] == 'image/jpeg') || 
    ($_FILES['upload_file']['type'] == 'image/png') || 
    ($_FILES['upload_file']['type'] == 'image/gif')) {
    // 允许上传
}

3. 黑名单绕过技术

Pass-03: 非常规PHP扩展名绕过

漏洞分析
黑名单包含.asp,.aspx,.php,.jsp,但未包含其他PHP变种扩展名。

绕过方法
使用不常见的PHP扩展名:

  • .php5, .php4, .php3, .php2, .php1
  • .phtml, .pht, .pHp (大小写变种)

关键代码

$deny_ext = array('.asp','.aspx','.php','.jsp');

Pass-04: .htaccess文件上传

漏洞分析
黑名单包含常见PHP扩展名但未包含.htaccess

绕过方法

  1. 上传.htaccess文件设置解析规则:
AddType application/x-httpd-php .abc
  1. 然后上传包含PHP代码的.abc文件

关键代码

$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");

4. Windows特性利用

Pass-06: 空格绕过

漏洞分析
黑名单检查但未处理文件名末尾空格。

绕过方法
在扩展名后添加空格:shell.php

关键代码

$file_name = trim($_FILES['upload_file']['name']);
$file_ext = strrchr($file_name, '.');

Pass-07: 点号绕过

漏洞分析
Windows会自动去除文件名末尾的点。

绕过方法
在扩展名后添加点:shell.php.

关键代码

$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name); // 删除末尾点

Pass-08: ::$DATA绕过

漏洞分析
Windows会忽略NTFS文件流标识::$DATA

绕过方法
使用shell.php::$DATA作为文件名。

关键代码

$file_ext = str_ireplace('::$DATA', '', $file_ext);

Pass-09: 点号空格点号绕过

漏洞分析
多重过滤后仍可构造特殊文件名。

绕过方法
使用shell.php. .作为文件名。

5. 其他高级绕过技术

Pass-10: 双写绕过

漏洞分析
直接替换黑名单扩展名为空字符串。

绕过方法
双写扩展名:shell.pphphp

关键代码

$file_name = str_ireplace($deny_ext,"", $file_name);

Pass-11/12: %00截断

漏洞分析
PHP旧版本(<=5.3.4)的magic_quotes_gpc=Off时可利用空字节截断。

绕过方法

  1. GET型:shell.php%00.jpg
  2. POST型:shell.php + Hex编辑器中修改为shell.php\x00.jpg

关键代码

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

Pass-13-16: 图片马与文件包含

技术要点

  1. 制作图片马:copy /b test.png + shell.php webshell.png
  2. 配合文件包含漏洞执行
  3. 对于二次渲染(Pass-16),需找到未被修改的部分插入代码

Pass-17/18: 竞争条件

漏洞分析
先保存文件后检查,存在时间差。

利用方法

  1. 快速重复请求上传文件
  2. 使用Python脚本检测文件是否上传成功

示例脚本

import requests
url = "http://target/upload/shell.php"
while True:
    html = requests.get(url)
    if html.status_code == 200:
        print("Success!")
        break

Pass-19: CVE-2015-2348

漏洞分析
move_uploaded_file()函数存在00截断问题。

利用方法
使用截断文件名:shell.php%00.jpg

Pass-20: 数组绕过

漏洞分析
通过数组形式传递文件名绕过检查。

利用方法
修改上传表单为数组形式:name="upload_file[]"

6. 防御建议

  1. 使用白名单而非黑名单
  2. 文件重命名(不使用用户提供的文件名)
  3. 限制上传目录的执行权限
  4. 检查文件内容而不仅依赖扩展名
  5. 对图片文件进行二次渲染
  6. 设置upload_max_filesizepost_max_size限制
  7. 及时更新PHP版本,修复已知漏洞

7. 总结

文件上传漏洞的绕过技术多种多样,攻击者会利用:

  • 前端验证不严格
  • 后端黑名单不完整
  • 服务器特性(如Windows特性)
  • PHP版本漏洞(如%00截断)
  • 竞争条件等时间差问题

防御需要采取多层次的安全措施,不能仅依赖单一防护手段。

文件上传漏洞及其Bypass技术详解 1. 基础环境搭建 使用Docker部署upload-labs靶场环境: 2. 文件上传漏洞基础绕过技术 Pass-01: 前端JS验证绕过 漏洞分析 : 前端JavaScript验证文件类型,仅允许 .jpg|.png|.gif 扩展名。 绕过方法 : 直接修改前端代码或禁用JS 使用Burp Suite拦截请求并修改文件名 关键代码 : Pass-02: Content-Type验证绕过 漏洞分析 : 服务器检查 Content-Type 是否为 image/jpeg 、 image/png 或 image/gif 。 绕过方法 : 拦截请求修改 Content-Type 为允许的类型 在MacOS上,修改文件扩展名可能自动修改 Content-Type 关键代码 : 3. 黑名单绕过技术 Pass-03: 非常规PHP扩展名绕过 漏洞分析 : 黑名单包含 .asp,.aspx,.php,.jsp ,但未包含其他PHP变种扩展名。 绕过方法 : 使用不常见的PHP扩展名: .php5 , .php4 , .php3 , .php2 , .php1 .phtml , .pht , .pHp (大小写变种) 关键代码 : Pass-04: .htaccess文件上传 漏洞分析 : 黑名单包含常见PHP扩展名但未包含 .htaccess 。 绕过方法 : 上传 .htaccess 文件设置解析规则: 然后上传包含PHP代码的 .abc 文件 关键代码 : 4. Windows特性利用 Pass-06: 空格绕过 漏洞分析 : 黑名单检查但未处理文件名末尾空格。 绕过方法 : 在扩展名后添加空格: shell.php 关键代码 : Pass-07: 点号绕过 漏洞分析 : Windows会自动去除文件名末尾的点。 绕过方法 : 在扩展名后添加点: shell.php. 关键代码 : Pass-08: ::$DATA绕过 漏洞分析 : Windows会忽略NTFS文件流标识 ::$DATA 。 绕过方法 : 使用 shell.php::$DATA 作为文件名。 关键代码 : Pass-09: 点号空格点号绕过 漏洞分析 : 多重过滤后仍可构造特殊文件名。 绕过方法 : 使用 shell.php. . 作为文件名。 5. 其他高级绕过技术 Pass-10: 双写绕过 漏洞分析 : 直接替换黑名单扩展名为空字符串。 绕过方法 : 双写扩展名: shell.pphphp 关键代码 : Pass-11/12: %00截断 漏洞分析 : PHP旧版本(<=5.3.4)的 magic_quotes_gpc=Off 时可利用空字节截断。 绕过方法 : GET型: shell.php%00.jpg POST型: shell.php + Hex编辑器中修改为 shell.php\x00.jpg 关键代码 : Pass-13-16: 图片马与文件包含 技术要点 : 制作图片马: copy /b test.png + shell.php webshell.png 配合文件包含漏洞执行 对于二次渲染(Pass-16),需找到未被修改的部分插入代码 Pass-17/18: 竞争条件 漏洞分析 : 先保存文件后检查,存在时间差。 利用方法 : 快速重复请求上传文件 使用Python脚本检测文件是否上传成功 示例脚本 : Pass-19: CVE-2015-2348 漏洞分析 : move_uploaded_file() 函数存在00截断问题。 利用方法 : 使用截断文件名: shell.php%00.jpg Pass-20: 数组绕过 漏洞分析 : 通过数组形式传递文件名绕过检查。 利用方法 : 修改上传表单为数组形式: name="upload_file[]" 6. 防御建议 使用白名单而非黑名单 文件重命名(不使用用户提供的文件名) 限制上传目录的执行权限 检查文件内容而不仅依赖扩展名 对图片文件进行二次渲染 设置 upload_max_filesize 和 post_max_size 限制 及时更新PHP版本,修复已知漏洞 7. 总结 文件上传漏洞的绕过技术多种多样,攻击者会利用: 前端验证不严格 后端黑名单不完整 服务器特性(如Windows特性) PHP版本漏洞(如%00截断) 竞争条件等时间差问题 防御需要采取多层次的安全措施,不能仅依赖单一防护手段。