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-34207 — El filtro SSRF verificaba el texto del nombre de host, pero el destino real se decidía después mediante DNS. Ese desfase permitió que las URL de Webhook controladas por el atacante alcanzaran objetivos de loopback, metadatos y redes privadas. | Kitploit
Herramientas/GitHubGitHub/0xmrma/cve-2026-34207
Análisis de VulnerabilidadesExplotaciónSeguridad WebPruebas de PenetraciónPapers e InvestigaciónAprendizaje y Educación
GitHub0xmrma/cve-2026-34207

CVE-2026-34207

El filtro SSRF verificaba el texto del nombre de host, pero el destino real se decidía después mediante DNS. Ese desfase permitió que las URL de Webhook controladas por el atacante alcanzaran objetivos de loopback, metadatos y redes privadas.

Ver Repositorio
1hace 2 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

CVE-2026-34207

El filtro SSRF verificaba el texto del nombre de host, pero el destino real se decidía después mediante DNS. Esa brecha permitió que URLs de Webhook controladas por el atacante alcanzaran loopback, metadatos y objetivos de red privada.

Introducción

Encontré este problema mientras revisaba Typebot, un creador de chatbots de código abierto, con una simple pregunta de seguridad en mente:

¿Qué sucede si la protección SSRF valida el texto del nombre de host, pero el destino real se decide después mediante DNS?

En este caso, esa pregunta llevó a un error real.

La protección SSRF de Typebot para los bloques Webhook / Petición HTTP validaba solo:

  • la cadena de la URL,
  • los literales de nombre de host bloqueados,
  • y los formatos IP literales

No resolvía los nombres de host antes de permitir la petición.

Eso significaba que un nombre de host como ssrf-repro.example podía parecer inofensivo durante la validación, y luego resolverse a:

  • 127.0.0.1
  • 169.254.169.254
  • o espacio RFC1918/red privada

y aun así ser obtenido por el cliente HTTP del backend.

Ese problema se convirtió en .

CVE-2026-34207

Typebot: Typebot en GitHub
CVE: CVE-2026-34207
Corregido en: 3.16.0

Esto afectó a Typebot, una plataforma de chatbot de código abierto ampliamente utilizada. En su sitio oficial, Typebot se presenta como confiable para más de 650 empresas en todo el mundo. El sitio también publicita más de 2 millones de chats mensuales y más de 1,5 millones de bots publicados.

photo0

Cadena de ataque

URL de Webhook controlada por atacante -> nombre de host pasa validación SSRF solo literal -> sin resolución DNS antes de la decisión de permitir -> cliente HTTP del backend resuelve nombre de host a destino interno -> petición del lado del servidor alcanza loopback / metadatos / red privada -> los datos de respuesta están disponibles a través de registros de ejecución


Lo que hace Typebot

Typebot es un creador de chatbots.

Permite a los usuarios crear flujos que pueden:

  • hacer preguntas
  • recopilar entradas estructuradas
  • llamar a servicios externos
  • encadenar lógica de negocio
  • y desencadenar peticiones HTTP salientes a través de bloques Webhook / Petición HTTP

Eso significa que la ejecución de peticiones salientes es un límite de seguridad real.

La pregunta importante aquí no era si Typebot soportaba bloques Webhook.

La pregunta real era:

¿La protección SSRF valida el destino real al que se conectará el servidor, o solo el texto del nombre de host que aparece en la URL?

En este caso, solo validaba la forma textual primero.

Ese fue el error.


Por qué valía la pena examinar esta superficie

Las defensas SSRF fallan de maneras muy predecibles.

La mayoría de las veces, los errores interesantes no son:

  • "olvidaste bloquear 169.254.169.254"
  • o "olvidaste bloquear localhost"

Los errores más significativos son errores de límite:

  • la validación ocurre antes de la canonicalización
  • la validación ocurre antes de las redirecciones
  • la validación ocurre antes de la resolución DNS
  • la validación ocurre en una representación, pero la pila de red usa otra

Ese era el lugar adecuado para buscar aquí.

Typebot ya tenía lógica de endurecimiento SSRF para IPs literales de metadatos, loopback, rangos privados y trucos de IP codificadas.

Eso hizo obvia la siguiente pregunta:

¿Qué sucede si el nombre de host no es literalmente peligroso, pero se resuelve a un destino peligroso más tarde?

Eso es exactamente lo que sucedió.


Causa raíz

El problema raíz fue la validación del destino basada en el texto del nombre de host en lugar de la dirección IP resuelta.

En la implementación vulnerable, validateHttpReqUrl():

  • analizaba la URL
  • permitía solo http: y https:
  • bloqueaba una lista corta de nombres de host literales como metadata.google.internal, metadata.goog, metadata y localhost
  • detectaba trucos de IP decimal/hexadecimal/octal literales
  • analizaba direcciones IPv4/IPv6 literales
  • validaba la dirección solo si el nombre de host ya era una IP literal

Esa es la parte importante.

Si el nombre de host era un valor normal como:

ssrf-repro.example

entonces parseIPAddress(hostname) devolvía null, y el validador se detenía allí.

No ocurría resolución DNS antes de la aprobación.

Por lo tanto, la lógica vulnerable se reducía efectivamente a:

root@kitploit:~
const ip = parseIPAddress(hostname);
if (ip) {
  validateIPAddress(ip);
}

Eso significa:

  • las IPs literales peligrosas estaban bloqueadas
  • las IPs codificadas peligrosas estaban bloqueadas
  • pero los nombres de host que se resuelven a IPs peligrosas no lo estaban

La segunda mitad del error estaba en la ruta de ejecución.

En executeHttpRequest(), Typebot primero ejecutaba la validación y luego realizaba la petición real con ky(request.url, ...).

Por lo tanto, la secuencia era:

  • validar la cadena de URL
  • aceptar el nombre de host
  • luego más tarde resolver el nombre de host durante la petición saliente real
  • conectarse al destino interno resuelto

Esa es toda la vulnerabilidad.


Por qué esto es un problema de seguridad, no solo un filtrado incompleto

La distinción importante es dónde se tomó la decisión de confianza.

Muchos errores parecen pequeños si se describen mal.

Si describes este como:

"el filtro de nombre de host estaba incompleto"

suena como un problema de calidad.

Ese no es el problema real.

El problema real era:

  • el servidor tomó una decisión de seguridad antes de conocer el destino real
  • la pila de red luego se conectó a otro lugar
  • y la aplicación trató esa petición como válida

Eso no es una debilidad cosmética de filtrado.

Eso es una falla de límite de confianza.

Y debido a que el ejecutor HTTP registraba los datos de respuesta en los registros de ejecución, el problema ni siquiera era ciego en los casos más fuertes.

Así que esto no era solo:

  • "tráfico interno inesperado ocurrió"

Era:

  • ocurrió tráfico interno
  • y el atacante a menudo podía recuperar la prueba y el contenido de la respuesta a través del comportamiento normal de la aplicación

Eso es una verdadera vulnerabilidad SSRF.


Prueba de concepto

Usé dos capas de prueba porque demostraban dos cosas diferentes.

PoC 1: demostración local con resolución controlada

La primera PoC aisló la causa raíz limpiamente.

Usé un pequeño entorno local que:

  • iniciaba un servidor HTTP loopback en 127.0.0.1
  • validaba una URL como http://ssrf-repro.example:18080/...
  • usaba un resolvedor controlado para que ssrf-repro.example se resolviera a 127.0.0.1
  • luego realizaba la petición

Eso demostró la falla exacta:

  • la validación pasó porque el nombre de host no era un valor bloqueado literal
  • la petición posterior aún alcanzó loopback

La salida capturada mostraba:

  • resultado del validador: pasado
  • resultado de la ejecución de la petición: loopback alcanzado
  • cuerpo de la respuesta devuelto desde el servicio loopback

Eso probó directamente la brecha de validación.


PoC 2: ruta de ejecución real de Typebot

La segunda PoC mostró el error a través de la ruta de funcionalidad real que importa.

La reproducción más simple era:

  1. Mapear un nombre de host benigno a loopback en la máquina donde el backend de Typebot resuelve DNS
  2. Iniciar un servicio HTTP local
  3. Crear un bloque Webhook que apunte a ese nombre de host benigno
  4. Activar el bloque a través de una ruta de vista previa autenticada normal o de ejecución en vivo

Un bloque representativo se veía así:

root@kitploit:~
{
  "id": "blk-webhook",
  "type": "Webhook",
  "options": {
    "webhook": {
      "method": "GET",
      "url": "http://ssrf-repro.example:8000/"
    }
  }
}

Con una entrada de archivo hosts como:

root@kitploit:~
127.0.0.1 ssrf-repro.example

el validador aún aceptaba la URL porque:

  • ssrf-repro.example no estaba en blockedHostnames
  • no era localhost
  • parseIPAddress("ssrf-repro.example") devolvió null
  • no ocurrió validación de IP de destino

Luego el cliente HTTP del backend resolvió el nombre de host a 127.0.0.1 y se conectó de todos modos.

Eso estableció la afirmación completa:

  • la lógica de validación vulnerable era accesible en el uso real de la funcionalidad
  • la petición alcanzó una clase de destino bloqueada
  • y la aplicación aún la trató como una petición HTTP saliente exitosa

Por qué se eligieron las dos PoC de esta manera

La primera PoC prueba la causa raíz.

La segunda PoC prueba el impacto en el producto.

Esa división importa.

Si solo muestras:

"este filtro acepta un nombre de host"

no has mostrado suficiente.

Si solo muestras:

"ocurrió una petición interna"

no has aislado el porqué.

El informe más sólido es:

  • la validación basada en nombre de host aceptó un valor que no debería haber sido confiable
  • la resolución DNS luego cambió el significado de seguridad real de ese valor
  • el backend se conectó a un destino bloqueado
  • y la ruta de funcionalidad aún se completó

Esa es la historia completa.


Gravedad y clasificación

Este problema se clasificó razonablemente como Alta.

La clasificación del aviso fue:

  • CWE-918: Server-Side Request Forgery (SSRF)
  • CWE-20: Improper Input Validation
  • CVSS:
root@kitploit:~
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L

Eso tiene sentido.

Esto no era un SSRF no autenticado a nivel de Internet por sí mismo.

Los privilegios requeridos eran Bajos porque el error independiente requería un actor que pudiera configurar o activar un bloque Webhook / Petición HTTP.

Pero dentro de ese límite, el impacto era grave:

  • acceso a loopback
  • acceso a red privada
  • acceso a metadatos
  • y exfiltración de respuesta a través de registros

Eso es un problema SSRF fuerte por sí mismo.

Y se vuelve aún más peligroso cuando se combina con otros errores que amplían la accesibilidad.


Por qué valía la pena informar esto

Algunas personas ven SSRF autenticado y lo subestiman de inmediato.

Eso es un error.

La pregunta real no es:

"¿El atacante había iniciado sesión?"

La pregunta real es:

"¿Podría ese atacante hacer que el servidor se conectara a algún lugar que el modelo de seguridad debía prohibir?"

Aquí, la respuesta fue sí.

El validador afirmaba proteger:

  • servicios de metadatos
  • loopback
  • rangos privados RFC1918
  • rangos locales IPv6

Pero una brecha de resolución de nombres de host permitió que esos mismos destinos volvieran a entrar a través de una representación diferente.

Ese es exactamente el tipo de error que merece un CVE.


Análisis de la corrección

La corrección fue sólida porque corrigió el límite real, no solo un síntoma.

En la implementación parcheada, validateHttpReqUrl() se modificó para resolver nombres de host antes de aprobar la petición.

El validador ahora:

  • importa lookup de node:dns/promises
  • trata la validación como asíncrona
  • resuelve nombres de host no literales antes de permitirlos
  • analiza cada dirección resuelta
  • valida cada dirección resuelta contra los mismos rangos bloqueados

Esa es la corrección correcta porque cambia la decisión de confianza de:

  • "¿el texto del nombre de host se ve bien?"

a:

  • "¿el destino real se resuelve a una dirección permitida?"

Esa es la propiedad de seguridad que debería haber existido desde el principio.

La remediación también agregó cobertura de regresión para:

  • nombres de host que se resuelven a loopback
  • nombres de host que se resuelven al espacio RFC1918
  • hosts internos permitidos para autoalojadores
  • preservación de protecciones no evadibles para objetivos de metadatos y loopback

Ese es el tipo de endurecimiento que quieres en una corrección SSRF real:

  • el límite se corrige
  • el comportamiento previsto se documenta en el código
  • y las pruebas bloquean la clase

El problema se resolvió en Typebot 3.16.0.


Divulgación

Este problema se informó de forma privada a través del flujo de informes de seguridad de GitHub.

El informe incluía:

  • la causa raíz en validateHttpReqUrl()
  • la ruta de ejecución posterior en executeHttpRequest()
  • una estrategia de reproducción realista usando resolución de nombre de host a loopback / objetivos privados
  • y una demostración autocontenida para aislar la brecha de validación

Los mantenedores aceptaron el problema, corrigieron la lógica de validación y la vulnerabilidad se publicó posteriormente como:

CVE-2026-34207

con la corrección lanzada en Typebot 3.16.0.


Lo que realmente enseña este error

La lección clave aquí es simple:

las decisiones de seguridad deben tomarse sobre la misma representación que usará la pila de red.

Eso suena obvio.

Pero muchas protecciones SSRF fallan precisamente porque no siguen esa regla.

  • Una cadena de nombre de host parece segura.
  • DNS cambia su significado.
  • La petición aún sale.

Eso es suficiente.

Este error también refuerza algo importante sobre la revisión SSRF en general:

  • el filtrado de IP literales no es suficiente
  • las listas negras de nombres de host no son suficientes
  • las comprobaciones de IP codificadas no son suficientes

Si no resuelves y validas el destino real, tu filtro SSRF sigue siendo incompleto.

Esa es la verdadera conclusión.


Puntos clave

  • Las defensas SSRF fallan cuando la validación ocurre antes de la resolución del destino
  • La validación del texto del nombre de host no es lo mismo que la validación de la IP de destino
  • Las funcionalidades de Webhook / Petición HTTP son límites de seguridad reales
  • El SSRF autenticado aún puede ser de alta gravedad cuando alcanza metadatos y servicios internos
  • Un informe sólido conecta la causa raíz y el impacto, no solo uno u otro
  • La corrección fue correcta porque movió la decisión al destino resuelto real

Palabras finales

Esta vulnerabilidad no trataba de un payload elegante.

Trataba de hacer la pregunta de límite correcta.

En Typebot, el validador SSRF verificaba primero el texto del nombre de host. El destino real se decidía después mediante DNS. El cliente de red seguía la dirección resuelta.

Esa brecha fue el error.

Por eso esto se convirtió en CVE-2026-34207.

Corregido en Typebot 3.16.0.

Descargar herramienta