FlawOpen

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

● Correspondance FlawOpen : CWE-345 · CVSS 9.9 · Critique
Recherche · FlawOpen

LiteLLM : élévation de privilèges par la clé salt (GHSA-7hp6)

LiteLLM réutilisait le chiffrement des secrets pour les jetons de session de l’interface et de la CLI. Un internal_user authentifié pouvait faire passer des données d’identité qu’il contrôlait par ce chemin et obtenir le rôle proxy_admin, lequel pouvait accéder à l’exécution de commandes via MCP stdio. Le correctif lie les jetons à un préfixe dédié et à un contexte AES-GCM authentifié. Aucun CVE ni exploitation confirmée dans la nature n’est signalé.[1], [2]

💡 Explication en Langage Simple (ELI5)

Un immeuble utilise le même sceau pour fermer une enveloppe de stockage et créer un badge d’administrateur. Un visiteur peut influencer le contenu de l’enveloppe, puis un gardien la prend pour un vrai badge. Le correctif de LiteLLM donne aux badges de session un préfixe distinct et lie cryptographiquement ce préfixe au sceau.[1], [2]

Concepts Clés et Termes

Clé salt
Matériel de clé configuré dans LiteLLM et utilisé par ses fonctions de chiffrement. La faille réutilisait le même chemin sans lier le texte chiffré à sa finalité.[1], [2]
Données supplémentaires authentifiées (AAD)
Données, comme un préfixe de type de jeton, authentifiées par AES-GCM avec le texte chiffré. Une modification ou une absence fait échouer l’authentification.[2]
internal_user et proxy_admin
Rôles LiteLLM. L’avis indique qu’un internal_user authentifié pouvait devenir proxy_admin, le rôle administratif.[1]
MCP stdio
Transport Model Context Protocol qui démarre un processus local et échange des messages via l’entrée et la sortie standard. L’avis indique que proxy_admin pouvait atteindre l’exécution de commandes par ce point d’accès.[1]
CWE-345
Vérification insuffisante de l’authenticité des données. C’est la classification éditoriale principale de FlawOpen ; l’avis cite aussi CWE-269 et CWE-441.[1], [5], [6], [7]

Correspondances de référentiels

  • Correspondance conceptuelle de FlawOpen avec MITRE CWE ; aucun fournisseur ni enregistrement CVE n’a attribué cet identifiant de faiblesse à cette démonstration de recherche. CWE-345

Déroulement de l'Attaque Étape par Étape

Étape 1

Un compte peu privilégié accède à la gestion des clés

La condition initiale de l’avis est un internal_user authentifié. Aucun accès anonyme n’est requis, mais l’acteur doit déjà posséder ce rôle.[1]

Étape 2

Les métadonnées produisent un texte chiffré via le chemin partagé

L’avis indique que des données d’identité contrôlées dans les métadonnées d’une clé pouvaient être chiffrées et renvoyées. La faille est leur acceptation ultérieure comme un autre type de jeton.[1], [2]

Étape 3

Le parseur de session accepte un texte chiffré d’une autre finalité

Avant le correctif, le chiffrement des valeurs et la vérification des sessions partageaient helper et chemin de clé, sans liaison authentifiée à la finalité du jeton. L’identité pouvait être interprétée comme proxy_admin.[1], [2]

Étape 4

L’accès administratif atteint MCP stdio

Avec proxy_admin, l’avis indique que l’acteur pouvait exécuter des commandes via le point d’accès MCP stdio. Il s’agit d’une capacité de processus sur l’hôte, pas d’une commande lancée par le modèle.[1]

Étape 5

La liaison à la finalité rejette la réutilisation

Le correctif utilise litellm_login_ comme AAD AES-GCM et un décodeur dédié. Installez une version corrigée ; désactiver EXPERIMENTAL_UI_LOGIN reste une mitigation temporaire avec des conséquences fonctionnelles.[1], [2], [3], [4]

Analyse de Cause Racine

L’avis BerriAI GHSA-7hp6-4w63-5g45 décrit une confusion d’authentification entre deux finalités. LiteLLM utilisait le helper de chiffrement des valeurs pour les secrets stockés et les jetons de session UI/CLI, tandis que l’authentification de session déchiffrait les valeurs avec le même chemin de clé. Un internal_user pouvait demander une clé dont les métadonnées contenaient des données d’identité sérialisées qu’il contrôlait ; la route de gestion chiffrait puis renvoyait ces données. Présenté comme bearer token, le texte chiffré pouvait être déchiffré par la route de session et interprété comme une identité proxy_admin falsifiée. Cette identité pouvait ensuite accéder à l’exécution de commandes MCP stdio. Le correctif upstream f7cd90f modifie la création et la vérification : préfixe litellm_login_, données AAD AES-GCM liées à ce préfixe et décodeur dédié. La clé salt reste le matériel cryptographique ; la frontière vérifiée est la finalité authentifiée du jeton et le décodeur correspondant. Un texte chiffré pour stockage ne valide donc plus comme jeton de session. L’avis attribue CVSS 3.1 9.9 Critical ; les versions après 1.91.0 sont touchées par défaut et les versions 1.87.0–1.90.x uniquement si EXPERIMENTAL_UI_LOGIN=true. Les versions corrigées listées sont 1.100.4, 1.101.3, 1.102.2, 1.103.1 et 1.104.0rc2 sur leurs branches respectives. La mitigation EXPERIMENTAL_UI_LOGIN=false désactive le chemin vulnérable, mais interrompt aussi le CLI SSO et la connexion Claude Code gateway. Aucun CVE n’est indiqué et aucune exploitation réelle n’est confirmée. L’extrait montre la modification du domaine d’authentification ; ce n’est ni un exploit ni une implémentation complète.[1], [2], [3], [4]

Code Source : Vulnérable vs Sécurisé

Le correctif upstream remplace les helpers génériques aux étapes de création et de vérification du jeton de session. encrypt_bearer_token authentifie le préfixe comme AAD AES-GCM ; decrypt_bearer_token exige ce même préfixe et ces mêmes données. Le texte chiffré de stockage ne peut ainsi pas servir de jeton de connexion. Cet extrait réduit provient du commit cité ; ce n’est pas un système d’authentification autonome. La clé salt partagée ne prouve pas à elle seule qu’une clé distincte soit utilisée pour chaque usage ; la séparation établie ici repose sur le type de jeton authentifié et le décodeur correspondant.[2], [3]

Extrait source: litellm/proxy/auth/auth_checks.py et litellm/proxy/common_utils/encrypt_decrypt_utils.py — extraits réduits du commit upstream f7cd90f

IMPLÉMENTATION VULNÉRABLE
# Avant le correctif : le texte chiffré des valeurs stockées pouvait aussi être émis comme jeton de session.
return encrypt_value_helper(valid_token.model_dump_json(exclude_none=True))

# L’authentification de session déchiffrait avec le helper générique des valeurs.
decrypted_token = decrypt_value_helper(hashed_token, key="ui_hash_key")
PATCH SÉCURISÉ ET ROBUSTE
# Après le correctif : les jetons de session ont leur propre type et AAD.
LITELLM_SESSION_TOKEN_PREFIX = "litellm_login_"
return encrypt_bearer_token(
    valid_token.model_dump_json(exclude_none=True),
    prefix=LITELLM_SESSION_TOKEN_PREFIX,
)

# L’authentification utilise le décodeur correspondant à cet usage.
decrypted_token = decrypt_bearer_token(
    hashed_token, prefix=LITELLM_SESSION_TOKEN_PREFIX
)

Liste de Contrôle de Sécurité pour l'Ingénierie

Sources

← AI Security Directory →