Saltearse al contenido

Web Cache Poisoning / Deception

Las cachés (CDN, reverse proxy, caché del navegador) guardan una respuesta y la sirven a muchos usuarios para ir rápido. El problema aparece cuando la clave de caché (lo que identifica “la misma respuesta”) no incluye una entrada que sí afecta al contenido. Entonces el atacante envenena una respuesta cacheada que se sirve a todos (poisoning), o engaña a la caché para que guarde contenido privado de la víctima y lo sirva a un tercero (deception).

Todo gira en torno a la cache key. La caché decide “esta petición es igual a esta otra” mirando típicamente método + host + path + query. Si una cabecera o parámetro que no está en la clave (“unkeyed input”) cambia la respuesta, el atacante manda una petición con esa entrada manipulada; la caché guarda la respuesta envenenada bajo la clave normal; las víctimas que piden esa clave reciben el veneno.

  • Identifica inputs unkeyed: cabeceras como X-Forwarded-Host, X-Forwarded-Scheme, X-Host, X-Forwarded-For, User-Agent, o parámetros de query que se reflejan pero no entran en la clave.
  • Observa cabeceras de caché: X-Cache: hit/miss, Age, Cache-Control, Vary. Un hit indica que se sirvió de caché.
  • Manda la petición con la cabecera sospechosa y un marcador; repite sin ella y mira si el marcador persiste (quedó cacheado).
# 1) el header unkeyed se refleja en la respuesta
GET /?cb=123 HTTP/1.1
Host: target
X-Forwarded-Host: evil.com
-> respuesta: <script src="//evil.com/a.js"> (reflejado)
# 2) esa respuesta queda cacheada bajo la clave /?cb=123
# 3) la víctima pide /?cb=123 -> recibe el script del atacante

Vectores habituales:

  • XSS cacheado: un X-Forwarded-Host reflejado en un <link>/<script>/<base> → XSS para todos.
  • Redirección cacheada: X-Forwarded-Host que acaba en un Location → open redirect masivo.
  • DoS por caché (CPDoS): envenenar con una respuesta de error (header que provoca 400/404) cacheado bajo la home.
  • Cache key normalization: delimitadores (;, #, codificación) que la caché y el origen tratan distinto para colar contenido bajo una clave “limpia”.

El flujo inverso: haces que la caché guarde una página dinámica/privada porque la URL parece estática.

# la víctima autenticada visita (porque tú le pasas el enlace):
https://target/account/profile/nonexistent.css
# el origen ignora la extensión y devuelve el perfil (con datos privados)
# la caché ve ".css" -> cachea "contenido estático"
# el atacante pide la misma URL -> recibe el perfil de la víctima

Variantes: .css, .js, /static/, path confusion (/profile%2f..%2fprofile.css), delimitadores que el origen y la caché parsean distinto.

  • Burp Suite — extensión Param Miner (descubre headers/params unkeyed).
  • Burp Repeater para confirmar hit/miss y persistencia.
  • Observación manual de X-Cache, Age, Vary.

XSS/redirect/DoS servidos a todos los usuarios (poisoning); robo de datos privados de víctimas autenticadas (deception).

  • Respuestas cacheadas que reflejan cabeceras no estándar (X-Forwarded-Host, etc.).
  • Picos de hit sobre URLs con queries raras o extensiones estáticas en rutas dinámicas.
  • Contenido dinámico apareciendo en la caché estática.

Loguea la cache key efectiva, las cabeceras entrantes y el X-Cache resultante; alerta sobre inputs reflejados no keyed.

  • Incluye en la clave de caché todo input que afecte a la respuesta, o no reflejes inputs unkeyed.
  • Usa Vary correctamente para las cabeceras que cambian la respuesta.
  • No caches contenido que dependa de la sesión/usuario; marca Cache-Control: private, no-store en respuestas autenticadas.
  • Define qué se cachea por extensión/ruta real, no por sufijo de URL; normaliza paths de forma consistente entre caché y origen.
  • Deshabilita el soporte de cabeceras X-Forwarded-* que no uses; no confíes en ellas para generar URLs.

Purga la caché afectada, corrige la clave/normalización, revisa qué contenido privado pudo servirse.

  • James Kettle — “Practical Web Cache Poisoning” (2018) y “Web Cache Entanglement” (2020) — investigación de referencia; afectó a GitHub, Mozilla, firmas grandes.
  • Omer Gil — “Web Cache Deception” (2017) — descubrió la técnica; PayPal entre los afectados iniciales.
  • CPDoS (2019) — clase de DoS por caché documentada académicamente, afectando CDNs populares.
  • Numerosos reportes en HackerOne de poisoning vía X-Forwarded-Host.
  • ¿Qué entra en la cache key? (método, host, path, query)
  • ¿Hay cabeceras/params reflejados que no estén en la clave? (Param Miner)
  • ¿Se puede cachear una respuesta con X-Forwarded-Host del atacante?
  • ¿Reflejo en <script>/<base>/Location → XSS/redirect cacheado?
  • ¿Error cacheable bajo una URL popular? (CPDoS)
  • ¿Una URL dinámica con extensión .css/.js se cachea con datos privados? (deception)
  • ¿Las respuestas autenticadas llevan Cache-Control: private/no-store?