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:
- Entrega la URL deceptiva a
carlos(p. ej. vía el exploit server). - Espera a que el navegador de la víctima cargue
/my-accounty el origin devuelva la página con la API key. - Realiza una
GETa/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-storeen 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.