其他
当同一请求中重复 query/body…
适用于 CDN/WAF、反向代理、应用框架或内部 HTTP 客户端对重复 query/body 键的选中策略不一致,导致校验层与执行层读取不同值的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
当同一请求中重复 query/body 通用
解决思路
- 建立完整请求路径模型:`browser → CDN/WAF → reverse proxy → app framework → business code`,逐跳确认重复键(`a=1&a=2`)会被取第一个、取最后一个、逗号拼接还是转为数组。
- 当 WAF 与应用对哪个值生效不一致,或内部 HTTP 客户端重建查询字符串时,按 HPP 假设测试:安全检查读取一个参数出现,业务动作读取另一个参数出现。
- 基础载荷探测:`id=1&id=2`。
- 基础载荷探测:`id=1&id=1%20OR%201=1`。
- 基础载荷探测:`url=https://legit.example&id=https://evil.example`。
- 基础载荷探测:`amount=1&amount=9999`。
- 基础载荷探测:`csrf=TOKEN_A&csrf=TOKEN_B`。
- 基础载荷探测:`user=alice&user=admin`。
- POST body 重复测试:`application/x-www-form-urlencoded` 中发送 `id=1&id=2`。
- POST body 重复测试:`multipart/form-data` 中构造两个同名 `id` 字段,一个值 1,一个值 2(原文包含 `Content-Disposition: form-data; name="id"` 和两个 boundary 块)。
- 快速方法:用基线 `a=1&a=2` 指纹识别前端栈(CDN/WAF)与源站(语言/框架)。
- 快速方法:发送两种顺序:`a=1&a=2` 和 `a=2&a=1`,检查解析器是否对顺序敏感。
- 快速方法:如果是 JSON,测试重复键和 Content-Type 混淆。
- 确认服务器行为矩阵,但始终以实际环境为准;中间件和自定义解析器会覆盖默认行为。
- PHP / Apache(`$_GET`):通常取最后一个出现,`a=1&a=2` → `a=2`。
- ASP.NET / IIS:常把所有值逗号拼接,`a=1&a=2` → `a=1,2`。
- JSP / Tomcat(servlet param):通常取第一个出现,`a=1&a=2` → `a=1`。
- Python / Django(`QueryDict`):通常取最后一个出现,`a=1&a=2` → `a=2`。
- Python / Flask(`request.args`):通常取第一个出现,`a=1&a=2` → `a=1`。
- Node.js / Express(`req.query`):通常转为值数组,`a=1&a=2` → `a=['1','2']`(形状随解析器版本变化)。
- Perl / CGI:通常取第一个出现,`a=1&a=2` → `a=1`。
- Ruby / Rack(`Rack::Utils`):通常取最后一个出现,`a=1&a=2` → `a=2`。
- Go `net/http`(`ParseQuery`):通常取第一个出现,`a=1&a=2` → `a=1`。
- 利用差异:例如 IIS 上的 WAF 可能看到 `a=1,2`,而 PHP 后端只收到 `a=2`;若代理做规范化,也可能相反。
- 测试基本重复键:`GET /api?q=safe&q=evil HTTP/1.1`。
- 测试数组式(PHP/某些框架):`GET /api?id[]=1&id[]=2 HTTP/1.1`。
- 测试数组与标量混合:`GET /api?item[]=a&item=b HTTP/1.1`。
- 测试编码的 ampersand 造成解析器差异:`param=value1%26other=value2` 与 `param=value1&other=value2`。
- 测试嵌套/括号键:`GET /api?user[name]=a&user[role]=user&user[role]=admin HTTP/1.1`。
- 测试 JSON 重复键:`{"test":"user","test":"admin"}`,记录解析器保留最后一个、第一个还是其他;JavaScript `JSON.parse` 保留最后一个重复键。
- HPP + WAF bypass:尝试 WAF 检查第一个值、应用使用最后一个值的模式:`id=1&id=1%20UNION%20SELECT%20...`。
- HPP + WAF bypass:如果网关合并来源方式不同,还可把良性值放在 JSON 字段,把重复参数放在 query string。
- HPP + SSRF:构造校验器读取安全 URL、fetcher 读取内网/恶意 URL:`url=https://allowed.cdn.example/&url=http://169.254.169.254/`。
- HPP + SSRF:确认哪个组件(库 vs 应用)消费哪个参数出现。
- HPP + CSRF:仅在授权的 CSRF 评估且有明确状态改变目标时,用重复 anti-CSRF token 让一份满足解析器 A、另一份满足解析器 B:`csrf=LEGIT&csrf=IGNORED_OR_ALT`。
- HPP + 业务逻辑(如支付):测试 `amount=1&amount=5000`、`quantity=1&quantity=-1`、`price=9.99&price=0.01`。
- HPP + 业务逻辑:与 race conditions 或服务端舍入配合提高影响;HPP 单独常需跨层拆分解释。
- 使用 Burp Suite:在 Repeater 中于 raw query/body 重复键;用 Param Miner / 扩展找隐藏参数;比较响应判断 `first` vs `last` 解释。
- 使用 OWASP ZAP:用 Manual Request Editor;Automated Scan 可能不会深度 fuzz HPP,优先手动变体。
- 使用自定义脚本:构造精确 raw HTTP(保留顺序),因为一些客户端会规范化重复参数。
- 如果控制测试实验室,在应用侧记录 raw query strings;一些框架只暴露“获胜”值,而日志显示完整字符串。
- 决策树:遇到同一请求中重复参数名时,先分支为只有单一应用层,还是存在 WAF/CDN/proxy 链。
- 单一应用层:读框架文档,并测试 `a=1&a=2` 与交换顺序。
- WAF/CDN/proxy 链:映射每一跳的 first/last/join/array 行为。
- 选择攻击模板:WAF vs app value、SSRF split URL、CSRF token confuse、Logic numeric fields、JSON dup key parsers。
- 攻击模板 WAF vs app value:测试 WAF 与后端应用读取不同参数出现造成的绕过。
- 攻击模板 SSRF split URL:测试校验器与 fetcher 读取不同 URL 参数。
- 攻击模板 CSRF token confuse:测试重复 token 分别满足不同解析器。
- 攻击模板 Logic numeric fields:测试重复数值字段导致的业务逻辑差异。
- 攻击模板 JSON dup key parsers:测试 JSON 重复键在不同解析器中的保留策略。
- 在高影响请求前先记录解析器行为,避免在未知解析差异时直接触发状态变更。
适用边界 · 注意事项
- 未获得明确授权的真实目标上不要运行 HPP 测试。
- 目标仅单一应用层且已确认重复参数按同一规则解析,且没有 WAF/代理/内部 HTTP 客户端重建查询字符串的差异时,跨层 HPP 绕过通常不适用。
- 涉及支付、账户设置等高影响状态变更时,若没有限定账户并提前记录解析器行为,不应运行测试。