CVE-2025-53547:Helm 依赖更新代码注入漏洞分析与复现指南
1. 漏洞概述
- 漏洞编号:CVE-2025-53547
- 影响组件:Kubernetes 包管理工具 Helm
- 影响版本:Helm 3.18.4 之前的所有版本
- 漏洞等级:高危 (High Severity)
- 漏洞类型:代码注入 → 潜在本地代码执行
- 触发条件:攻击者能够诱使目标用户在恶意构造的 Helm Chart 目录下执行依赖更新或构建命令。
2. 漏洞原理与核心问题
该漏洞的本质是一个不安全的文件写入问题,源于 Helm 在处理依赖锁文件时未进行充分的安全检查。
- 正常流程:当用户执行
helm dependency update或helm dependency build时,Helm 会解析Chart.yaml中的依赖项,计算出版本约束,并将最终的依赖关系详情写入一个名为Chart.lock的文件中,以确保后续构建使用相同的版本。 - 漏洞点:在写入
Chart.lock文件之前,Helm 没有检查目标路径是否已经存在,以及如果存在,它是否是符号链接(Symlink)。 - 攻击手法:攻击者可以预先在 Chart 目录中创建一个名为
Chart.lock的符号链接,此链接指向系统上的任意其他文件(如~/.bashrc,/etc/cron.d/evil_job等)。 - 触发结果:当 Helm 执行更新操作时,它会毫无防备地向这个符号链接指向的目标文件写入 Lock 数据(YAML 格式)。如果目标文件是敏感脚本或配置文件,则可能破坏其原有功能或注入恶意代码,从而导致本地代码执行。
3. 漏洞定位与代码分析
漏洞根源于 pkg/downloader/manager.go 文件中的 writeLock 函数。
关键代码段分析(v3.18.3 及之前版本):
// pkg/downloader/manager.go
func (m *Manager) writeLock(chartPath string, lock *chart.Lock) error {
lockFileName := filepath.Join(chartPath, "Chart.lock") // 拼接锁文件路径
out, err := yaml.Marshal(lock) // 将lock结构体序列化为YAML格式的data
if err != nil {
return err
}
// 关键漏洞点:直接使用 os.WriteFile,未检查 lockFileName 是否是符号链接
if err := os.WriteFile(lockFileName, out, 0644); err != nil {
return errors.Wrap(err, "failed to save Chart.lock")
}
return nil
}
filepath.Join(chartPath, "Chart.lock")简单地拼接出目标文件路径。os.WriteFile(lockFileName, out, 0644)会无条件地向lockFileName写入数据。如果该路径是一个符号链接,则数据会被写入到链接所指向的实际文件。
调用链:
helm dependency update/build -> (*Manager).Update() -> (*Manager).writeLock()
4. 官方修复方案
在 Helm v3.18.4 版本中,官方对 writeLock 函数进行了修复。
修复代码分析(v3.18.4):
修复逻辑通常在写入文件前添加检查:
- 检查目标文件路径是否存在。
- 如果存在,使用
os.Lstat获取其元信息(Lstat不会追踪符号链接)。 - 检查该文件是否是一个符号链接(通过
FileInfo.Mode()与os.ModeSymlink进行判断)。 - 如果检测到是符号链接,则返回错误,拒绝写入,从而避免覆盖任意文件。
5. 漏洞复现 (PoC)
环境准备:
- 一台 Linux 或 macOS 机器。
- 安装 Helm 版本 < 3.18.4 (例如 v3.18.3)。
- 一个简单的 Helm Chart 目录。
复现步骤:
-
创建一个测试 Chart:
helm create test-vuln-chart cd test-vuln-chart -
添加一个依赖项到
Chart.yaml(确保依赖存在):# Chart.yaml apiVersion: v2 name: test-vuln-chart ... dependencies: - name: redis version: "~18.0.0" repository: "https://charts.bitnami.com/bitnami" -
创建恶意符号链接:
假设我们想覆盖用户家目录下的.bashrc文件(这是一个概念验证,实际利用条件苛刻)。# 在Chart目录下,将Chart.lock链接到.bashrc ln -sf ~/.bashrc Chart.lock -
触发漏洞:
执行依赖更新命令。helm dependency update .预期结果:由于
.bashrc不是有效的 YAML 文件,Helm 在解析现有的Chart.lock(即你的.bashrc)时会遇到错误,命令执行会失败并报错。但这证明了 Helm 确实尝试向.bashrc写入数据,触发了漏洞路径。
PoC 参考项目:
https://github.com/DVKunion/CVE-2025-53547-POC
6. 利用限制与深度思考
单纯的复现可能会失败,原因如下,这也是漏洞利用的关键约束:
-
文件格式约束:在调用
writeLock之前,Update()函数会调用loadChartDir(),该函数会尝试读取并解析 Chart 目录下的Chart.lock文件。如果该文件内容不是合法的 YAML 或不是空文件,Helm 会在写入之前就抛出解析错误导致进程退出。这使得直接覆盖.bashrc、/etc/passwd等非 YAML 文件变得困难。 -
潜在利用场景:
- 覆盖空白的 Cron 文件:如果系统
/etc/cron.d/、/etc/cron.hourly/等目录下存在一个空的或内容恰好是 YAML 格式的文件,攻击者可以将其链接为Chart.lock。Helm 成功写入 YAML 数据后,Cron 会读取这个被污染的文件并执行其中定义的命令,从而实现代码执行。 - 破坏现有应用配置:覆盖某个服务的配置文件(如 YAML 或 JSON 格式),可能导致服务崩溃或行为异常,造成拒绝服务(DoS)或更复杂的攻击链。
- 条件竞争(Race Condition):理论上存在一个极小的机会窗口,在 Helm 检查文件之后和写入文件之前,通过符号链接切换目标,但利用难度极高。
- 覆盖空白的 Cron 文件:如果系统
7. 修复与缓解措施
- 立即升级:将 Helm 升级到最新版本(≥ v3.18.4)。
- 审慎操作:不要在不信任的 Helm Chart 目录中执行任何 Helm 命令。
- 安全审计:检查你的 CI/CD 流水线,确保在执行 Helm 操作前,代码仓库和 Chart 来源是可信的。
8. 附录
- 官方修复 Commit:参考 Helm GitHub 仓库的 v3.18.3 与 v3.18.4 的代码对比:https://github.com/helm/helm/compare/v3.18.3...v3.18.4
- 相关文章:
- 【漏洞复现】CVE-2025-53547 helm恶意代码执行漏洞复现&分析
- 注:文中提到的
helm dependency build同样能触发漏洞,因为它内部在某些条件下会调用Update()函数。
总结:CVE-2025-53547 是一个由于安全开发意识不足导致的文件写入漏洞。虽然直接利用条件有些苛刻,但它破坏了系统的一个重要安全假设:“软件应只操作其指定目录下的文件”。及时升级是杜绝此类风险的根本方法。