Aller au contenu

Web cache deception

La tromperie de cache web (web cache deception) permet à un attaquant de faire stocker, par un cache, du contenu dynamique sensible. L'attaquant amène une victime à visiter une URL piégée, ce qui fait émettre par son navigateur une requête ambiguë pour du contenu sensible ; le cache l'interprète comme une ressource statique et la stocke ; l'attaquant requête ensuite la même URL pour récupérer la réponse en cache — et donc les données de la victime.

Deception ≠ poisoning

La différence avec l'empoisonnement de cache est nette : l'empoisonnement manipule les clés pour injecter un contenu malveillant servi aux autres ; la tromperie exploite les règles de cache pour piéger le cache afin qu'il stocke des données sensibles auxquelles l'attaquant accède.

Rappels sur le cache

Un cache s'intercale entre le serveur d'origine et l'utilisateur. À une requête, il sert une copie stockée (cache hit) ou transmet au serveur d'origine (cache miss) puis stocke selon ses règles. Trois notions sont centrales :

  • La clé de cache, générée à partir d'éléments de la requête (chemin, paramètres, parfois en-têtes), détermine l'équivalence entre requêtes.
  • Les règles de cache déterminent ce qui est stocké. Le contenu statique l'est (il change peu), le dynamique ne l'est pas (il contient des données sensibles).
  • Ces règles s'appuient souvent sur des chaînes du chemin URL : extension (.css, .js), dossier statique (préfixe /static, /assets), ou nom de fichier (robots.txt, favicon.ico).

L'attaque exploite la façon dont ces règles sont appliquées, et surtout les incohérences entre le cache et le serveur d'origine.

Construire l'attaque

La démarche : identifier un endpoint renvoyant une réponse dynamique sensible (en étudiant la réponse dans Burp, certaines données n'apparaissant pas à l'écran ; se concentrer sur GET/HEAD/OPTIONS) ; trouver une différence d'analyse du chemin entre cache et serveur d'origine (mappage des ressources, traitement des délimiteurs, normalisation) ; forger une URL exploitant cette différence ; puis récupérer la réponse en cache via Burp (éviter le navigateur, qui peut rediriger ou invalider les données et masquer la faille).

Cache buster et détection des hits

Chaque requête de test doit avoir une clé unique (cache buster ajouté au chemin, automatisable via Param Miner), sinon on reçoit des réponses en cache trompeuses. On identifie une réponse en cache via l'en-tête X-Cache (hit/miss/dynamic), les directives Cache-Control, ou un écart de temps de réponse.

Règles sur les extensions statiques

C'est le comportement standard de la plupart des CDN. On exploite une incohérence pour qu'une ressource dynamique porte une extension statique, vue par le cache mais ignorée par le serveur d'origine.

Incohérences de mappage. Le mappage traditionnel pointe vers un fichier du système (/path/resource.html) ; le mappage REST décompose le chemin en parties logiques (/path/resource/param). Pour /user/123/profile/wcd.css, un serveur REST renvoie le profil de l'utilisateur 123 en ignorant wcd.css ; un cache traditionnel y voit un fichier CSS et met le profil en cache. On teste le serveur d'origine en ajoutant un segment (/api/orders/123/api/orders/123/foo) : une réponse identique signale qu'il fait abstraction du segment. On teste le cache en ajoutant une extension (/foo/foo.js) : une mise en cache confirme une règle sur .js. Il faut essayer plusieurs extensions (.css, .ico, .exe).

Incohérences de délimiteurs. Le RFC URI étant permissif, les frameworks diffèrent. Java Spring traite ; comme délimiteur (/profile;foo.css/profile) ; Ruby on Rails traite . comme séparateur de format (/profile.ico géré par le formateur HTML par défaut) ; OpenLiteSpeed traite %00 comme délimiteur. On identifie un délimiteur côté origine en ajoutant une chaîne arbitraire (/list/listaaa), puis en insérant le délimiteur candidat (/list;aaa) : si la réponse égale celle de base, le ; est un délimiteur. On teste ensuite le cache en ajoutant une extension statique.

Délimiteurs traités par le navigateur

Certains caractères ({, }, <, >) sont encodés par le navigateur, et # tronque le chemin — ils ne peuvent servir directement dans l'exploit, sauf sous forme encodée si le cache ou le serveur les décode.

Incohérences de décodage. Certains parseurs décodent un délimiteur encodé avant traitement. Pour /profile%23wcd.css, le serveur d'origine décode %23 en # et interprète /profile, tandis que le cache garde %23 et applique sa règle .css. On teste avec des caractères encodés, notamment %00, %0A, %09.

Règles sur les dossiers statiques

Les règles ciblant des préfixes (/static, /assets) s'exploitent via une traversée de répertoires combinée à une incohérence de normalisation. Pour /static/..%2fprofile, un serveur d'origine qui décode %2f et résout les .. normalise en /profile, tandis qu'un cache qui ne le fait pas garde /static/..%2fprofile et applique sa règle de préfixe. Les segments de traversée doivent être encodés, sinon le navigateur les résout avant la requête.

On teste le serveur d'origine sur une ressource non cachable (méthode POST) en ajoutant une traversée et un dossier arbitraire (/profile/aaa/..%2fprofile) : réponse identique = résolution. On teste le cache sur une ressource en cache de la même manière. Selon le serveur qui normalise, on exploite via /prefixe-statique/..%2fchemin-dynamique (normalisation côté origine) ou /chemin-dynamique%2f%2e%2e%2fprefixe-statique en encodant toute la séquence et en ajoutant un délimiteur côté origine (normalisation côté cache) :

/profile;%2f%2e%2e%2fstatic

Règles sur les noms de fichiers

Les fichiers comme robots.txt ou favicon.ico sont mis en cache par correspondance exacte de nom. La réponse n'étant cachée que si la requête correspond au nom exact, l'exploitation n'est possible que si le cache résout les ../ encodés mais pas le serveur d'origine, avec les mêmes méthodes que pour les dossiers :

/my-account;%2f%2e%2e%2frobots.txt?wcd

permettant par exemple de récupérer le jeton CSRF d'un administrateur, puis de forger une preuve de concept poussant une mise à jour non désirée.

Aide-mémoire

Type de règle Incohérence exploitée
Extension statique Mappage (REST vs fichier), délimiteur (;, ., %00), décodage (%23)
Dossier statique Normalisation + traversée encodée (..%2f)
Nom de fichier Normalisation côté cache + correspondance exacte

Tester systématiquement tous les caractères ASCII comme délimiteurs (encodage automatique désactivé dans Burp Intruder) et confirmer chaque hypothèse avec un cache buster sont les réflexes clés ; Burp Scanner et la Web Cache Deception Scanner détectent les incohérences de mappage les plus courantes.