flawopen.com/AI Security/berriai-litellm-ghsa-7hp6-salt-key-session-token-privilege-escalation
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]
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]
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
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]
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]
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
# 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")
# 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
- ✓Mettez chaque déploiement LiteLLM à jour vers une version corrigée de sa branche et vérifiez le paquet ou l’image réellement résolus, sans vous fier à un tag flottant.[1], [3], [4]
- ✓Pour les versions 1.87.0–1.90.x, vérifiez si EXPERIMENTAL_UI_LOGIN était activé ; l’avis indique que seul ce cas est touché.[1]
- ✓Si la mise à jour immédiate est impossible, définissez
EXPERIMENTAL_UI_LOGIN=falsetemporairement et prévoyez la perte documentée du CLI SSO et de la connexion Claude Code gateway.[1] - ✓Ajoutez un test qui vérifie le rejet du ciphertext stocké par le décodeur de session et l’acceptation d’un jeton de session valide et non expiré.[2]
- ✓Liez le ciphertext à sa finalité : authentifiez le préfixe comme AAD AES-GCM à l’émission et à la vérification ; n’utilisez pas la sortie d’un helper générique comme identité.[2]
- ✓Limitez la gestion des clés et la configuration MCP stdio aux rôles nécessaires et exécutez le proxy avec des privilèges système minimaux.[1]
- ✓Analyse de FlawOpen : instrumentez l’audit d’authentification du déploiement pour enregistrer le principal, le rôle résolu, le type de jeton, l’heure et l’identifiant de requête, sans conserver les bearer tokens ni les textes chiffrés ; testez le schéma de l’événement. Ajoutez un test d’alerte lorsqu’un processus du proxy LiteLLM lance un enfant MCP stdio, puis corrélez les événements d’authentification et de processus pendant l’enquête. Ce sont des recommandations de détection côté déploiement, pas des signaux de journal confirmés par l’éditeur.
- ✓Suivez l’identifiant GHSA-7hp6-4w63-5g45 : l’avis ne mentionne aucun CVE et les sources consultées ne confirment pas d’exploitation réelle.[1]
Sources
- BerriAI LiteLLM security advisory GHSA-7hp6-4w63-5g45
- LiteLLM upstream session-token fix f7cd90f
- LiteLLM v1.100.4 release notes: UI and CLI session-token format
- LiteLLM v1.104.0 release notes: session-token format and upgrade behavior
- MITRE CWE-345: Insufficient Verification of Data Authenticity
- MITRE CWE-269: Improper Privilege Management
- MITRE CWE-441: Unintended Proxy or Intermediary