FlawOpen

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

● Mapeamento da FlawOpen: CWE-345 · CVSS 9.9 · Crítica
Pesquisa · FlawOpen

LiteLLM: escalada de privilégios por chave salt (GHSA-7hp6)

O LiteLLM reutilizava a criptografia de segredos para tokens de sessão da interface e do CLI. Um internal_user autenticado podia fazer dados de identidade controlados por ele passarem por esse caminho e obter proxy_admin; essa função podia alcançar execução de comandos via MCP stdio. A correção usa um prefixo próprio e contexto autenticado AES-GCM. Não há CVE nem exploração confirmada em campo.[1], [2]

💡 Explicação em Linguagem Simples (ELI5)

Um prédio usa o mesmo selo para fechar um envelope de armazenamento e emitir um crachá de administrador. Um visitante consegue influenciar o conteúdo do envelope, e o guarda depois o confunde com um crachá legítimo. A correção do LiteLLM dá aos crachás de sessão um rótulo próprio e vincula esse rótulo criptograficamente ao selo.[1], [2]

Conceitos Centrais e Termos

Chave salt
Material de chave configurado no LiteLLM e usado por seus helpers criptográficos. A falha reutilizava o caminho da chave sem vincular o ciphertext ao uso pretendido.[1], [2]
Dados adicionais autenticados (AAD)
Dados, como um prefixo de tipo de token, autenticados pelo AES-GCM junto com o ciphertext. Se forem alterados ou omitidos, a autenticação falha.[2]
internal_user e proxy_admin
Funções do LiteLLM. O aviso informa que um internal_user autenticado podia escalar para proxy_admin, a função administrativa.[1]
MCP stdio
Transporte do Model Context Protocol que inicia um processo local e troca mensagens pela entrada e saída padrão. O aviso diz que o proxy_admin podia alcançar execução de comandos por esse endpoint.[1]
CWE-345
Verificação insuficiente da autenticidade dos dados. Esta é a classificação editorial principal da FlawOpen; o aviso também lista CWE-269 e CWE-441.[1], [5], [6], [7]

Mapeamentos de frameworks

  • Mapeamento conceitual da FlawOpen para o MITRE CWE; nenhum fornecedor ou registro CVE atribuiu este identificador de fraqueza a esta demonstração de pesquisa. CWE-345

Fluxo de Ataque Passo a Paso

Passo 1

Uma conta de baixo privilégio acessa o gerenciamento de chaves

A condição inicial indicada é um internal_user autenticado. Não é necessário acesso anônimo, mas o ator já precisa ter essa função.[1]

Passo 2

A metadata gera ciphertext no caminho compartilhado

O aviso diz que dados de identidade controlados pelo usuário na metadata de uma chave podiam ser criptografados e devolvidos. O problema é aceitar depois esse ciphertext como outro tipo de token.[1], [2]

Passo 3

O autenticador de sessão aceita ciphertext de outra finalidade

Antes da correção, a criptografia de valores e a verificação de sessão compartilhavam helper e caminho de chave sem vincular criptograficamente a finalidade do token. A identidade podia ser interpretada como proxy_admin.[1], [2]

Passo 4

O acesso administrativo alcança MCP stdio

Com proxy_admin, o aviso diz que o ator podia executar comandos pelo endpoint MCP stdio. Isso é capacidade de processo no host, não um comando executado pelo modelo.[1]

Passo 5

O vínculo de finalidade rejeita a reutilização

A correção usa litellm_login_ como AAD AES-GCM e um decodificador específico. Atualize para uma versão corrigida; desativar EXPERIMENTAL_UI_LOGIN é apenas uma mitigação temporária com impacto funcional.[1], [2], [3], [4]

Análise de Causa Raiz

O aviso GHSA-7hp6-4w63-5g45 da BerriAI descreve uma falha de autenticação entre finalidades. O LiteLLM usava o helper de criptografia de valores para segredos armazenados e tokens de sessão da interface e do CLI; a autenticação da sessão decifrava os valores pelo mesmo caminho de chave. Um internal_user podia solicitar uma chave cuja metadata contivesse dados de identidade serializados e controlados por ele; a rota de gerenciamento criptografava e devolvia esse valor. Quando o ciphertext era apresentado como bearer token, a rota de sessão podia decifrá-lo e interpretar a identidade forjada como proxy_admin, que podia chegar à execução de comandos MCP stdio. A correção upstream f7cd90f muda a criação e validação dos tokens: usa o prefixo litellm_login_, AAD AES-GCM vinculado ao prefixo e um decodificador específico. A chave salt continua sendo material de chave; a fronteira demonstrada é a finalidade autenticada do token e o decodificador correspondente. Assim, ciphertext de valores armazenados não valida como token de sessão. O aviso atribui CVSS 3.1 9.9 Critical; versões posteriores à 1.91.0 são afetadas por padrão e 1.87.0–1.90.x apenas quando EXPERIMENTAL_UI_LOGIN=true. Correções listadas: 1.100.4, 1.101.3, 1.102.2, 1.103.1 e 1.104.0rc2 em suas respectivas linhas. A mitigação temporária EXPERIMENTAL_UI_LOGIN=false desativa a rota vulnerável, mas também interrompe CLI SSO e login do Claude Code gateway. O aviso não lista CVE nem confirma exploração em campo. O trecho de código mostra a alteração de domínio de autenticação upstream; não é uma exploração nem substitui a implementação completa.[1], [2], [3], [4]

Código-Fonte: Vulnerável vs. Seguro

O patch upstream substitui o criptografador e decodificador genéricos nos pontos de criação e autenticação do token de sessão. encrypt_bearer_token autentica o prefixo como AAD AES-GCM; decrypt_bearer_token exige o mesmo prefixo e AAD. Assim, ciphertext de armazenamento não pode ser reinterpretado como token de login. Este é um trecho reduzido do commit, não código de autenticação independente. A chave salt compartilhada, por si só, não comprova uma chave exclusiva por finalidade; a separação confirmada aqui é o tipo de token autenticado e o decodificador correspondente.[2], [3]

Trecho de origem: litellm/proxy/auth/auth_checks.py e litellm/proxy/common_utils/encrypt_decrypt_utils.py — trechos reduzidos do commit upstream f7cd90f

IMPLEMENTAÇÃO VULNERÁVEL
# Antes da correção: ciphertext de valores armazenados também era emitido como token de sessão.
return encrypt_value_helper(valid_token.model_dump_json(exclude_none=True))

# A autenticação da sessão descriptografava usando o helper genérico de valores.
decrypted_token = decrypt_value_helper(hashed_token, key="ui_hash_key")
PATCH SEGURO E ROBUSTO
# Após a correção: tokens de sessão têm tipo e AAD próprios.
LITELLM_SESSION_TOKEN_PREFIX = "litellm_login_"
return encrypt_bearer_token(
    valid_token.model_dump_json(exclude_none=True),
    prefix=LITELLM_SESSION_TOKEN_PREFIX,
)

# A autenticação usa o decodificador correspondente à finalidade.
decrypted_token = decrypt_bearer_token(
    hashed_token, prefix=LITELLM_SESSION_TOKEN_PREFIX
)

Lista de Verificação de Segurança para Engenharia

Fontes

← AI Security Directory →