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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
verify-ghsa-c4j6-fc7j-m34r — Verificador OOB para GHSA-c4j6-fc7j-m34r / CVE-2026-44578 (SSRF por actualización WebSocket en Next.js) | Kitploit
Herramientas/GitHubGitHub/panchocosil/verify-ghsa-c4j6-fc7j-m34r
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad WebPruebas de PenetraciónRed Teaming
GitHubpanchocosil/verify-ghsa-c4j6-fc7j-m34r

verify-ghsa-c4j6-fc7j-m34r

Verificador OOB para GHSA-c4j6-fc7j-m34r / CVE-2026-44578 (SSRF por actualización WebSocket en Next.js)

Ver Repositorio
7hace 4 mesesAú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

verify-ghsa-c4j6-fc7j-m34r

Verificador in-band para GHSA-c4j6-fc7j-m34r / CVE-2026-44578 — Falsificación de peticiones del lado del servidor (SSRF) en Next.js mediante peticiones de upgrade WebSocket.

⚠️ Solo para pruebas de seguridad autorizadas. Eres responsable de asegurarte de que tienes permiso para probar cada objetivo que pases a este script.

La vulnerabilidad

CampoValor
CVECVE-2026-44578
GHSAGHSA-c4j6-fc7j-m34r
CWECWE-918 (SSRF)
CVSS v3.18.6 (Alto) — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Afectadonext >=13.4.13 <15.5.16, >=16.0.0 <16.2.5
Parcheado15.5.16, 16.2.5
Commit de correcciónc4f69086
No afectadoAlojado en Vercel; output: "export"; despliegues detrás de un proxy inverso que no reenvía Upgrade

Cómo funciona realmente el bug (verificado empíricamente contra 15.5.15 vs 15.5.16)

  1. Un atacante abre una conexión TCP a un proceso Next.js autoalojado y envía un upgrade WebSocket HTTP/1.1 cuya request-URI es una URL absoluta:

    GET http://anything/<path> HTTP/1.1
    Host: <target>
    Connection: Upgrade
    Upgrade: websocket
    Sec-WebSocket-Version: 13
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    
  2. En resolveRoutes, la URL contiene // (como toda URI absoluta), lo que coincide con la rama de "normalizar barras repetidas". Esa rama retorna anticipadamente con { finished: true, statusCode: 308, parsedUrl: <mangled> }. El normalizador colapsa http://host/path en http:/host/path (una sola barra).

  3. En router-server.ts, el manejador de upgrade anterior al parche ignoraba finished/statusCode y solo comprobaba parsedUrl.protocol. Como el protocolo sobrevive a la normalización, llamaba a proxyRequest(...).

  4. proxyRequest ejecuta url.format(parsedUrl) sobre la URL alterada, obteniendo http:/host:port/path. http-proxy analiza ese destino, no encuentra host (url.parse('http:/...').host === null), y cae a su destino predeterminado: localhost:80 (o localhost:443 para https).

  5. Entonces, en la práctica, el SSRF permite hacer que Next abra un upgrade WebSocket al localhost:80 / localhost:443 del propio host de Next.js con una ruta controlada por el atacante.

El fix (commit c4f69086) hizo que el manejador de upgrade comprobara finished && !statusCode antes de hacer proxy. El caso de normalización 308 ahora falla la comprobación !statusCode y el socket se cierra en su lugar.

Por qué un verificador OOB basado en callbacks no funciona para este CVE

El proxy nunca alcanza un host externo. Si configuras un interactsh / Burp Collaborator / webhook canary y esperas que el proceso de Next llame a casa, no lo hará — la conexión va a localhost en la máquina objetivo. Por lo tanto, este verificador utiliza una señal in-band leída desde el socket de upgrade: un servidor vulnerable devuelve un cuerpo de error reconocible, un servidor parcheado no devuelve nada.

Impacto práctico

El objetivo del SSRF está restringido pero sigue siendo relevante en despliegues reales:

  • Contenedores sidecar / proxies inversos / paneles de administración co-ubicados en el mismo host que escuchan en 127.0.0.1:80 o :443 y confían en peticiones originadas desde localhost.
  • Socket de Docker expuesto vía HTTP en 127.0.0.1:80 (poco común pero visto).
  • Path traversal hacia cualquier servicio HTTP localhost con ruta URI controlada por el atacante y semántica de upgrade WebSocket.

Los endpoints de metadatos de AWS / GCP / Azure (169.254.169.254) no son directamente alcanzables porque el bug fija el destino a localhost.

Modelo de detección

Para cada objetivo, el script abre un socket TCP (o TLS) crudo, envía el upgrade manipulado, lee la respuesta y produce dos señales:

  • verdict — si el bug está presente.
  • impact_confirmed — si el SSRF realmente exfiltró datos (es decir, un servicio co-ubicado en localhost:80/443 del objetivo respondió y obtuvimos su respuesta).
RespuestaVeredictoimpact_confirmed
Contiene Internal Server Errorvulnerablefalse — bug probado, pero el proxy no alcanzó nada en localhost
Empieza con HTTP/1.vulnerable_proxy_succeededtrue — datos de respuesta reales exfiltrados
Vacía / cierre limpiolikely_patchedfalse — también cubre "no es Next", "el proxy inverso eliminó Upgrade", "Vercel"
Idéntica al control sin Upgradefront_end_interceptsfalse — el proxy front-end cortocircuitó ambas sondas; el SSRF nunca llegó a Next
Cualquier otra cosainconclusivefalse

Cuando impact_confirmed es true, la salida JSON también incluye upstream_status, upstream_server y upstream_content_type extraídos de la respuesta filtrada (útil para triaje / redacción de informes).

Guardia contra falsos positivos del proxy front-end

Por defecto, cada objetivo también recibe una sonda de control con la misma línea de petición de URI absoluta pero sin cabeceras Upgrade (Connection: close). Si el front-end devuelve la misma respuesta a ambas sondas (línea de estado + tamaño dentro de la tolerancia), el front-end del propio host está rechazando la línea de petición de URI absoluta en sí — nginx 400, Apache 400, borde CDN — y el SSRF nunca llegó a Next. El veredicto se degrada a front_end_intercepts y la salida JSON incluye front_end_status y front_end_server extraídos de la respuesta del proxy para que el operador pueda identificar qué está interceptando.

Esto elimina un falso positivo del mundo real observado cuando Next autoalojado está detrás de nginx/Apache: esos proxies rechazan la línea de petición GET http:///x HTTP/1.1 de la sonda con un 400 genérico, que el detector anteriormente malinterpretaba como vulnerable_proxy_succeeded. Pasa --no-control-probe para desactivar esta protección y ver los veredictos crudos.

Requisitos

  • Python 3.10+
  • Sin dependencias de terceros (solo stdlib)

Uso

# single target
python3 verify_ghsa_c4j6.py --target https://app.example.com

# multiple targets via flag repetition
python3 verify_ghsa_c4j6.py \
    --target https://app1.example.com \
    --target app2.example.com:3000 \
    --target 10.0.0.5:80

# from a file (one target per line; '#' for comments)
python3 verify_ghsa_c4j6.py --targets-file targets.txt

# from stdin
cat targets.txt | python3 verify_ghsa_c4j6.py

# JSON Lines output for downstream tooling
python3 verify_ghsa_c4j6.py --targets-file targets.txt --json

# Enumerate co-located services on the target's localhost:80/443 via the bug
python3 verify_ghsa_c4j6.py --target https://app.example.com --scan

# Same, with a custom path list
python3 verify_ghsa_c4j6.py --target ... --scan-paths-file my_paths.txt

Modo scan

--scan sondea una lista integrada de rutas comunes (módulos de estado de Apache/nginx, endpoints de salud y métricas, Spring Boot Actuator, Go pprof, endpoints del daemon de Docker, paneles de administración comunes, archivos de configuración con fugas, rutas de Elasticsearch, etc.) a través del gadget SSRF.

Por defecto, el modo scan ejecuta una sonda de línea base diferencial adicional con una ruta aleatoria inexistente por objetivo. Las sondas posteriores se etiquetan DIFF solo cuando su firma (status, body length) diverge de la línea base — los 404 uniformes de un upstream que "no encontró nada" se marcan como noise y no inflan el contador de aciertos. Pasa --no-differential para informar de cada sonda que alcanzó un servicio (comportamiento heredado).

La salida se agrupa por objetivo:

Descargar herramienta