「Pythonを起動するだけで感染」月間9500万DLのLiteLLMが乗っ取られた
PyPIで月間9500万回ダウンロードされるLiteLLMが攻撃者に乗っ取られた。.pthファイルによりPython起動時に自動実行されるcredential stealerが仕込まれ、SSH鍵やクラウド認証情報を窃取。攻撃の起点はセキュリティスキャナーTrivyだった。
ニュース
kkm
Backend Engineer / AWS / Django
何が起きたのか
2026年3月24日、PythonのAI開発で広く使われるライブラリ「LiteLLM」のPyPIパッケージが攻撃者に乗っ取られた。LiteLLMは100種類以上のLLM APIを統一的に呼び出せるプロキシツールで、月間9500万回以上ダウンロードされている。クラウド環境の36%で使われているというWizの調査もある。
攻撃者「TeamPCP」は、LiteLLMのメンテナーのPyPIアカウントを乗っ取り、正規のアカウントからマルウェアを仕込んだバージョン1.82.7と1.82.8を公開した。パッケージはPyPIに約3時間公開された後、隔離措置が取られた。
何が盗まれるのか
仕込まれたマルウェアはcredential stealer(認証情報窃取ツール)で、インストールされたマシンから以下を根こそぎ収集する。
| 対象 | 具体例 |
|---|---|
| SSH鍵 | ~/.ssh/ 配下の秘密鍵・公開鍵 |
| クラウド認証情報 | AWS、GCP、AzureのIMDS経由の認証情報・設定ファイル |
| Kubernetesシークレット | サービスアカウントトークン、クラスタ全ネームスペースのSecret |
| 環境変数・.envファイル | APIキー、データベースパスワード、CI/CDトークン |
| 暗号ウォレット | ウォレットディレクトリの秘密鍵 |
| シェル履歴 | .bash_history、.zsh_history |
| SSL秘密鍵 | サーバー証明書の秘密鍵 |
収集したデータはAES-256-CBCで暗号化し、ハードコードされた4096ビットRSA公開鍵でセッション鍵を保護した上で、攻撃者が管理するドメイン models.litellm.cloud にPOST送信される。このドメインは攻撃当日の3月24日にNamecheapで取得されたものだ。
「importしなくても動く」という衝撃
今回の攻撃で最も危険なのは、バージョン1.82.8で採用された .pth ファイルという手法だ。
通常のPyPIマルウェアは、パッケージをimportしたとき、あるいは setup.py のインストールフック経由で実行される。しかし .pth ファイルはPythonの起動メカニズムそのものに組み込まれている。Pythonインタープリタが起動するたびに site.py が site-packages 内の .pth ファイルを走査し、import で始まる行をPython文として実行する。
つまり、import litellm を書いていなくても、pytest を実行しても、django の開発サーバーを起動しても、flask アプリを動かしても、同じvenv内であればPythonプロセスが起動するたびにマルウェアが発火する。
攻撃者が仕込んだ litellm_init.pth の中身は、二重base64エンコードされたペイロードを subprocess.Popen で子プロセスとして起動する1行だった。
バージョン1.82.7は proxy_server.py にペイロードを埋め込む手法で、litellm --proxy コマンドの実行やモジュールのimport時に発動する。1.82.8は.pthファイルでの自動実行に「進化」しており、13分の間隔で両バージョンが公開された。
攻撃チェーン、セキュリティツールが入口になった
攻撃の起点は、LiteLLM自体ではなくセキュリティスキャナー「Trivy」だった。
3月19日、攻撃者はTrivy GitHub Actionsリポジトリの trivy-action のGitタグを書き換え、悪意あるリリースv0.69.4を指すようにした。LiteLLMはCI/CDパイプラインでTrivyをバージョンピンなしで使用していたため、ビルド時に改ざんされたTrivyが実行され、PyPIの公開用トークン(PYPI_PUBLISH)が攻撃者に流出した。
攻撃者はこのトークンを使い、GitHubにタグもリリースも作らずPyPIに直接パッケージをアップロードした。正規のメンテナーアカウントからの公開であるため、PyPIの通常のセキュリティチェックでは検出できない。
| 日時 | 出来事 |
|---|---|
| 3月1日 | Aqua Security(Trivyメンテナー)が初期侵害を受ける |
| 3月19日 | trivy-actionのGitタグが悪意あるリリースに書き換えられる |
| 3月23日 | 攻撃者がexfilドメイン litellm.cloud を登録 |
| 3月24日 08:30 UTC | 悪意あるv1.82.7、続いてv1.82.8がPyPIに公開 |
| 3月24日 11:25 UTC | PyPIがlitellmパッケージ全体を隔離 |
| 3月24日 20:15 UTC | 侵害バージョンがyanked、隔離解除 |
Kubernetesクラスタへの横展開
マルウェアの被害はローカルマシンにとどまらない。Kubernetesのサービスアカウントトークンを検出すると、クラスタ内の全ネームスペースのSecretを読み取り、さらに全ノードに node-setup-{ノード名} という名前の特権Podをデプロイする。
このPodは alpine:latest イメージで起動し、ホストのファイルシステムをマウントした上で chroot でホストに入り込む。そこに ~/.config/sysmon/sysmon.py というバックドアをsystemdユーザーサービスとしてインストールする。このサービスは checkmarx.zone/raw に50分ごとにアクセスし、次段階のペイロードを取得する。
開発者のローカルマシンが感染しただけで、本番のKubernetesクラスタ全体が乗っ取られる可能性がある。
現在の状況と対処法
PyPIは侵害バージョンをyanked(削除)し、LiteLLMチームはGoogleのMandiantセキュリティチームと協力して調査を進めている。新しいメンテナーアカウントへの移行も完了した。Dockerイメージ経由でLiteLLMを使用しているユーザーは、依存関係がピン留めされているため影響を受けていない。
3月24日以降にlitellmをインストールまたはアップグレードしたシステムは、以下の確認が必要だ。
| 確認項目 | コマンド |
|---|---|
| バージョン確認 | pip show litellm | grep Version |
| .pthファイルの存在確認 | find $(python3 -c "import site; print(site.getsitepackages()[0])") -name "litellm_init.pth" |
| バックドアの存在確認 | ls -la ~/.config/sysmon/sysmon.py |
| systemdサービスの確認 | systemctl --user status sysmon.service |
| K8s不正Podの確認 | kubectl get pods -n kube-system | grep node-setup |
該当バージョンがインストールされていた場合は、パッケージの削除に加え、SSH鍵、クラウド認証情報、APIキー、Kubernetesトークンなど、マシン上に存在したすべての認証情報のローテーションが必要になる。
参照元
- →GitHub Issue #24518: litellm PyPI package (v1.82.7 + v1.82.8) compromised
- →Snyk: How a Poisoned Security Scanner Became the Key to Backdooring LiteLLM
- →Wiz: TeamPCP Trojanizes LiteLLM in Continuation of Campaign
- →The Hacker News: TeamPCP Backdoors LiteLLM Versions 1.82.7–1.82.8
- →FutureSearch: Supply Chain Attack in litellm 1.82.8 on PyPI