Threat Advisories

Quand les scanners de sécurité deviennent l'arme : une décomposition de l'attaque de la chaîne d'approvisionnement de LiteLLM

Rédigé par Integrity360 | 25 mars 2026 15:49:12

LiteLLM est une bibliothèque Python open-source très populaire et un serveur proxy qui fournit une interface unifiée pour appeler plus de 100+ Large Language Model (LLM) APIs, tels que OpenAI, Anthropic, Bedrock, et VertexAI, en utilisant le format d'entrée/sortie standard OpenAI. Il simplifie l'intégration de plusieurs LLM, en offrant des fonctionnalités telles que le repli automatique, les tentatives et le suivi des coûts. Parce qu'il fonctionne comme une passerelle API, il agit comme un agrégateur d'informations d'identification par conception, en conservant de manière sécurisée les clés API pour divers fournisseurs LLM.

Vue d'ensemble

LiteLLM est largement déployé par des organisations telles que Stripe, Netflix, et Google ADK. En outre, il gère plus de 95 millions de téléchargements mensuels et est largement utilisé comme dépendance transitive dans les principaux cadres d'agents d'intelligence artificielle, y compris CrewAI, DSPy, Opik, Browser-Use, MLflow et OpenHands.

Un groupe d'acteurs de la menace financièrement motivés, connu sous le nom de TeamPCP (également suivi sous les noms de DeadCatx3, PCPcat, ShellForce et CipherForce), a exécuté une attaque de la chaîne d'approvisionnement logicielle critique sur le paquet officiel `litellm` sur le Python Package Index (PyPI). TeamPCP, qui collaborerait avec le groupe d'extorsion LAPSUS$, a ciblé les références de publication PyPI du PDG de LiteLLM et de son principal mainteneur, Krrish Dholakia.

Qui et qu'est-ce qui a été affecté ?

Les attaquants ont publié deux versions malveillantes (1.82.7 et 1.82.8) directement sur PyPI, en contournant complètement le processus officiel de publication CI/CD de GitHub :

    • La version 1.82.7 incluait une charge utile injectée codée en base64 dans `litellm/proxy/proxy_server.py` qui s'exécutait de manière malveillante chaque fois que le module était importé.
    • La version 1.82.8 incluait un fichier `litellm_init.pth` très dangereux placé à la racine de la roue. Les fonctions de configuration du chemin natif de Python traitent automatiquement les fichiers `.pth` au démarrage de l'interpréteur. Cela signifie que le malware s'exécute en arrière-plan à chaque fois qu'un processus Python démarre, que l'utilisateur ait explicitement importé LiteLLM ou non.

Toute organisation, développeur, pipeline CI/CD, ou processus de construction Docker qui a exécuté `pip install litellm` (ou l'a tiré comme une dépendance transitive non épinglée) le 24 mars 2026, entre 10:39 UTC et approximativement 16:00 UTC, est affecté.

Qui n'est pas affecté: Les utilisateurs de l'image Docker officielle du Proxy LiteLLM (`ghcr.io/berriai/litellm`) et de LiteLLM Cloud n'ont pas été compromis, car leurs dépendances ont été strictement épinglées à des versions sûres.

Le malware a déclenché une attaque dévastatrice en trois étapes :

    • Récolte systématique d'informations d'identification: Il a balayé les systèmes affectés et a collecté les clés d'API LLM, les clés SSH, les identifiants cloud AWS/GCP/Azure, les jetons de compte de service Kubernetes, les jetons d'authentification du registre Docker, les chaînes de connexion aux bases de données, les identifiants Git, les historiques de shell, les secrets CI/CD et les portefeuilles de crypto-monnaies.
    • Exfiltration: Les données volées ont été regroupées dans une archive (`tpcp.tar.gz`), chiffrées à l'aide d'un schéma hybride AES-256 et RSA-4096, et envoyées silencieusement à `models.litellm[.]cloud` contrôlé par l'attaquant.
    • Mouvement latéral et persistance: Sur les clusters Kubernetes, il a utilisé des jetons de compte de service accessibles pour lire tous les secrets du cluster et déployer un pod `alpine:latest` (`node-setup-*`) hautement privilégié sur chaque nœud. Il a ensuite installé une porte dérobée persistante (`sysmon.py` et `sysmon.service`) qui interroge périodiquement `checkmarx[.]zone/raw` pour télécharger et exécuter des charges utiles arbitraires de second niveau provenant des attaquants.

Chronologie des événements

    • Fin février 2026: Un bot IA autonome nommé "hackerbot-claw" a exploité un flux de demandes d'extraction mal configuré dans le dépôt Trivy d'Aqua Security, en volant un jeton GitHub privilégié.
    • 19 mars 2026: TeamPCP a utilisé l'accès résiduel de la violation de Trivy pour distribuer un binaire Trivy de vol d'informations d'identification et des actions GitHub empoisonnées. Parce que LiteLLM a utilisé Trivy dans son propre flux de travail d'analyse de sécurité CI/CD sans épingler la version, le scanner Trivy compromis a récolté silencieusement le jeton `PYPI_PUBLISH` de LiteLLM.
    • 20-23 mars 2026: Les acteurs de la menace ont déployé un ver autopropagé ("CanisterWorm") dans l'écosystème npm et ont compromis les actions GitHub de Checkmarx KICS. Ils ont également enregistré un domaine d'exfiltration malveillant, `models.litellm[.]cloud`, pour imiter l'infrastructure LiteLLM légitime et un domaine C2 `checkmarx[.]zone`.
    • 24 mars 2026, 10:39 UTC: TeamPCP a utilisé le jeton PyPI volé pour publier la version malveillante `litellm` 1.82.7 sur PyPI.
    • 24 mars 2026, 10:52 UTC: Les attaquants ont intensifié l'attaque en publiant la version 1.82.8, qui a ajouté le vecteur d'exécution agressif du fichier `.pth`.
    • 24 mars 2026, 11:48 UTC: Les chercheurs en sécurité de FutureSearch ont découvert la compromission après que le mécanisme d'exécution `.pth` du logiciel malveillant a accidentellement créé une "bombe à fourche" exponentielle qui a fait tomber leur système en panne.
    • 24 mars 2026, 12:44 UTC: Les attaquants ont déployé un botnet pour spammer le problème de divulgation de GitHub et ont utilisé des comptes de mainteneurs compromis pour dégrader temporairement les dépôts et fermer le problème comme "non planifié" pour perturber la réponse à l'incident.
    • 24 mars 2026, 13:38 UTC: L'équipe de sécurité de PyPI a réussi à mettre en quarantaine l'ensemble du projet `litellm`, bloquant ainsi les téléchargements ultérieurs.
    • 24 mars 2026, 15:27 UTC: Les versions malveillantes ont été définitivement supprimées, les comptes des mainteneurs ont été récupérés, et toutes les clés ont été retournées avec succès.

Mesures d'atténuation recommandées

Si vous pensez que votre système, votre pipeline CI/CD ou votre image Docker a rencontré `litellm` 1.82.7 ou 1.82.8, vous devez prendre immédiatement les mesures de remédiation suivantes :

    • Identifier l'exposition: Vérifier tous les environnements Python pour voir si les versions 1.82.7 ou 1.82.8 sont actuellement installées (`pip show litellm | grep Version`), et rechercher explicitement la présence du fichier `litellm_init.pth` dans `site-packages`.
    • Assumer une compromission totale et faire tourner les secrets: Si l'une ou l'autre des versions était présente, vous devez supposer que tous les credentials, cloud tokens, mots de passe de base de données, clés LLM, et clés SSH accessibles à l'environnement ont été volés. Effectuez immédiatement une rotation de tous les titres d'accès.
    • Éliminer la persistance: Arrêtez et désactivez l'unité systemd `sysmon.service`, et supprimez `~/.config/sysmon/sysmon.py`, `/tmp/pglog`, et `/tmp/.pg_state`. Dans les environnements Kubernetes, vérifiez minutieusement l'espace de noms `kube-system` et supprimez tous les pods attaquants correspondant à `node-setup-*`.
    • Purgez et reconstruisez les environnements: Ne vous contentez pas de rétrograder le paquet. Supprimer et recréer entièrement les environnements virtuels Python. Purger les caches des gestionnaires de paquets locaux (`pip cache purge` ou `rm -rf ~/.cache/uv`) pour empêcher la réinstallation accidentelle de roues malveillantes mises en cache. Reconstruire les environnements CI affectés à partir d'images de base propres.
    • Épingler les dépendances: Assurez-vous que vos environnements sont rattachés à la dernière version propre connue (`litellm==1.82.6` ou antérieure).
    • Bloquer l'infrastructure malveillante: Bloquez les connexions réseau sortantes et la résolution DNS pour les CIO connus dans le périmètre de votre réseau.

Indicateurs de compromission (IOC)

Catégorie

Indicateur

Description de l'indicateur

Fichier Hash

8395c3268d5c5dbae1c7c6d4bb3c318c752ba4608cfcd90eb97ffb94a910eac2

1.82.7 roue (SHA-256)

Fichier Hash

d2a0d5f564628773b6af7b9c11f6b86531a875bd2d186d7081ab62748a800ebb

1.82.8 roue (SHA-256)

Fichier Hash

71e35aef03099cd1f2d6446734273025a163597de93912df321ef118bf135238

litellm_init.pth (SHA-256)

Fichier Hash

a0d229be8efcb2f9135e2ad55ba275b76ddcfeb55fa4370e0a522a5bdee0120b

Fichier malveillant proxy_server.py (SHA-256)

Réseau

models.litellm[.]cloud

Point d'arrivée principal de l'exfiltration

Réseau

checkmarx[.]zone

Point final de persistance C2

Réseau

checkmarx[.]zone/raw

Point final d'interrogation pour la livraison des données utiles

Système de fichiers

.../site-packages/litellm_init.pth

Charge utile de démarrage de l'interprète

Système de fichiers

~/.config/sysmon/sysmon.py

Script de porte dérobée persistante (également dans /root/)

Système de fichiers

~/.config/systemd/user/sysmon.service

Unité malveillante ("System Telemetry Service")

Système de fichiers

/tmp/pglog

Charge utile binaire téléchargée

Système de fichiers

/tmp/.pg_state

Fichier de suivi de l'état du logiciel malveillant

Système de fichiers

tpcp.tar.gz

Archive d'exfiltration

Kubernetes

Pods : node-setup-*

Situé dans l'espace de noms kube-system

Kubernetes

Image du conteneur : alpine:latest

Utilisée dans le conteneur d'installation

Si vous êtes préoccupé par l'une des menaces décrites dans ce bulletin ou si vous avez besoin d'aide pour déterminer les mesures à prendre pour vous protéger contre les menaces les plus importantes auxquelles votre organisation est confrontée, veuillez contacter votre gestionnaire de compte ou prendre contact avec nouspour savoir comment vous pouvez protéger votre organisation.