Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
cve-2026-69243-poc-aiohttp-smuggling — 通过被拒绝的 WebSocket 升级复现 aiohttp CWE-444 请求走私,附带 Python/Rust 载荷及 Docker 实验环境,演示代理访问控制绕过。 | Kitploit
工具/GitHubGitHub/jvbotelho/cve-2026-69243-poc-aiohttp-smuggling
Payload生成漏洞分析漏洞利用Web应用程序漏洞利用Web安全模糊测试
GitHubjvbotelho/cve-2026-69243-poc-aiohttp-smuggling

cve-2026-69243-poc-aiohttp-smuggling

通过被拒绝的 WebSocket 升级复现 aiohttp CWE-444 请求走私,附带 Python/Rust 载荷及 Docker 实验环境,演示代理访问控制绕过。

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
查看仓库网站
116天前尚未审核

CVE-2026-69243 — aiohttp 请求走私(CWE-444)

通过 aiohttp < 3.14.2 中被拒绝的 WebSocket 升级实现请求走私。 当反向代理转发 Connection: Upgrade + Upgrade: websocket 头时, 存在漏洞的 aiohttp 解析器会跳过请求主体,并将尾部字节解释为流水线请求——从而绕过边缘访问控制。

已在 aiohttp 3.14.2 中修复(提交 6ae358f)。

作者:João Victor Botelho(JV Botelho)— https://glitchedcat.com

60 秒快速运行

复制粘贴 Python 版本(零依赖,仅标准库):

root@kitploit:~
curl -O https://raw.githubusercontent.com/JVBotelho/cve-2026-69243-poc-aiohttp-smuggling/main/poc.py
python3 poc.py <proxy-host> <proxy-port> <backend-host>

或构建 Rust 版本(零依赖,仅标准库):

root@kitploit:~
git clone https://github.com/JVBotelho/cve-2026-69243-poc-aiohttp-smuggling
cd cve-2026-69243-poc-aiohttp-smuggling/poc
cargo build --release
./target/release/cve-2026-69243-poc <proxy-host> <proxy-port> <backend-host>

预编译二进制文件将通过发布工作流发布到 Releases。

两者都会生成 字节完全一致 的载荷(由 CI 一致性测试强制保证)。 如果实验环境正在运行:

root@kitploit:~
python3 poc.py nginx-upgrade 80 backend-vuln

预期输出:1 个 HTTP 响应(WebSocket upgrade rejected)。然后验证:

root@kitploit:~
# 后端处理了 2 个请求(/ws + 被走私的 /admin):
docker logs backend-vuln | grep -c '"path".*"/admin"'

# Nginx 只记录了 1 个请求(/ws):
docker exec nginx-upgrade cat /logs/nginx-upgrade.access.log | grep -c '/admin'

后端计数 > 0 且 Nginx 计数 = 0 即确认 CWE-444 拆分。此 PoC 发送单个 TCP 段——主体就是被走私的请求;Nginx 将其视为主体,aiohttp 将其视为第二个请求。

这证明了什么

  • 解析器混淆:aiohttp 3.14.1 的 _http_parser.pyx 在主体被消费之前检测到升级时返回 2(跳过主体)(约第 863 行)。主体字节保留在 _message_tail 中,并在 web_protocol.py 的 finish_response(约第 771 行)中被重新喂给解析器。
  • CWE-444 拆分:前端看到 1 个带主体的请求;后端看到 2 个流水线请求。日志中的请求计数不一致。
  • 访问控制绕过:当 Nginx 配置了 location /admin { deny all; } 时,被走私的 /admin 仍然会到达后端,因为 Nginx 的路由决策仅基于外部请求。
  • 没有处理器级修复:在 3.14.1 中,await request.read() 在升级请求上返回 0 字节——主体被保留在处理器层之下。请打补丁,或在代理上对不允许切换协议的路由剥离升级头。

完整实验环境

root@kitploit:~
git clone https://github.com/JVBotelho/cve-2026-69243-poc-aiohttp-smuggling
cd cve-2026-69243-poc-aiohttp-smuggling
docker compose up -d

# 运行 PoC:
docker compose run --rm --entrypoint /app/poc attacker nginx-upgrade 80 backend-vuln

服务:

完整的第一至三阶段发现见 findings/。

局限性(如实说明)

  • 代理必须转发升级头。 向后端发送 Connection: close 或剥离 Connection/Upgrade 头的 Nginx 配置不受影响。暴露该拆分的配置是 Nginx 自身代理文档中的标准 WebSocket map 片段。
  • 被走私的响应会被代理吸收。 在演示的 Nginx 链路中,攻击者只会收到外部 /ws 响应。走私的证据在后端日志中,而不在攻击者响应中——在该拓扑中这是一种盲目的单向原语。未测试其他代理拓扑。
  • 分块传输框架在效果上是 CL 特有的。 直接针对 aiohttp,Transfer-Encoding: chunked 不会走私——原始块大小行(例如 3e)作为无效方法命中解析器,连接随即终止。通过 Nginx 则有效,但通过规范化实现:Nginx 对主体去分块并转发合成的 Content-Length,因此后端是通过相同的 CL 路径被利用的。--chunked 标志演示了代理路径。
  • 需要一个拒绝 WebSocket 升级的端点。 处理器必须返回非 WebSocketResponse 的响应。大多数在路由上不使用 WebSocket 的应用会默认拒绝(框架返回 404 或落到下一个处理器)。

文件

root@kitploit:~
poc/                       # Rust cargo 项目
├── Cargo.toml
├── src/main.rs            # CLI 二进制
├── src/lib.rs             # 库 + 单元测试
├── tests/parity.rs        # 跨语言载荷一致性测试
└── fuzz/                  # cargo-fuzz 目标
poc.py                     # Python PoC(从博客复制粘贴)
attacker/ backend/ frontend/   # Docker 实验服务
docker-compose.yml         # 7 服务实验环境
findings/                  # 研究笔记(第一阶段至第三阶段)
.github/workflows/
├── ci.yml                 # 构建、测试、clippy、一致性、集成、fuzz
└── release.yml            # 交叉编译 + GitHub Release

检测

完整分析见 findings/fase3-deteccao.md。总结如下,并附上生产环境中真正重要的注意事项:

  1. 请求计数不一致(后端 > 前端)出现在同一条连接上。注意后端记录的是代理的 IP,而不是客户端的——关联需要规范化 X-Forwarded-For/代理协议,或记录上游连接 ID + 每连接请求序列。仅凭客户端 IP + 时间窗口是较弱的(NAT、keep-alive、并发)。
  2. 后端请求在前端无匹配:后端日志中出现受限路径,而前端访问日志中没有对应条目。过滤内部子网(绕过代理的健康检查会产生误报)。
  3. 升级被拒绝 + 同一客户端在约 100 毫秒内访问不同路径。 置信度中等——合法的流水线也会产生类似间隔;实验日志记录器不记录远程端口/连接 ID,因此“没有新的 TCP 握手”并不是这些数据能证明的。
  4. 主体被扣留的中间件(content_length 与 request.read() 返回的字节数对比):在 3.14.1 上会触发,在 3.14.2 上静默。可检测,但不能缓解。需要限定范围(可能是升级的路由、较小的主体、非 101 状态)——朴素的实现会把每个主体都缓冲在内存中。
  5. WebSocket 端点上边缘 reqlen 高于头部基线 —— 单独来看置信度较低(cookie/JWT/追踪头噪声很大),但当客户端不发送 Content-Length(分块入口)时,这是唯一的边缘信号。
下载工具
容器用途
backend-vulnaiohttp 3.14.1(存在漏洞),READ_BODY=false
backend-vuln-readaiohttp 3.14.1,READ_BODY=true(证明处理器无法帮助)
backend-patchedaiohttp 3.14.2(已修复)
nginx-upgrade转发升级头(对 /admin 执行 deny all)
nginx-default不转发升级头(消除该 bug)
nginx-stripConnection "" 剥离(消除该 bug)
attackerRust 二进制:reproduce、fase2、poc