Nouvelle réglementation de cybersécurité 2026 en vigueur au Maroc. Obtenir un audit de conformité gratuit →
← Retour au blog
OWASP 2025-11-20 ⏱️ 11 min

Web Cache Deception en 2025 : confusion de chemin, règles de cache et limites du Deception Armor

Web Cache Deception en 2025 : confusion de chemin, règles de cache et limites du Deception Armor

La Web Cache Deception (WCD) est une attaque élégante. L'attaquant n'a pas besoin de voler un cookie de session, de casser un mot de passe ou d'exploiter une corruption mémoire. Il lui suffit d'amener un cache partagé à stocker une réponse privée authentifiée sous une URL qu'il pourra ensuite demander sans authentification. La victime visite un lien piégé, le cache enregistre la page, l'attaquant la lit. La technique a été popularisée par Omer Gil en 2017 et étudiée à grande échelle dans l'article USENIX Security 2020 « Cached and Confused ». Elle reste pertinente car le désaccord sous-jacent — ce que l'origine considère comme une page dynamique et ce que le cache considère comme un fichier statique — n'a jamais été entièrement résolu.


1. Le mécanisme central

Considérez une application qui sert une page de compte privée à :

GET /account HTTP/1.1
Host: example.com
Cookie: session=victim-session

L'origine renvoie du HTML contenant l'e-mail, le solde ou une clé API de la victime, avec Cache-Control: private. Un cache correct ne le stocke pas. Considérez maintenant une requête avec un segment supplémentaire et une extension statique :

GET /account/avatar.css HTTP/1.1
Host: example.com
Cookie: session=victim-session

Beaucoup de frameworks routent cela vers le même contrôleur de compte car le routeur ignore les segments finaux ou les traite comme paramètres. L'origine renvoie toujours le HTML privé. Mais le cache voit un chemin .css et applique une règle d'actif statique : mise en cache publique, souvent pour des heures. L'attaquant demande alors /account/avatar.css sans cookie et reçoit la page de la victime.

La vulnérabilité n'est ni dans le cache ni dans l'application seule. Elle est dans l'écart entre leurs règles de normalisation et de routage.


2. Variantes encore efficaces

2.1 Confusion d'extension

Ajouter .css, .js, .png, .ico ou .woff2 à une route dynamique est la forme classique. Elle fonctionne quand l'origine ignore le suffixe mais que la règle de cache du CDN le reconnaît.

2.2 Différences de normalisation de chemin

Caches et origines normalisent différemment .., ., les slashs doublés, les points-virgules, les slashs encodés (%2f) et les antislashs. Une requête comme /account/..%2fstatic/app.css peut être routée par l'origine vers /account alors que le cache la traite comme un fichier statique. Les recherches de James Kettle en 2024 sur la confusion de chemin ont montré la persistance de ces écarts dans les grands CDN.

2.3 Astuces de délimiteurs et paramètres

Certaines origines traitent ;, ? ou # comme délimiteurs de routage ; les caches parfois non. Une URL comme /account;.css peut être interprétée comme /account par l'application et comme fichier CSS par le cache. De même, un cache peut ignorer la query string dans sa clé alors que l'origine l'utilise pour choisir le contenu.

2.4 Confusion d'en-tête et de méthode

Si le cache indexe par méthode mais que l'origine traite HEAD comme GET, une requête HEAD peut remplir une entrée servie ensuite à GET. La gestion de Vary crée aussi des failles : si le cache n'inclut pas Cookie dans la clé (normal pour du contenu public), une réponse authentifiée stockée selon une règle statique est servie à tous.


3. Pourquoi le « Cache Deception Armor » ne suffit pas

Le Cache Deception Armor (CDA) de Cloudflare compare le Content-Type de la réponse à l'extension demandée. Si une requête finit en .css mais que l'origine renvoie text/html, CDA refuse de mettre en cache. C'est un contrôle utile, mais heuristique :

  • Il dépend d'en-têtes d'origine corrects. Si l'origine omet ou étiquette mal Content-Type, la comparaison échoue de façon imprévisible.
  • Il ne couvre pas toutes les extensions. Les règles statiques personnalisées et les types MIME rares peuvent ne pas être mappés.
  • La confusion de chemin peut contourner le contrôle. Si le cache normalise le chemin différemment de l'origine, l'extension vue par CDA peut ne pas être celle du routage.
  • Il ne corrige pas l'origine. La réponse privée est toujours générée et renvoyée avec une sémantique cachable ; une autre couche de cache ou un proxy mal configuré peut encore la stocker.

CDA réduit la surface. Il ne remplace ni des en-têtes Cache-Control corrects ni un routage strict.


4. Méthodologie de test

Ne testez que des systèmes autorisés. Utilisez deux comptes : une victime et un attaquant. L'objectif est de prouver que l'attaquant récupère les données privées de la victime via un cache.

  1. Identifiez les pages privées. Paramètres de compte, tableaux de bord, factures, clés API, panneaux d'administration.
  2. Établissez une base. Demandez la page en tant que victime et notez les en-têtes : Cache-Control, Vary, Age, X-Cache, CF-Cache-Status, Akamai-Cache-Status.
  3. Ajoutez des suffixes statiques. Essayez /account.css, /account.js, /account.png, /account/foo.css et /account%2ffoo.css.
  4. Vérifiez le statut du cache. Une réponse passant de BYPASS à HIT ou MISS avec un en-tête public est prometteuse.
  5. Demandez sans authentification. Depuis une session propre, demandez la même URL. Si les données de la victime apparaissent, le cache a stocké une réponse privée.
  6. Confirmez avec une seconde action. Modifiez une valeur du compte victime et répétez pour montrer que la page en cache fuit la nouvelle valeur.
# Base en tant que victime
curl -s -D - -o /dev/null -b 'session=VICTIM' https://example.com/account

# Sonde avec suffixe statique
curl -s -D - -o /dev/null -b 'session=VICTIM' https://example.com/account/x.css

# Récupération attaquant sans cookies
curl -s -D - https://example.com/account/x.css | head -40

5. Conception défensive

  • Marquez explicitement les réponses authentifiées. Envoyez Cache-Control: private, no-store sur toute réponse contenant des données utilisateur. Ne comptez pas sur l'absence d'en-tête public.
  • Ne laissez pas les règles statiques écraser la sémantique d'origine. Configurez le CDN pour ne cacher que des chemins statiques connus, pas « tout ce qui finit en .css ». Préférez des listes explicites.
  • Normalisez de façon cohérente. Assurez l'accord entre edge et origine sur le décodage, les slashs, les segments de points et les délimiteurs. Rejetez les chemins ambigus à l'edge.
  • Séparez les origines statiques et dynamiques. Servir le contenu utilisateur depuis app.example.com et les actifs depuis static.example.com élimine la plupart des confusions. Les cookies doivent être limités à l'hôte applicatif.
  • Incluez les bonnes dimensions dans la clé de cache. Si une réponse varie selon le cookie, l'en-tête Authorization ou le locataire, incluez-le dans la clé ou ne cachez pas.
  • Testez après chaque changement de règle CDN. Le comportement du cache est de la configuration, et la configuration dérive. Ajoutez des sondes WCD à la suite de régression.

6. Conclusion

La Web Cache Deception exploite une ambiguïté, pas un chiffrement cassé. L'attaquant demande une chose à l'origine et une autre au cache, et l'écart entre les deux réponses devient une fuite de données. Les contrôles d'extension et le deception armor augmentent le coût, mais le correctif durable consiste à rendre explicite la sémantique de confidentialité de l'origine et à garantir que l'edge ne cache jamais une réponse qu'il ne comprend pas entièrement. Si une page exige une session, sa réponse doit le dire dans Cache-Control — et le CDN doit être configuré pour la croire.

Besoin d'un audit de sécurité ?

Contactez Cayvora pour une consultation gratuite et protégez votre entreprise contre les cybermenaces.

✉️ Contact via Email

Articles connexes