【免费下载链接】Decepticon
Autonomous Hacking Agent for Red Team
HTTP Parameter Pollution(HPP,HTTP 参数污染)是一类利用多层组件对同一重复参数解析结果不一致的攻击技术:当代理/WAF、Web 框架与应用代码对?id=1&id=2这类重复参数给出不同取值时,WAF 检查到的是"无害"的值,而应用实际读到的是"恶意"的值,载荷便得以穿透防护;同理,框架在鉴权时取一个值、执行动作时取另一个值,即可造成 ACL/认证绕过。本指南以 Decepticon 开源红队项目中的hpp技能文档(SKILL.md)为主体,完整覆盖从解析优先级指纹识别、WAF 绕过、服务端/客户端 HPP 利用、注入载荷投递到防御方检测签名的全流程,并给出可直接复制运行的 curl 命令与决策门(Decision Gate)。读完你将掌握:如何用响应回显指纹化目标技术栈、如何构造跨层参数差异载荷、何时应当升级为 SQLi/XSS 链式利用,以及防御侧该在哪里做规范化收敛。
1. 技术本质:两套解析器、两个世界
HPP 的核心前提非常简单:同一份 HTTP 请求中携带了同名参数的多个值(?id=1&id=2、id[]=1&id[]=2、id=1;id=2,或 GET/POST 同名混用),而请求路径上的不同组件——CDN、WAF、反向代理、Web 框架、应用代码——对"最终应该取哪个值"各自有独立的解析规则。
原技能文档开篇即点明利用模型:
Two layers (proxy/WAF, framework, app code) parse the same duplicate parameterdifferently. The WAF inspects one value, the app reads another — payload slips through. Or the framework picks one value for the auth check and a different one for the action — ACL bypass.
由此得到 HPP 的两个经典攻击面:
- WAF 绕过:WAF 只检查某一个出现位置的值(通常是第一个或最后一个),应用却取另一个位置的值(或拼接所有值),被规则拦截的关键字可以从"漏检位置"进入应用层;
- 鉴权/ACL 绕过:鉴权过滤器(filter/middleware)读取一个出现位置判断权限(如
account=mine),控制器(controller)却按另一个出现位置执行操作(如account=victim),形成"检查与执行不一致"。
从独立严重度看,HPP 通常只有 Low/Medium;但它作为放大器存在:与 SQLi、SSRF、XSS、认证绕过链式组合后可达 High/Critical。这正是 Decepticon 技能体系中将其归类为subdomain: execution(执行阶段)、并挂载mitre_attack: T1190(Exploit Public-Facing Application)的原因——它是初始访问与技术升级的载体,而不是终点。
2. 解析优先级速查表:指纹化目标技术栈
当收到?id=1&id=2(或重复的 body 参数)时,不同技术栈的取法完全不同。这是整个 HPP 方法论的基石,务必熟记:
| 技术栈 | request.GET['id']/ 等价 API | getParameterValues/ 列表视图 |
|---|---|---|
PHP($_GET) | 最后一个生效(2) | $_GET['id[]']才成数组;否则重复值被丢弃 |
ASP.NET(Request.QueryString["id"]) | 逗号拼接("1,2") | GetValues返回全部 |
| ASP Classic | 逗号拼接 | — |
Java Servlet(getParameter) | 第一个(1) | getParameterValues返回全部 |
Java Spring@RequestParam String | 第一个 | List<String>绑定全部 |
Node.jsqs(Express 默认) | 数组(["1","2"]) | n/a |
Node.jsquerystring(legacy) | 数组 | n/a |
Python Flaskrequest.args.get | 第一个 | getlist返回全部 |
Python Djangorequest.GET['id'] | 最后一个 | getlist返回全部 |
Pythonurllib.parse.parse_qs | 列表(["1","2"]) | — |
| Ruby on Rails | 最后一个 | params[:id]取最后一个;数组用id[]= |
Gonet/httpr.URL.Query().Get | 第一个 | ["id"]返回全部 |
Perl CGIparam("id") | 标量上下文取第一个,列表上下文返回列表 | — |
nginx$arg_id | 第一个 | — |
Apache mod_rewrite%{QUERY_STRING} | 原始串——两个值都保留 | — |
| AWS API Gateway → Lambda proxy | queryStringParameters取最后一个,multiValueQueryStringParameters返回全部 | — |
| Cloudflare WAF | 一般对所有值做规则匹配 | — |
| AWS WAF | 检查每一次出现 | — |
| ModSecurity(CRS) | 检查每一次出现——但异常分按规则计 | — |
可利用模式一句话概括:WAF/代理读到值 A,应用读到值 B(The exploitable pattern: WAF/proxy reads value A, app reads value B)。表中还隐藏着两个容易被忽略的细节:其一,ASP.NET 家族把重复值逗号拼接成一个字符串,这直接催生了第 6 节的"分段注入"手法;其二,同一语言内部 API 不同也可能不一致——例如 Java 的getParameter取第一个而getParameterValues返回全部,Flask 的args.get取第一个而getlist返回全部,Go 的Query().Get取第一个而["id"]返回全部——这意味着"框架层"与"代码层"之间本身就可能存在差异。
3. 检测:用响应回显指纹化解析器
检测阶段的思路是构造参数置换矩阵,观察响应如何回显。原技能文档给出的基线探测流程可直接照用:
# Baseline —— 单值基线 curl -s "http://<TARGET>/api?id=1" -o /dev/null -w 'HTTP %{http_code} %{size_download}B\n' # Duplicate param —— 同名重复 curl -s "http://<TARGET>/api?id=1&id=2" -o resp.dup -w 'HTTP %{http_code} %{size_download}B\n' cat resp.dup | head -c 300 # Bracket form —— PHP 数组形式 curl -s "http://<TARGET>/api?id[]=1&id[]=2" -o resp.arr -w 'HTTP %{http_code} %{size_download}B\n' # Whitespace / separator variants —— 分号分隔(PHP/Java 行为不同)、等号前空格、body 重复 curl -s "http://<TARGET>/api?id=1;id=2" # semicolon separator (PHP/Java differ) curl -s "http://<TARGET>/api?id=1&id =2" # space-before-= curl -s --data-urlencode 'id=1' --data-urlencode 'id=2' "http://<TARGET>/api" # body dup反射检查(Reflection check)是判断技术栈的关键判据:响应回显的是1、2、1,2,还是["1","2"]?这个回显形状本身就是对第 2 节速查表的一次"活体指纹":
for pair in 'id=1&id=2' 'id=2&id=1' 'id=1;id=2' 'id[]=1&id[]=2'; do echo "== $pair ==" curl -s "http://<TARGET>/echo?$pair" echo done注意循环中特意包含了id=1&id=2与id=2&id=1两个次序相反的探测——因为"先者生效"与"后者生效"只有在交换次序后回显不变时才能区分(first-wins 与 last-wins 在单次1&2探测中无法分辨)。这一"差分探测"思想在 Decepticon 的技能体系中被显式定义为独立的能力类别:blind-sqli技能(SKILL.md)同样依赖"两种页面状态可区分"的二元 oracle 逻辑,可见"用差分响应做判定"是该项目 Web 利用方法论的一贯范式。
4. WAF 绕过:让载荷从"漏检位置"进入应用
原理:WAF 只检查某一个出现位置,应用拼接或选择另一个位置的值。原文档给出三个按技术栈定制的最小 PoC:
# ASP.NET: WAF 看到第一个出现位置的值 "1",应用拼接后实际得到 "1,UNION SELECT ..." curl -G "http://<TARGET>/search" \ --data-urlencode "q=1" \ --data-urlencode "q=UNION SELECT user,password FROM users--" # PHP last-wins: 只有当 WAF 检查每一个值时才拦得住明显载荷 curl -G "http://<TARGET>/search" \ --data-urlencode "q=harmless" \ --data-urlencode "q=<svg/onload=alert(1)>" # Java first-wins, 而某些 WAF 设备只检查最后一个出现位置 curl -G "http://<TARGET>/cmd" \ --data-urlencode "host=' OR 1=1--" \ --data-urlencode "host=8.8.8.8"三个例子的取法组合覆盖了表格中最常见的三类场景:拼接型(.NET 逗号拼接,恶意段藏在第二个值里)、last-wins 型(PHP,恶意值放最后)、first-wins 型(Java 应用先者生效,而 WAF 只查最后一处)。关键点在于:必须先用第 3 节的反射检查确认"应用读哪个、WAF 查哪个",再决定恶意载荷放哪一侧。
混合来源混淆(GET vs POST)是另一类解析器差异——部分框架会把 GET 与 POST 参数合并进同一个参数字典,其合并优先级与 WAF 的检查顺序不同:
# 一些框架将 GET+POST 合并进同一个 params 字典;合并优先级与 WAF 检查顺序不一致 curl -X POST "http://<TARGET>/api?role=user" \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data 'role=admin'在 Decepticon 的技能体系中,HPP 被明确视为 WAF 绕过技能树的一员:Web 类目路由技能 web/SKILL.md 的 Routing 表指向各专项技能;而 waf-bypass/SKILL.md 在 "HTTP-level evasion" 一节中直接把参数污染列为 3.8 号绕过手段并交叉引用到本技能("Param pollution — WAF inspects first, app reads last (or concat)")。反过来,HPP 技能也把 waf-bypass 列为第一交叉引用。二者互为姊妹篇,构成"载荷混淆 + 解析器差异"的双通道绕过组合。
5. 服务端 HPP:认证 / ACL 绕过
当鉴权层评估一个值、控制器作用于另一个值时,HPP 就从 WAF 绕过升级为访问控制漏洞。原技能文档给出三个经典模式:
# 模式一:过滤器读第一个,动作读最后一个(filter reads first, action reads last) curl "http://<TARGET>/transfer?account=mine&account=victim&amount=100" # 过滤器:account==mine → 放行。控制器:last-wins → 实际操作 victim 账户。 # 模式二:角色检查 vs 角色赋值 curl -X POST "http://<TARGET>/users/create" \ -d 'role=user&username=x&role=admin' # 模式三:租户作用域逃逸 curl "http://<TARGET>/api/orders?tenant_id=$MINE&tenant_id=$OTHER"这类漏洞的本质是TOCTOU 式的"检查-执行分离":安全检查(filter/middleware 读第一处)与业务执行(controller 读最后一处)各用各的取值,二者从未被保证一致。在 Python 系应用中,"filter 用request.args.get(first-wins)而业务用 Django 式request.GET['id'](last-wins)"正是这种不一致的教科书来源——即使同一框架内,不同 API 的取值策略也可能背道而驰(见第 2 节表内备注)。
这与 Decepticon 中姊妹技能 bfla/SKILL.md(Broken Function Level Authorization,动作级越权)的验证要求完全一致:必须有基线对比 + 持久状态变化 + 最小复现。对服务端 HPP 的 ACL 绕过,建议沿用 bfla 的验证纪律——先用高权限 token 打基线确认动作本身可用,再用低权限 token 携带重复参数复现,最后用一次后续 GET 确认状态确实被改变(如account=victim的资金转移确实发生),避免把"响应相同"误判为"利用成功"。
6. 客户端 HPP:参数未重新编码的反射与重定向
客户端 HPP 的场景是:用户可控参数被重新发射进链接或重定向,且未对&重新编码。原技能文档的推演示例非常直观:
脆弱模板: <a href="/proxy?url=USER_INPUT&action=read"> 载荷: USER_INPUT = http://x.tld?evil=1 渲染链接: /proxy?url=http://x.tld?evil=1&action=read 服务端看到:url=http://x.tld?evil=1 AND action=read (仍然无害) 现在构造: USER_INPUT = http://x.tld?evil=1&action=delete 渲染链接: /proxy?url=http://x.tld?evil=1&action=delete&action=read 服务端(first-wins):action=delete ← 攻击者控制了流程,尽管 "&action=read" 是硬编码的注意关键细节:?在 URL 值内合法(http://x.tld?evil=1中的?不会被转义),于是攻击者注入的&action=delete与模板硬编码的&action=read形成重复参数,而服务端按 first-wins 取delete——模板作者的意图被同名参数的次序规则推翻。探测方法是在 payload 中携带&,观察响应 HTML 中它是否被原样保留:
# Probe —— 传递包含 & 的 payload,在响应 HTML 中寻找未编码的反射 curl -s "http://<TARGET>/page?ref=foo%26admin=1" | grep -oE 'href="[^"]*ref=[^"]*"' | head客户端 HPP 单独存在时严重度通常为 Low,但它是open redirect / CSRF / 服务端 HPP链路的理想起点:原技能文档的决策门明确建议"Document, often Low; chain with open redirect / CSRF"。这与 open-redirect/SKILL.md 覆盖的?url=、?next=、?redirect=参数面天然衔接。
7. 注入投递(Injection Delivery):用参数分段击穿单值检查
当 WAF 或应用存在单值长度限制 / 单出现位置正则时,HPP 可以把一个完整载荷拆到两个参数值里,利用解析器的拼接/取用规则在应用层重组:
# 将 SQLi 载荷拆成两段,绕过单值长度 / 模式检查 curl -G "http://<TARGET>/search" \ --data-urlencode "q=' UNION SELECT 1,2,3--" \ --data-urlencode "q=' UNION SELECT username,password,3 FROM users--" # .NET 逗号拼接 → 应用侧最终值同时包含两个片段,由 "," 连接 # 让 XSS 载荷绕过只检查单个出现位置的正则 curl -G "http://<TARGET>/view" \ --data-urlencode "name=harmless" \ --data-urlencode "name=<img src=x onerror=alert(1)>"第一例中,若目标是 ASP.NET(逗号拼接),应用最终拿到的q值形如' UNION SELECT 1,2,3--,' UNION SELECT username,password,3 FROM users--——两段注入被拼进同一条 SQL 语句;第二例则针对"正则只匹配第一个出现位置"的 WAF 规则,把危险标签藏在第二个值。投递成功后,就应当立即转入对应漏洞类的链式利用:Decepticon 的 sqli/SKILL.md 明确要求"SQLi 一旦确认(错误串 / 布尔差分 / 时间延迟任一),立即启动 sqlmap--batch --dump,禁止手工逐字符提取"——HPP 投递只是敲门砖,真正的数据提取要交给自动化管线。
8. 工具链:从参数挖掘到重复键注入
原技能文档列出的工具组合是完整 HPP 侦察-利用流水线:
- Burp Param Miner——发现隐藏/未文档化参数,检测反射与重复参数(dup-detection);
- HTTPParameterPollution(Burp 扩展)——自动生成重复参数排列组合(dup-permutations);
- wfuzz / ffuf——用
-z list,1-2-1,1注入重复键进行模糊测试; - sqlmap——
--param-del=';'、-p 'q'、--skip-urlencode组合用于分号分隔型 HPP(对应第 3 节探测中的id=1;id=2变体); - 手写 Python 方案:
requests.PreparedRequest允许传入元组列表以保留参数顺序:[("id","1"),("id","2")]。
手写 Python 一项值得展开:curl 的--data-urlencode无法控制同名参数的字节序(默认按书写顺序,但对复杂场景不便编程化),而PreparedRequest的元组列表是唯一能精确表达"第一次出现、第二次出现"的编程接口——这对第 5 节服务端 HPP 的"过滤器读第一处、控制器读最后一处"复现至关重要,因为role=user&role=admin与role=admin&role=user的利用方向完全相反。
9. 防御侧:检测签名与收敛修复
原技能文档同时给出了防守视角的检测信号表,红队成员了解这些信号也有助于评估探测噪音与规避痕迹:
| 信号 | 来源 |
|---|---|
单请求行内出现两次id=(或任意同名键) | 访问日志、请求审计 |
| WAF 规则在某一次出现处触发,但请求仍返回 200 | WAF 与应用日志关联分析 |
?key[]=或;key=模式 | nginx / Apache 日志 |
ASP.NET 请求把用户输入拼接成"1,2"并转发给后端 | 应用追踪(app trace) |
?a=1&a=2与?a=2&a=1结果不同(差分结果) | 主动监控探针 |
修复建议(原文档原文要点,不可省略):canonicalize duplicates before auth/inspection——在鉴权/检查之前先对重复参数做规范化收敛;对敏感端点按策略拒绝重复参数;绝不把用户输入未经重新编码&与=就重新发射进 URL。这三条分别对应第 4/5 节(服务端取用不一致)、第 7 节(分段注入)与第 6 节(客户端反射)三类攻击面的根治方案。
10. 决策门(Decision Gate):何时确认、何时升级、何时放弃
原技能文档的决策门是 HPP 利用流程的"判例法",直接指导 Agent 在每个观测点上的行动:
| 观测 | 行动 |
|---|---|
| 技术栈已指纹化、重复参数被接受、应用读值 B 而 WAF 检查值 A | 用已知被拦截的载荷拆分到 A/B 两侧确认 → 升级为 SQLi/XSS 链 |
| 鉴权相关参数接受重复值,且后端动作使用不同出现位置 | 追 ACL/IDOR-via-HPP 链 → 高严重度 |
| 重复参数被接受,但两个出现位置都被同等检查与对待 | 低影响,放弃或并入 bypass 研究 |
| 仅客户端 HPP(无鉴权/ACL 影响) | 记录在案,通常 Low;与 open redirect / CSRF 链式利用 |
这一"观测→行动"决策门在 Decepticon 的执行框架中并非孤立存在:执行提示词 exploit.md 定义了3-class pivot 规则——同一绕过类别(bypass class)连续 3 个载荷全负,就切换下一类别;同一端点耗尽 3 个类别即判定"端点已加固",写出exploit/PIVOT.md转向其他端点。HPP 正是这类"类别边界"的教科书示例:id=1&id=2、id[]=1&id[]=2、id=1;id=2三个 payload 属于同一类别(重复参数解析差异),不应被当作三次独立尝试反复迭代。
11. 该技能在 Decepticon 体系中的定位与加载机制
本技能是 Decepticon 开源项目(Autonomous Hacking Agent for Red Team)技能库中的一个子技能,位于 packages/decepticon/decepticon/skills/standard/exploit/web/hpp/SKILL.md。其 frontmatter 元数据定义了技能的使用边界:
name: hpp,allowed-tools: Bash Read Write——技能只允许使用 Bash、Read、Write 三类工具执行;metadata.subdomain: execution——归类于执行阶段;when_to_use触发词:HPP、HTTP parameter pollution、duplicate parameters、parameter precedence、WAF bypass via dup params、parser discrepancy、?a=1&a=2;mitre_attack: T1190——对应"Exploit Public-Facing Application"。
从源码结构可以确认技能的加载与调度机制:middleware/skills.py 中的SkillsMiddleware._format_skills_list会读取每个技能的 frontmatter,按subdomain分组渲染目录,并把mitre_attack与when_to_use触发词内联展示,供 Agent 做目标匹配;tools/skills.py 中的load_skill工具则按路径/相对路径/slug 解析并完整返回技能正文(无行数截断),其路径校验强制/skills/前缀并拒绝..穿越。也就是说,当 Agent 的当前目标命中when_to_use触发词(例如观察到?a=1&a=2这种重复参数或怀疑解析器差异)时,会通过load_skill("/skills/standard/exploit/web/hpp/SKILL.md")按需加载本技能全文,再按第 2~10 节的流程执行。
技能库内部对 HPP 的引用网络也印证了它的枢纽地位:web/SKILL.md 是 Web 攻击类目的路由总入口;waf-bypass/SKILL.md 第 3.8 节与交叉引用均指向 HPP;verb-tampering/SKILL.md 称 HPP 为"姊妹解析器差异类别"(sister parser-discrepancy class);方法论文档 tools/references/methodology.py 的别名表还把"parameter pollution": "hpp"映射为统一漏洞类别 slug,供methodology_lookup检索。跨技能交叉引用中,与 HPP 最常组合的是 waf-bypass(载荷混淆 + 解析器差异)、sqli(分段注入投递后升级)、bfla(参数遮蔽式越权)与 smuggling(同为解析器差异族:CL.TE/TE.CL 等请求走私)。
12. 方法论小结
HPP 攻击的完整闭环可以压缩为五步:
- 指纹——用
?id=1&id=2、?id=2&id=1、?id=1;id=2、?id[]=1&id[]=2差分探测,通过回显形状确定技术栈的取值规则(对照第 2 节速查表); - 定位差异——确认 WAF/代理与应用的取值不一致(WAF 读 A、应用读 B),或鉴权层与动作层的取值不一致;
- 投递——按"谁读哪个位置"决定恶意载荷放哪一侧(WAF 绕过放漏检侧,鉴权绕过放动作侧),必要时用
PreparedRequest精确控制参数次序; - 验证——遵循 bfla 纪律:基线对比 + 持久状态变化 + 最小复现;
- 升级或收尾——按第 10 节决策门决定升级为 SQLi/XSS 链(通常经 sqli 与 waf-bypass)还是记录 Low 级发现。
值得反复强调的两点纪律:一是HPP 的同类变体不要重复迭代——&、[]、;只是同一"解析器差异类别"的不同语法糖,连续三个同类载荷全负就应依 3-class pivot 规则切换类别;二是所有利用都必须限定在授权范围内(Decepticon 的 RoE 中间件与plan/roe.json即为此约束),HPP 的 WAF 绕过本质上是规避安全控制,必须在明确的渗透测试授权下进行。
交叉引用
- WAF 绕过载荷混淆——HPP 是其中 3.8 号 HTTP 层绕过手段;
- SQLi 链——HPP 分段投递后的标准升级路径;
- BFLA / 参数遮蔽式越权——服务端 HPP 的 ACL 绕过的验证方法论;
- HTTP 请求走私——同属"解析器差异"族的相关漏洞类别;
- HTTP 动词篡改——HPP 的姊妹解析器差异类别;
- Web 类目路由总入口——Web 攻击技能的选择与加载路由;
- 技能加载工具实现 与 技能目录中间件——理解技能如何被 Agent 加载与展示的源码依据。
【免费下载链接】Decepticon
Autonomous Hacking Agent for Red Team
相关推荐
HTTP 参数污染(HPP)实战指南:跨平台参数解析差异与安全绕过技术 —— 基于 PayloadsAllTheThings
HTTP 参数污染(HPP)实战指南:跨平台参数解析差异与安全绕过技术 —— 基于 PayloadsAllTheThings HTTP Parameter Po
网络安全应用安全渗透测试Sileo:iOS 11+ 终极现代包管理器,重新定义你的越狱体验
Sileo:iOS 11+ 终极现代包管理器,重新定义你的越狱体验 Sileo 是一款专为 iOS 11 及更高版本设计的现代包管理器,它彻底改变了越狱设备的应
移动开发包管理器HowToHunt 实战指南:社交分享按钮中的 HTTP 参数污染(HPP)挖掘方法
HowToHunt 实战指南:社交分享按钮中的 HTTP 参数污染(HPP)挖掘方法 本文是 HowToHunt 开源漏洞狩猎方法论仓库中的一篇实战指南,围绕
网络安全应用安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考