Table of Contents
Description
L'attaque HTTP Request Smuggling explore clandestinement une analyse syntaxique incomplète des données soumises par un système HTTP intermédiaire travaillant comme un proxy. HTTP Request Smuggling consiste à envoyer une requête HTTP spécialement formatée qui sera analysée d'une façon différente par le système proxy et par le système final, donc l'attaquant pourrait faire passer clandestinement une demande à un système sans que l'autre en ai conscience. Cette attaque rend possible l'exploitation d'autres attaques, comme Cache Poisoning, Session Hijacking, Cross-site Scripting (XSS) et de la manière plus importante, la capacité d'éviter firewall de l'application web.
Pour exploiter la HTTP Request Smuggling, quelques conditions spécifiques doivent exister, comme la présence de système de proxy spécifique et de version comme SunOne Proxy 3.6 (SP4) ou FW-1/FP4-R55W beta ou une vulnérabilité XSS dans le serveur web.
Basiquement l'attaque consiste à soumettre une requête HTTP qui encapsule deuxième requête HTTP dans le même en-tête, comme montré ci-dessous.
GET /some_page.jsp?param1=value1¶m2= Content-Type: application/x-www-form- Content-Length: 0 Foobar: GET /mypage.jsp HTTP/1.0 Cookie: my_id=1234567 Authorization: Basic ugwerwguwygruwy
Dans ce cas-là, le première en-tête HTTP est analysée par le système de proxy et le deuxième par le système final, permettant à l'attaquant d'éviter le contrôle d'accès du proxy. L'attaque pourrait être exploitée différemment comme annoncé par le papier “HTTP Request Smuggling” de Watchfire, donc il est possible de réaliser ces attaques : • *Web Cache Poisoning • *Firewall/IPS/IDS evasion • *Forward vs. backward HRS • *Request Hijacking • *Request Credential Hijacking
Exemples
Exemple 1 - Cache Poisoning Exploiting
Notre premier exemple démontre une attaque HRS classique. Supposons qu'une requête POST contient deux en-têtes “Content-Length” avec des valeurs conflictuelles. Certains serveurs (par ex., IIS et Apache) rejettent une telle requête, mais ils retournent autre chose pour ignorer l'en-tête problématique. Lequel des deux en-têtes est celui problématique ? Heureusement pour l'attaquant, différents serveurs choisissent différentes réponses. Par exemple, SunONE W/S 6.1 (SP1) utilise le premier en-tête “Content-Length” , tandis que SunONE Proxy 3.6 (SP4) prend le deuxième en-tête (remarquez que les deux applications sont de la famille SunONE). Laissez SITE être le nom du DNS du SunONE W/S derrière le proxy SunONE. Supposons que “ /poison.html ” est une page HTML (en cache) statique sur le W/S. Voici l'attaque d'HRS qui exploite l'incohérence entre les deux serveurs :
1 POST <nowiki>0</nowiki> 2 Host: SITE 3 Connection: Keep-Alive 4 Content-Type: application/x-www-form-urlencoded 5 Content-Length: 0 6 Content-Length: 44 7 [CRLF] 8 GET <nowiki>1</nowiki> 9 Host: SITE 10 Bla: [space after the "Bla:", but no CRLF] 11 GET <nowiki>2</nowiki> 12 Host: SITE 13 Connection: Keep-Alive 14 [CRLF]
[Notez que chaque ligne se termine avec un CRLF (“ \r\n ”), à part la ligne 10.] Examinons ce qui arrive quand cette requête est envoyée au W/S via le serveur proxy. D'abord, le proxy analyse la requête POST des lignes 1 à 7 (en bleu) et rencontre les deux en-têtes “Content-Length”. Comme nous avons mentionné plus tôt, il décide d'ignorer le premier en-tête, donc il suppose que la requête a un corps de longueur 44 octets. Donc, il traite les données des lignes 8 à 10 comme le premier corps de requête (les lignes 8 à 10, en violet, contiennent exactement 44 octets). Le proxy analyse alors les lignes 11 à 14 (en rouge), qu'il traite comme la deuxième requête du client. Maintenant voyons comment le W/S interprète la même charge, dès qu'elle a été envoyée par le proxy. À la différence du proxy, le W/S utilise le premier en-tête “Content-Length” : Bien qu'elles soient concernées, la première requête POST n'a aucun corps, et la deuxième requête est le GET en ligne 8 (remarquez que le GET en ligne 11 est analysé par le W/S comme la valeur de l'en-tête “Bla” à la ligne 10). Pour résumer, c'est la façon dont les données sont partagées par les deux serveurs :
1st request 2nd request
SunONE Proxy lines 1-10 lines 11-14
SunONE W/S lines 1-7 lines 8-14
Ensuite, voyons quelles réponses sont retournées au client. Les requêtes que le W/S voit sont “POST /foobar.html” (à la ligne 1) et “GET /poison.html” (à la ligne 8), donc il retourne deux réponses avec les contenus de la page “foobar.html” et de la page “poison.html”, respectivement. Le proxy penset que ces réponses aux deux requêtes ont été envoyées par le client - “POST /foobar.html” (ligne 1) et “GET /pagetopoison.html” (ligne 11). Puisque la réponse est dans le cache (nous avons supposé que “poison.html” est une page du cache), les caches du proxy contiennent “poison.html” sous l'URL “pagetopoison.html”, et voilà : le cache est empoisonné ! N'importe quel client demandant “pagetopoison.html” au proxy recevra la page “poison.html”. Une note technique : les lignes 1 à 10 et 11à 14 doivent être envoyées dans deux paquets séparés, puisque SunONE proxy ne fait pas de requêtes de pipeline sur le même paquet.
Exemple 2 - Request Credential Hijacking
Un autre centre d'intérêt est la capacité de l'attaquant d'invoquer de force un script (/some_page.jsp) avec l'identité d'un client. Cette attaque est semblable en fait à l'attaque de Cross-Site Request Forgery, encore est elle plus puissante parce que l'attaquant n'est pas tenu de communiquer avec le client (la victime). L'attaque est la suivante :
POST /some_script.jsp HTTP/1.0 Connection: Keep-Alive Content-Type: application/x-www-form-urlencoded Content-Length: 9 Content-Length: 142 this=thatGET /some_page.jsp?param1=value1¶m2=value2 HTTP/1.0 Content-Type: application/x-www-form-urlencoded Content-Length: 0 Foobar:
Quand le client envoie une requête du type :
GET /mypage.jsp HTTP/1.0 Cookie: my_id=1234567 Authorization: Basic ugwerwguwygruwy
Tomcat collera celle-ci à la queue de la requête incomplète, ce qui donnera :
GET /some_page.jsp?param1=value1¶m2=value2 HTTP/1.0 Content-Type: application/x-www-form-urlencoded Content-Length: 0 Foobar: GET /mypage.jsp HTTP/1.0 Cookie: my_id=1234567 Authorization: Basic ugwerwguwygruwy
Maintenant une requête complète, il invoquera le script /some_page.jsp et retournera ses résultats au client. Si ce script est une demande de changement de mot-de-passe, ou un transfert d'argent vers le compte de l'attaquant, donc cela peut engendrer potentiellement de sérieux dommages au client.
References
- http://www.securiteam.com/securityreviews/5GP0220G0U.html
- Testing for HTTP Splitting/Smuggling https://www.owasp.org/index.php/Testing_for_HTTP_Splitting/Smuggling_%28OWASP-DV-016%29
