惡意行為:憑證竊取與遠端程式碼執行

安裝 LiteLLM 1.107.0 會在 site-packages 目錄中放置三個檔案,其中兩個會在 Python 啟動時自動載入。cook.pth 會匯入 cook.py,這是一個憑證竊取器,負責收集 SSH 金鑰、雲端憑證、CI/CD 密鑰、AI 工具令牌、瀏覽器密碼以及 LiteLLM proxy 資料庫中的 LLM 供應商金鑰。這些資料會被加密並傳送至 www.litellm[.]dev。

另一個檔案 sitecustomize.py 會啟動一個背景守護程序。該程序每小時從攻擊者控制的 GitHub 檔案中讀取伺服器地址,重新執行竊取器,並從該伺服器下載並執行程式碼。這意味著即使主機上的 Python 程序從未匯入 litellm,這些惡意行為仍會被觸發。

感染機制:透過建置設定注入而非原始碼提交

攻擊者並未直接在公開的 GitHub 儲存庫中新增檔案,而是修改了源碼分發包(sdist)中的 pyproject.toml。在 maturin 建置區塊中加入了一行 data = "cook",這導致建置過程會將一個 cook/ 資料夾複製到 wheel 包的 purelib 目錄中,最終安裝至 site-packages。

SafeDep 比較了 PyPI 上的 sdist 與 Git 標籤 v1.107.0 指向的提交(commit 66c8f5b),發現兩者不符。PyPI 上的檔案實際上對應於較晚的 main 分支提交 a8113b0,並額外包含了五個編輯過的檔案和 cook/ 資料夾。其中四個是 Cargo.toml 檔案增加了 readme 行(這在合法的 rc2 版本中也存在),第五個則是 pyproject.toml,其版本號被改回 1.107.0 並注入了 data = "cook" 設定。

這種修改使得依賴差異對比 rc2 版本時看起來正常,因為輔助套件 litellm-proxy-extras 和 litellm-enterprise 的版本釘選(pins)與 rc2 相同。然而,公開的 BerriAI/litellm 儲存庫中沒有任何提交包含 data = "cook" 或 cook/ 資料夾。

憑證竊取器詳細行為與收集範圍

cook.py 是一個經過 zlib 壓縮和 base64 編碼的 Python 腳本,解碼後會執行一系列模組來收集系統資訊。收集的目標包括主機名稱、網路設定、Chromium 和 Firefox 的儲存密碼與歷史記錄、SSH 金鑰、Shell 歷史記錄、AWS/Azure/GCP/Kubernetes/Docker 等雲端憑證、開發環境密鑰(.pem, .key 等)、CI/CD 工具配置(GitLab, Jenkins, Terraform 等)、AI 開發工具令牌(Claude, Cursor, Copilot 等)以及 LiteLLM proxy 資料庫中的 API 金鑰。

收集到的 JSON 資料會使用隨機 AES-256-CBC 金鑰加密,該金鑰再透過內嵌的 RSA-4096 公鑰進行 OAEP 加密。結果打包成 tar.gz 格式,透過 POST 請求傳送到 www.litellm[.]dev/healthcheck,並帶有特定的 X-Token 標頭。上傳成功後,系統會在 /tmp/.pc_once_72129118c59f5636c0bb 寫入標記檔案,確保每台主機只執行一次收集動作。

後門機制與攻擊者控制權

sitecustomize.py 啟動的守護程序會鎖定 /tmp/remote_code_loader.lock 以確保每台主機只有一個實例運行,並透過 fork() 和 setsid() 脫離父程序。它每小時從 https://raw.githubusercontent.com/letters9813/pythonclient-test/main/domain.txt 讀取第一行看似域名的字串作為伺服器地址。

接著,守護程序會執行內嵌的竊取器副本(無一次性標記),並從 http://<domain>/codepy 下載程式碼並透過 exec() 執行。攻擊者可以通過編輯 domain.txt 來改變目標伺服器,從而控制每台受感染主機執行的第二階段程式碼。

在發布後約兩小時(UTC 13:40),GitHub 帳號 letters9813 及其儲存庫返回 404 錯誤,表示攻擊者已刪除該資源。此時後門無法找到伺服器地址而停止動作。SafeDep 無法恢復被刪除的伺服器地址,因此無法確定在刪除前是否有主機接收並執行了第二階段程式碼。

時間線與來源分析

所有事件發生於 UTC 2026-10-21。標籤 v1.107.0 於 06:59 創建,對應提交 66c8f5b。合法的 1.106.2 版本於 10:44 上傳至 PyPI。惡意的 1.107.0 wheel 包在 11:20 至 11:37 之間建置,並於 11:39 至 11:40 上傳至 PyPI。

SafeDep 檢查了 BerriAI 的 GitHub Actions 執行紀錄,發現沒有公開的工作流構建或發布了該版本。然而,litellm-dispatcher[bot] 在 11:50(PyPI 上傳後約 10 分鐘)發布了 GitHub release v1.107.0。SafeDep 評估認為,這些 wheel 包是由 BerriAI 的私有發布管線從攻擊者修改過的 Git 來源構建而成,置信度為中等至高。

可能的入侵途徑包括維護者或機器人憑證被洩露、使用私有分支或鏡像倉庫,或是攻擊者使用了竊取的 PyPI token 從自己的機器上傳。只有 BerriAI 的管線日誌才能確認根本原因。PyPI 上沒有針對 1.107.0、1.106.2 或 rc2 的來源證明(provenance attestations)。

受感染指標與清理建議

使用者應檢查 site-packages 目錄中是否存在 cook.pth、cook.py 和 sitecustomize.py。此外,/tmp/.pc_once_72129118c59f5636c0bb 的存在表示竊取器已上傳資料,/tmp/remote_code_loader.lock 表示後門守護程序曾運行。環境變數 PRIVCOLLECT_ACTIVE=1 也可能出現在受感染的程序中。

網路指標包括對 www.litellm[.]dev 的 HTTP 請求、帶有特定 X-Token 標頭的流量、對 raw.githubusercontent.com/letters9813/... 的請求,以及 Python 程序向 AWS IMDS (169.254.169.254) 發出的請求。

SafeDep 提供了受感染檔案的 SHA-256 雜湊值以供驗證。由於 Windows wheel 中的檔案因 CRLF 行尾轉換而具有不同的雜湊值,檢查時需注意作業系統差異。建議使用者升級至乾淨的版本或從 PyPI 移除該版本後重新安裝其他安全版本。