← Writeups

Exploiting cache server normalization for web cache deception

Web cache deception vía normalización de la caché: el cache server resuelve una secuencia de path traversal mientras el origin usa # como delimitador, cacheando la respuesta de /my-account.

Target Overview & Vulnerability Summary

El lab explota una discrepancia de normalización entre el cache server y el origin server. Se debe obtener la API key del usuario carlos. La URL /my-account%23%2f%2e%2e%2fresources se procesa distinto en cada componente: el cache server resuelve la secuencia de path traversal (/../) y la trata como un asset cacheable bajo /resources; el origin server usa # (%23) como delimitador y sirve el contenido de /my-account. La respuesta de la página de cuenta queda guardada en la caché.

Campo Valor
Severidad Alta (exfiltración de datos autenticados vía caché pública)
Endpoint vulnerable /my-account (ruta dinámica no cacheable, cacheada por normalización)
Root cause Discrepancia de normalización entre cache y origin (path traversal vs delimitador #)

Credenciales del laboratorio: wiener:peter. Se dispone de una lista de caracteres delimitadores para la resolución.

Technical Breakdown & Exploitation Flow

1. La request deceptiva

GET /my-account%23%2f%2e%2e%2fresources HTTP/2
Host: <LAB-ID>.web-security-academy.net
Cookie: session=<SESSION_ID>

2. Comportamiento divergente de los parsers

Cache server:

  • Recibe el path /my-account%23%2f%2e%2e%2fresources.
  • Decodifica %2f → / y %2e%2e → .., resolviendo la secuencia de path traversal: /my-account#/../resources → /resources.
  • Al terminar en un path que apunta a recursos estáticos, decide cachear la respuesta bajo esa clave.

Origin server:

  • Usa # (%23) como carácter delimitador: ignora todo lo que sigue al #.
  • Resuelve el recurso real /my-account, que es una página dinámica con la API key del usuario autenticado.

3. Resultado

La respuesta de /my-account (con la API key de carlos cuando la víctima visita la URL) se almacena en la caché bajo la clave normalizada /resources. El atacante:

  1. Entrega la URL deceptiva a carlos (p. ej. vía el exploit server).
  2. Espera a que el navegador de la víctima cargue /my-account y el origin devuelva la página con la API key.
  3. Realiza una GET a /resources (o la clave cacheada): el cache server devuelve la respuesta previamente cacheada, exponiendo la API key.

Root Cause Analysis

El root cause es la discrepancia de normalización entre los dos componentes del stack:

  • El cache server normaliza y resuelve secuencias de path traversal antes de clasificar el recurso, viendo /resources (statico, cacheable).
  • El origin server respeta # como delimitador de fragmento y solo procesa /my-account (dinámico, no cacheable).

Como cada capa aplica sus propias reglas de parsing/normalización sobre la misma URL, la misma request se clasifica como asset estático para la caché y como página dinámica para el origin. El cache server no conoce la semántica del origin y cacha una respuesta que nunca debió ser cacheable.

Secure Remediation

  • Hacer que el cache server use la misma normalización que el origin (o que el origin y la caché compartan la misma lógica de parsing de URLs y delimitadores).
  • Cachear solo por cache key explícita (path + query normalizados con la misma regla), nunca por heurísticas que interpreten la URL de forma distinta a la app.
  • Marcar respuestas dinámicas/autenticadas como no cacheables: Cache-Control: private, no-store en páginas de cuenta.
  • Configurar reglas de caché por tipo de contenido/endpoint y por presencia de cookies de sesión: nunca cachear respuestas con Set-Cookie o contenido dependiente de autenticación.