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-14361 — El helper writeToFile de Consul Template abría directamente un destino proporcionado por el operador y seguía los componentes de ruta enlazados, permitiendo que la salida renderizada escapara del directorio previsto y sobrescribiera un archivo preexistente. | Kitploit
Herramientas/GitHubGitHub/0xmrma/cve-2026-14361
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónAprendizaje y Educación
GitHub0xmrma/cve-2026-14361

CVE-2026-14361

El helper writeToFile de Consul Template abría directamente un destino proporcionado por el operador y seguía los componentes de ruta enlazados, permitiendo que la salida renderizada escapara del directorio previsto y sobrescribiera un archivo preexistente.

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

El helper writeToFile de Consul Template abría directamente un destino proporcionado por el operador y seguía los componentes de ruta con enlaces, lo que permitía que la salida renderizada escapara del directorio previsto y sobrescribiera un archivo preexistente.

Introducción

Encontré este problema al revisar HashiCorp Consul Template, con una pregunta directa de seguridad del sistema de archivos en mente:

Si writeToFile recibe una ruta que parece estar dentro del directorio previsto, ¿verifica dónde escribirá realmente el sistema de archivos los datos?

En este caso, la respuesta fue no.

El helper de plantilla writeToFile abría directamente la ruta final proporcionada por el usuario mediante os.Create() u os.OpenFile().

Esas operaciones seguían enlaces simbólicos, junctions de directorio y redirecciones equivalentes del sistema de archivos ya presentes en la ruta de destino.

Eso significaba que la cadena de ruta podía permanecer bajo la raíz prevista por el operador mientras que la escritura real aterrizaba en otro lugar.

En mi prueba de concepto controlada, un directorio padre con enlace redirigió la salida renderizada fuera del árbol previsto y provocó que un archivo de destino preexistente fuera sobrescrito.

Ese problema se convirtió en CVE-2026-14361.

Boletín de HashiCorp: HCSEC-2026-20
Boletín de IBM: boletín de seguridad CVE-2026-14361
CVE: CVE-2026-14361
Corregido en: 0.42.1

photo0


Cadena de ataque

el destino proporcionado por el operador aparece dentro de la raíz prevista -> el atacante coloca de antemano un componente padre o final con enlace -> writeToFile abre la ruta directamente -> el sistema de archivos resuelve la escritura fuera del directorio previsto -> el secreto renderizado es redirigido -> un objetivo preexistente puede ser sobrescrito


Qué hace writeToFile

Consul Template renderiza datos de fuentes como Consul y Vault.

El helper writeToFile permite que una plantilla escriba contenido seleccionado en un archivo local separado mientras aplica un propietario, grupo y modo de permisos solicitados.

La documentación de HashiCorp demuestra específicamente el helper con material PKI:

root@kitploit:~
private key -> writeToFile /my/path/to/cert.key
certificate authority -> writeToFile /my/path/to/cert.pem
certificate -> append to /my/path/to/cert.pem

Eso lo convierte en algo más que un helper de salida ordinario.

El contenido que cruza este límite puede incluir:

  • claves privadas
  • certificados
  • secretos obtenidos de Vault
  • valores de configuración
  • credenciales de servicio

La pregunta importante no era si writeToFile podía crear un nombre de archivo solicitado.

La pregunta real era:

¿El proceso escribe en la ubicación del sistema de archivos prevista por el operador, o simplemente en el objeto al que la ruta se resuelve en el momento de la apertura?

En las versiones vulnerables, confiaba en esto último.


Por qué valía la pena examinar esta superficie

Los helpers de escritura son superficies de seguridad de alto valor porque cruzan de los datos de la aplicación a la mutación del sistema de archivos.

Los fallos interesantes a menudo no son el clásico traversal ../.

Son fallos de resolución:

  • la cadena parece segura
  • el árbol de directorios parece controlado por el operador
  • un componente con enlace cambia el destino real
  • la llamada de apertura sigue esa redirección automáticamente

Eso es especialmente importante cuando el proceso se ejecuta con más privilegios del sistema de archivos que el atacante.

Un atacante local con pocos privilegios puede no ser capaz de sobrescribir un archivo sensible directamente.

Pero si puede influir en un componente de ruta bajo un directorio de escritura previsto, un proceso de Consul Template más privilegiado puede realizar la escritura por él.

Ese fue el límite en el que me centré.


El límite en el que me centré

No abordé esto como una revisión genérica de path traversal.

La ruta proporcionada no necesitaba segmentos ...

Podía permanecer léxicamente dentro de la raíz prevista todo el tiempo.

La pregunta más sólida era:

¿Se rechazan los componentes de destino con enlaces antes de que se escriba contenido sensible?

Esa pregunta importa para ambos casos:

  • un nombre de archivo final con enlace
  • un componente de directorio con enlace que redirige toda la ruta restante

El segundo caso es especialmente útil porque los registros y la configuración siguen mostrando una ruta de apariencia inocente bajo el directorio esperado.

El sistema de archivos la resuelve en otro lugar.


Causa raíz

La causa raíz era la creación directa de archivos basada en rutas sin validación consciente de enlaces.

En la revisión probada, writeToFile() seleccionaba uno de dos caminos de apertura.

El modo de append usaba:

root@kitploit:~
f, err = os.OpenFile(
    path,
    os.O_APPEND|os.O_WRONLY|os.O_CREATE,
    perm,
)

El modo de escritura normal usaba:

root@kitploit:~
dirPath := filepath.Dir(path)

if _, err := os.Stat(dirPath); err != nil {
    err := os.MkdirAll(dirPath, os.ModePerm)
    if err != nil {
        return "", err
    }
}

f, err = os.Create(path)

Ninguno de los dos caminos rechazaba componentes de destino con enlaces antes de abrir el archivo.

Eso importa porque:

  • os.Create(path) sigue las redirecciones existentes del sistema de archivos y trunca el archivo resuelto
  • os.OpenFile(path, ...) sigue los componentes de ruta con enlaces durante el modo append
  • un directorio con enlace cambia dónde se resuelve el nombre de archivo final
  • un componente final con enlace puede redirigir la apertura a un archivo existente diferente

La misma suposición basada en rutas continuaba después de la escritura.

La propiedad y los permisos se aplicaban usando la ruta nuevamente:

root@kitploit:~
err = os.Chown(path, uid, gid)
err = os.Chmod(path, perm)

Eso significaba que las operaciones de metadatos también estaban vinculadas a un nombre de ruta mutable en lugar del descriptor de archivo ya abierto.

Por qué esto es explotable

Porque el atacante puede preparar la redirección antes de que writeToFile se ejecute.

No se requiere una condición de carrera probabilística para el ataque básico.

La secuencia es sencilla:

  • el operador configura un destino bajo una raíz esperada
  • el atacante obtiene suficiente acceso local para crear o reemplazar un componente con enlace debajo de esa ubicación de escritura
  • la cadena de ruta todavía parece permanecer bajo la raíz prevista
  • writeToFile la abre directamente
  • el sistema operativo sigue el enlace o junction
  • la salida renderizada aterriza en el destino resuelto
  • si ese destino ya existe, el modo de creación normal lo trunca y sobrescribe

Esa es toda la vulnerabilidad.


Qué hace que esto sea un problema de seguridad, no solo el comportamiento normal de los symlinks

Es cierto que los sistemas operativos normalmente siguen los symlinks durante las aperturas de archivos basadas en rutas.

Eso no hace que este sea un comportamiento seguro de la aplicación.

La pregunta de seguridad no es:

"¿Go se comportó como está documentado?"

La pregunta real es:

¿Un helper que escribe datos sensibles renderizados verificó que el destino resuelto coincidiera con la ubicación prevista por el operador?

En las versiones vulnerables, no lo hizo.

Esa distinción importa porque Consul Template puede ejecutarse:

  • como un servicio de larga duración
  • con acceso a secretos derivados de Vault
  • bajo una cuenta elevada
  • con acceso de escritura que el atacante local no tiene directamente

Seguir una redirección del sistema de archivos posicionada por el atacante en ese contexto crea un problema real de privilegios y de límite de confianza.


Prueba de concepto

Construí un reproductor independiente alrededor del comportamiento exacto de writeToFile en el commit probado.

La configuración controlada usaba:

  • una raíz de salida prevista
  • un directorio externo fuera de esa raíz
  • un componente padre con enlace debajo de la raíz prevista
  • un archivo de destino preexistente en el directorio redirigido
  • contenido secreto controlado pasado a writeToFile

El flujo de reproducción fue:

  1. Crear la raíz de salida prevista.
  2. Crear un directorio de destino externo separado.
  3. Colocar un archivo de destino preexistente en el directorio externo.
  4. Crear un directorio padre con enlace bajo la raíz prevista que se resuelva al directorio externo.
  5. Construir la ruta de destino final usando el padre con enlace mientras se mantiene la cadena de ruta bajo la raíz prevista.
  6. Invocar la ruta de escritura vulnerable con contenido secreto controlado.
  7. Resolver e inspeccionar el destino real.
  8. Comparar los bytes del archivo final y el SHA-256 con la entrada secreta.

El comportamiento observado fue:

  • la cadena de destino prevista permaneció bajo la raíz prevista
  • el padre con enlace redirigió la escritura real fuera de esa raíz
  • writeToFile siguió la redirección
  • el objetivo externo preexistente fue sobrescrito
  • el archivo externo final coincidió exactamente con la entrada secreta según SHA-256

Eso estableció ambas partes de la afirmación:

  • la salida podía escapar del árbol de directorios previsto
  • un archivo existente en el destino resuelto podía ser sobrescrito

Por qué se eligió el PoC de esta manera

Un symlink en el componente final ya demostraría la práctica insegura de seguir enlaces.

Pero un componente padre con enlace prueba un punto operativo más sólido:

  • el nombre de archivo configurado puede parecer completamente normal
  • la ruta puede permanecer léxicamente bajo la raíz prevista
  • la redirección puede ocurrir más arriba en la ruta
  • la escritura final puede aterrizar igualmente en otro lugar

El objetivo preexistente también importaba.

Sin él, el PoC mostraría solo una creación inesperada de archivos.

Al comenzar con un archivo existente y verificar su hash final, la reproducción demostró directamente el comportamiento de sobrescritura.

Eso hizo que el resultado fuera más concreto que una afirmación solo basada en el código fuente.


Requisitos de explotación y alcance

Este problema requiere influencia local en el sistema de archivos.

Un atacante necesita suficiente acceso para crear o modificar un symlink, junction de directorio o redirección equivalente en o debajo de la ubicación de escritura prevista.

El proceso de Consul Template debe entonces escribir a través de esa ruta.

El impacto depende en gran medida de los privilegios del proceso y del contenido renderizado.

Los resultados prácticos incluyen:

  • redirigir la salida de la plantilla fuera del directorio previsto por el operador
  • colocar datos sensibles renderizados en una ubicación legible por el atacante
  • sobrescribir un archivo preexistente en el destino resuelto
  • aumentar el impacto cuando el proceso se ejecuta con privilegios elevados
  • aumentar el riesgo de confidencialidad cuando el contenido contiene claves, certificados o secretos

Esto no era una escritura arbitraria remota no autenticada desde una instalación predeterminada.

Pero era un claro fallo local de límite de confianza con impacto significativo en implementaciones privilegiadas o con sistemas de archivos compartidos.


Severidad y clasificación

HashiCorp clasificó el problema como:

  • CWE-59: Resolución incorrecta de enlaces antes del acceso al archivo
  • CVSS 3.1:
root@kitploit:~
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N

La puntuación base publicada es:

root@kitploit:~
4.7 / Medium

Ese vector refleja:

  • acceso de atacante local
  • se necesitan pocos privilegios para influir en la ruta
  • alta complejidad de ataque
  • sin interacción del usuario
  • potencial alto impacto de confidencialidad cuando la salida sensible renderizada es redirigida

Los boletines oficiales también documentan explícitamente que la escritura redirigida puede sobrescribir un archivo preexistente.

La puntuación es moderada porque la explotación depende de condiciones locales de control de rutas, no porque el efecto en el sistema de archivos sea teórico.


Versiones afectadas

El boletín de HashiCorp enumera:

root@kitploit:~
Affected: consul-template up to and including 0.42.0
Fixed:    consul-template 0.42.1

La corrección se publicó en la versión 0.42.1 el 8 de julio de 2026.


Análisis de la corrección

El parche 0.42.1 endureció la ruta de escritura en varias capas.

1. Rechazar componentes de destino con enlaces

El helper parcheado usa os.Lstat() para inspeccionar:

  • el directorio padre inmediato
  • el componente de destino final

y rechaza esos componentes cuando son enlaces.

Eso cierra los casos de redirección directa del padre y de symlink del archivo final cubiertos por el informe y las pruebas de regresión.

2. Usar O_NOFOLLOW para la apertura final donde sea compatible

En plataformas Unix compatibles, el destino se abre con O_NOFOLLOW.

Eso hace que la propia apertura falle si el componente final se convierte en un symlink entre la verificación previa y la apertura.

Esto es importante porque una verificación previa por sí sola puede crear otra ventana TOCTOU.

La implementación específica de la plataforma es un no-op en Windows, donde O_NOFOLLOW no está disponible a través del mismo mecanismo.

3. Aplicar metadatos a través del descriptor abierto

El parche reemplazó las operaciones de propiedad y modo basadas en rutas por operaciones basadas en el descriptor:

root@kitploit:~
f.Chown(uid, gid)
f.Chmod(perm)

Eso vincula los cambios de metadatos al archivo que realmente se abrió en lugar de resolver la ruta nuevamente más tarde.

4. Fallar de forma segura ante errores de stat inesperados

El helper ahora crea el directorio padre solo cuando el fallo de stat es genuinamente os.IsNotExist.

Otros errores, como fallos de permisos, se devuelven en lugar de continuar hacia la ruta de escritura.

Cobertura de regresión

El parche añadió pruebas específicas para:

  • rechazo de symlink en el componente final
  • rechazo de directorio padre con enlace
  • éxito de rutas normales
  • rechazo de symlink final en modo append
  • verificación de bytes de que el objetivo sensible permanece sin cambios

Un límite importante de la corrección

La discusión pública del parche documenta una limitación importante con claridad.

La nueva validación verifica:

  • el directorio padre inmediato
  • el componente de ruta final

No recorre ni rechaza todos los ancestros de nivel superior.

Los mantenedores eligieron ese límite porque writeToFile no tiene una raíz de sandbox configurada para anclar una verificación completa de contención, y los sistemas operativos comunes pueden incluir enlaces gestionados legítimos en prefijos de ruta, como /var -> /private/var en macOS.

O_NOFOLLOW también protege el componente final, no todos los directorios ancestros.

Eso no cambia el estado de la vulnerabilidad reportada ni la versión oficial corregida.

Sí aclara la propiedad de seguridad exacta que entrega el parche:

  • las rutas de redirección reportadas de padre inmediato y componente final se rechazan
  • las operaciones de metadatos están vinculadas al descriptor abierto
  • el helper no pretende proporcionar un sandbox general del sistema de archivos para cada ruta ancestra

Esa distinción vale la pena conservarla en un informe técnico.


Divulgación

Reporté este problema de forma privada a HashiCorp Security el 21 de marzo de 2026 como un segundo hallazgo independiente de Consul Template.

El informe incluía:

  • análisis de causa raíz a nivel de código fuente
  • una prueba de concepto independiente
  • salida de ejecución
  • evidencia de la ruta prevista y la resuelta
  • comportamiento del archivo antes/después
  • confirmación SHA-256 de que el objetivo redirigido coincidía con la entrada secreta
  • detalles de la revisión afectada

El correo de seguimiento original no estaba presente en la cola de informes del equipo de seguridad, probablemente porque fue atrapado por un filtro de spam de la lista de correo.

Después de que reenvié el informe completo, HashiCorp se puso en contacto con el equipo de ingeniería y lo investigó por separado del primer problema de Consul Template.

HashiCorp corrigió la vulnerabilidad en 0.42.1 y publicó HCSEC-2026-20 el 8 de julio de 2026.

IBM publicó un boletín de seguridad correspondiente para el mismo CVE.

Ambos boletines oficiales reconocieron el informe como:

Mohamed Abdelaal (0xmrma)


Qué enseña realmente este bug

La lección clave es simple:

una cadena de ruta no es lo mismo que el objeto del sistema de archivos que nombra

Esa distinción importa siempre que un código privilegiado escribe rutas influenciadas por el atacante.

Verificar que una cadena comienza con un directorio previsto no es suficiente.

Incluso una ruta limpia sin secuencias de traversal puede resolverse en otro lugar a través de:

  • enlaces simbólicos
  • junctions de directorio
  • redirecciones de montajes
  • componentes de ruta mutables

La operación sensible debe estar vinculada a un destino cuya identidad haya sido validada en el límite correcto.

Este problema también refuerza una regla más amplia:

cuando ya tienes un descriptor de archivo abierto, aplica las operaciones sensibles de seguridad a través de ese descriptor en lugar de resolver la ruta nuevamente

Eso es exactamente por qué los cambios de Chown y Chmod basados en el descriptor importan.


Puntos clave

  • writeToFile está documentado para material sensible como certificados y claves privadas
  • las versiones vulnerables abrían el destino directamente con os.Create u os.OpenFile
  • los componentes padre y final con enlaces podían redirigir la escritura real
  • la ruta configurada podía permanecer bajo la raíz prevista mientras el objetivo resuelto estaba fuera de ella
  • el modo de creación normal podía truncar y sobrescribir un objetivo preexistente
  • Chown y Chmod basados en rutas introducían una confianza adicional en rutas mutables
  • el PoC demostró la redirección y sobrescritura con comparación SHA-256 byte a byte
  • la versión 0.42.1 añadió verificaciones de enlaces, O_NOFOLLOW donde es compatible, operaciones de metadatos basadas en el descriptor y pruebas de regresión

Palabras finales

Esta vulnerabilidad no se trataba de traversal ../.

La cadena de ruta parecía correcta.

El destino del sistema de archivos no lo era.

Consul Template aceptó la ruta prevista por el operador, siguió una redirección posicionada por el atacante y escribió el contenido renderizado en un archivo diferente.

Por eso se convirtió en CVE-2026-14361.

Corregido en consul-template 0.42.1.

Descargar herramienta