FlawOpen

flawopen.com/AI Security/berriai-litellm-ghsa-7hp6-salt-key-session-token-privilege-escalation

● FlawOpen 매핑: CWE-345 · CVSS 9.9 · 심각
보안 연구 · FlawOpen

LiteLLM: salt key 재사용을 통한 권한 상승 (GHSA-7hp6)

LiteLLM은 저장된 비밀값과 UI·CLI 세션 토큰에 같은 암호화 경로를 사용했습니다. 인증된 internal_user는 자신이 제어하는 신원 데이터를 이 경로에 통과시켜 proxy_admin 권한을 얻을 수 있었고, 해당 권한으로 MCP stdio 명령 실행에 접근할 수 있었습니다. 수정은 전용 접두사와 인증된 AES-GCM 컨텍스트로 토큰 목적을 결합합니다. CVE나 실제 공격에서의 악용은 확인되지 않았습니다.[1], [2]

💡 알기 쉬운 설명 (ELI5)

건물에서 보관 봉투를 봉하고 관리자 출입증을 발급할 때 같은 도장을 사용합니다. 방문자는 봉투의 내용에 영향을 줄 수 있고, 경비원은 나중에 봉투를 진짜 출입증으로 오인합니다. LiteLLM 수정은 세션 출입증에 별도 표시를 붙이고 그 표시를 도장과 암호학적으로 결합합니다.[1], [2]

핵심 개념 및 용어

Salt key
LiteLLM에서 설정하는 암호화 키 자료입니다. 취약점은 암호문을 목적에 결합하지 않은 채 같은 키 경로를 여러 용도로 재사용한 데 있습니다.[1], [2]
인증된 추가 데이터(AAD)
토큰 유형 접두사처럼 AES-GCM이 암호문과 함께 인증하는 데이터입니다. 변경하거나 누락하면 인증이 실패합니다.[2]
internal_user와 proxy_admin
LiteLLM 역할입니다. 권고문은 인증된 internal_user가 관리자 역할인 proxy_admin으로 상승할 수 있었다고 설명합니다.[1]
MCP stdio
로컬 프로세스를 시작하고 표준 입력·출력으로 통신하는 Model Context Protocol 전송 방식입니다. 권고문에 따르면 proxy_admin은 이 endpoint를 통해 명령 실행에 접근할 수 있었습니다.[1]
CWE-345
데이터 진위 검증 부족입니다. FlawOpen이 선택한 대표 편집상 분류이며, 권고문은 CWE-269와 CWE-441도 제시합니다.[1], [5], [6], [7]

프레임워크 매핑

  • MITRE CWE에 대한 FlawOpen의 개념적 매핑입니다. 공급업체나 CVE 레코드가 이 연구 시연에 해당 약점 ID를 지정한 것은 아닙니다. CWE-345

단계별 공격 실행 흐름

단계 1

낮은 권한의 계정이 키 관리 기능에 접근

권고문상 시작 조건은 인증된 internal_user입니다. 익명 접근은 필요 없지만 해당 역할을 이미 보유해야 합니다.[1]

단계 2

metadata가 공통 경로에서 암호문을 생성

권고문은 키 metadata에 넣은 제어 가능한 신원 데이터가 암호화되어 반환될 수 있다고 설명합니다. 문제는 이후 이 암호문을 다른 토큰 유형으로 받아들인 것입니다.[1], [2]

단계 3

세션 parser가 다른 목적의 암호문을 수락

수정 전에는 값 암호화와 세션 검증이 helper와 키 경로를 공유하면서 토큰 목적을 인증된 방식으로 결합하지 않았습니다. 신원 데이터가 proxy_admin으로 해석될 수 있었습니다.[1], [2]

단계 4

관리자 권한이 MCP stdio에 도달

권고문에 따르면 proxy_admin은 MCP stdio endpoint를 통해 명령을 실행할 수 있었습니다. 이는 호스트의 프로세스 권한이며 모델이 직접 명령을 실행하는 것은 아닙니다.[1]

단계 5

목적 결합으로 재사용을 거부

수정은 litellm_login_을 AES-GCM AAD로 사용하고 전용 decoder로 확인합니다. 수정 버전으로 업그레이드하세요. EXPERIMENTAL_UI_LOGIN 비활성화는 기능에 영향을 주는 임시 조치입니다.[1], [2], [3], [4]

근본 원인 분석 (Root Cause)

BerriAI 권고문 GHSA-7hp6-4w63-5g45는 인증 목적을 혼동한 문제를 설명합니다. LiteLLM은 저장된 비밀값과 UI/CLI 세션 토큰 모두에 일반 값 암호화 helper를 사용했고, 세션 인증도 같은 키 경로로 값을 복호화했습니다. 인증된 internal_user는 자신이 제어하는 직렬화된 신원 데이터를 key metadata에 넣어 API key를 요청할 수 있었으며, 관리 경로는 그 값을 암호화해 반환했습니다. 해당 암호문을 bearer token으로 제시하면 세션 경로가 이를 복호화해 위조된 proxy_admin 신원으로 해석할 수 있었습니다. 이 권한은 MCP stdio 명령 실행으로 이어질 수 있습니다. 상류 수정 f7cd90f는 토큰 발급과 검증을 변경해 litellm_login_ 접두사, 해당 접두사에 결합된 AES-GCM AAD, 전용 decoder를 사용합니다. salt key는 여전히 키 자료이며, 확인된 경계는 암호학적으로 인증된 토큰 목적과 대응 decoder입니다. 따라서 저장 값 암호문은 세션 토큰으로 검증되지 않습니다. 권고문은 CVSS 3.1 9.9 Critical로 평가하고, 1.91.0 이후 버전은 기본 설정에서 영향받으며 1.87.0–1.90.x는 EXPERIMENTAL_UI_LOGIN=true일 때만 영향받는다고 합니다. 브랜치별 수정 버전은 1.100.4, 1.101.3, 1.102.2, 1.103.1, 1.104.0rc2입니다. 임시 조치 EXPERIMENTAL_UI_LOGIN=false는 취약한 로그인 경로를 끄지만 CLI SSO와 Claude Code gateway 로그인도 중단시킵니다. CVE는 없고 실제 악용도 확인되지 않았습니다. 코드 비교는 상류 인증 경계 변경을 보여주는 축약본이며 exploit이나 완전한 인증 구현이 아닙니다.[1], [2], [3], [4]

소스 코드 비교: 취약한 구현 vs 보안 패치

상류 수정은 세션 토큰을 만들고 인증하는 지점에서 일반 값 helper를 교체합니다. encrypt_bearer_token은 접두사를 AES-GCM AAD로 인증하고, decrypt_bearer_token은 같은 접두사와 AAD를 요구합니다. 따라서 저장 암호문을 로그인 토큰으로 재사용할 수 없습니다. 인용한 commit의 축약 코드이며 독립적인 인증 구현은 아닙니다. 공유 salt 키만으로는 용도별 전용 키가 있다고 입증되지 않습니다. 여기서 확인된 분리는 인증된 토큰 유형과 그에 맞는 디코더에서 비롯됩니다.[2], [3]

소스 코드 발췌: litellm/proxy/auth/auth_checks.py 및 litellm/proxy/common_utils/encrypt_decrypt_utils.py — upstream commit f7cd90f의 축약 발췌

취약한 구현
# 수정 전에는 저장 값의 암호문도 세션 토큰으로 발급되었습니다.
return encrypt_value_helper(valid_token.model_dump_json(exclude_none=True))

# 세션 인증은 일반 값 helper를 사용해 복호화했습니다.
decrypted_token = decrypt_value_helper(hashed_token, key="ui_hash_key")
보안 강화 패치
# 수정 후 세션 토큰에는 전용 유형과 AAD가 있습니다.
LITELLM_SESSION_TOKEN_PREFIX = "litellm_login_"
return encrypt_bearer_token(
    valid_token.model_dump_json(exclude_none=True),
    prefix=LITELLM_SESSION_TOKEN_PREFIX,
)

# 인증에는 해당 용도에 맞는 디코더를 사용합니다.
decrypted_token = decrypt_bearer_token(
    hashed_token, prefix=LITELLM_SESSION_TOKEN_PREFIX
)

엔지니어링 및 시스템 보안 강화 체크리스트

출처

← AI Security Directory →