Python .pthファイルを利用したサプライチェーン攻撃 — LiteLLM事例分析
pip installだけで全システムが乗っ取られる攻撃チェーンの構造
LiteLLMはOpenAI、Anthropic、Google等を統合するPythonライブラリだ。月間9500万ダウンロード。2026年3月にサプライチェーン攻撃を受けた。
サプライチェーン攻撃とは
ソフトウェアを直接攻撃するのではなく、そのソフトウェアが依存するライブラリやビルドツールを攻撃する手法だ。npm、PyPI、RubyGemsのようなパッケージリポジトリに悪意あるコードを仕込めば、それをインストールする全ユーザーが感染する。
直接攻撃はファイアウォール・認証で防げる。サプライチェーン攻撃は「通常のパッケージ更新」に偽装するため、既存のセキュリティ体制を迂回する。開発者が毎日行うpip installが攻撃ベクターになる。
今回の攻撃経路
- まずTrivy(脆弱性スキャナー)v0.69.4〜v0.69.6が攻撃された
- CI/CDからPyPIクレデンシャルが流出
- 流出クレデンシャルでLiteLLMメンテナーアカウントを乗っ取り
- 悪意あるv1.82.7/v1.82.8をPyPIに直接アップロード
importなしでインストールだけでコードが実行される。
.pthファイルとは
Pythonのsite-packages/ディレクトリの.pthファイルはインタプリタ起動時に自動読み込みされる。本来はパッケージパス追加用だが、importで始まる行はそのまま実行される。
pip install → wheel展開 → site-packagesに.pth設置 → Python起動時に自動実行。
4段階ペイロード
Stage 0 — .pthがsubprocess生成
Stage 1 — RSA-4096公開鍵 + AES-256-CBC暗号化ルーチンロード
Stage 2 — 25箇所以上からクレデンシャル収集:SSHキー、AWS/GCP/Azureトークン、K8sサービスアカウントトークン、11種以上暗号通貨ウォレット、シェルヒストリー
Stage 3 — C2サーバーに50分間隔ポーリング、任意バイナリ実行可能
Kubernetesクラスター掌握
tolerations operator: Exists + privileged: trueで全ノードに特権Pod生成。ホストFSを/hostにマウントして永続バックドア設置。
影響範囲
19,262依存リポジトリ — OpenHands、DSPy(Stanford NLP)、Databricks AI含む。
実際の対応 — Trivyユーザーとして
筆者はCI/CDでtrivy-actionを使っていた。乗っ取りが発生した3/19〜3/20に実際にワークフローが実行されていた。
幸い、trivy-actionをバージョンタグではなくfull-length commit SHAで固定していた。v0.28.0時点のSHAを直接指定していたため、乗っ取られたv0.69.4〜v0.69.6に自動更新されなかった。
確認手順として3/19〜3/20期間のGitHub Actionsログを全てダウンロードし、乗っ取られたバージョンが実行されていないことを検証した。仮に乗っ取られていたとしても、該当ワークフローのenv/secretsに危険なキー(AWSクレデンシャル、PyPIトークン等)が設定されていなかったため被害はなかったはずだ。
GitHub Actionsを使っているなら必ずやっておくこと
Repository Settings → Actions → General → Actions permissions → "Require actions to be pinned to a full-length commit SHA"をチェックしておくと、SHAで固定されていないactionを使用した時にワークフローがエラーで実行拒否される。
# ❌ タグ指定 — タグは誰でも上書き可能
uses: aquasecurity/trivy-action@v0.28.0
# ✅ SHA固定 — この特定コミットのコードのみ実行
uses: aquasecurity/trivy-action@a23fa65c5ff3e8d0c5f578c4b2a2b69e3b03be3b
タグは上書きできる。SHAは変えられない。この差が今回の事件で明暗を分けた。
既存ワークフローのactionを一括SHA固定するにはpinactというOSSが便利だ。pinact runで.github/workflows/内の全タグをSHAに自動変換してくれる。
動作フロー
Trivy攻撃 → CI/CDからPyPIクレデンシャル流出
流出クレデンシャルでLiteLLMメンテナーアカウント乗っ取り
.pthファイル含む悪意あるバージョンをPyPIにアップロード
pip installで.pthがsite-packagesに設置 → Python起動時自動実行
4段階ペイロード:subprocess→暗号化→クレデンシャル収集(25箇所+)→C2ポーリング