一、简介
未经身份验证的攻击者可以从服务器读取任意文件的前几行,而只读授权的攻击者可以读取整个文件。在某些情况下,这最终可能导致执行任意代码 (CVE-2024-23897)。如果满足以下条件之一,即使未经身份验证的用户也至少拥有读取权限:
1、启用传统模式授权。
2、在“登录用户可以执行任何操作”授权模式下勾选“允许匿名读取访问”配置。
2、注册功能已启用。
第二个漏洞 (CVE-2024-23898) 存在于 WebSocket CLI 功能中,该功能缺乏来源检查,从而允许跨站点 WebSocket 劫持 (CSWSH)。该漏洞可能会通过向受害者发送恶意链接而被利用。某些现代 Web 浏览器实施“默认宽松”策略,这是针对此漏洞的潜在防护措施。尽管如此,考虑到一些广泛使用的浏览器(例如 Safari 和 Firefox)并未严格执行此策略,并且考虑到潜在绕过技术或用户使用过时浏览器的相关风险,该漏洞的严重程度分类为“高”。
#洛米唯熊
二、分析
Jenkins-CLI为用户提供了一个内置的命令行界面来执行在Jenkins Git 存储库的hudson/cli目录中实现的自定义命令。
除了使用(利用 Web 套接字)或 SSH 调用命令的常见方法之外jenkins-cli.jar,我们发现还有一个额外的选项,即向http://jenkins/cli?remoting=false.
当Stapler(Jenkins 的将方法与端点相关联的组件)获取“ /cli”路径的相关方法时,端点将抛出PlainCliEndpointResponse()异常,该异常最终将出现在这个generateResponse函数中:
此功能需要下载器和上传器。下载器返回命令的响应,上传器从请求正文中调用指定的命令。Jenkins 使用标头中的 UUID 连接它们(下载器和上传器)Session。
#洛米唯熊
当使用参数调用 CLI 命令时,我们注意到 Jenkins 使用args4j 的 parseArgument,它调用 ExpandAtFiles:
该函数检查参数是否以 @ 字符开头,如果是,则读取 @ 之后的路径中的文件,并为每一行扩展一个新参数。
这意味着,如果攻击者可以控制某个参数,他们就可以将 Jenkins 实例上的任意文件中的参数扩展到任意数量。
攻击者利用这一点的一种方法是找到一个带有任意数量参数的命令并将这些参数显示给用户。由于参数是根据文件内容填充的,因此攻击者可以通过这种方式泄露文件内容。我们发现命令connect-to-node是一个很好的候选者:它接收一个字符串列表作为参数并尝试连接到每个字符串。如果失败,则会生成一条错误消息,其中包含失败的连接节点的名称。
public class ConnectNodeCommand extends CLICommand {
//...
"NAME", usage = "Agent name, or empty string for built-in node; comma-separated list is supported", required = true, multiValued = true) (metaVar =
private List<String> nodes;
//...
protected int run() throws Exception {
//...
for (String node_s : hs) {
try {
Computer computer = Computer.resolveForCLI(node_s);
computer.cliConnect(force);
} catch (Exception e) {
//...
final String errorMsg = node_s + ": " + e.getMessage();
stderr.println(errorMsg);
//...
}
}
//...
}
}
此连接到节点的命令通常需要 CONNECT 权限,该权限在cliConnect函数中进行验证。但由于在resolveForCLI函数中的权限检查之前抛出异常,因此除了初始只读验证之外,该命令实际上不需要任何授权。
从任意文件读取实现代码执行取决于上下文。攻击者可能感兴趣的一些文件可能是:
SSH 密钥
/etc/passwd、/etc/shadow
项目秘密和凭证(有关更多信息,请参阅 Jenkins 的建议)
源代码、构建工件
二进制文件读取限制
读取文件时,将使用进程的默认字符编码,对于大多数部署来说是 UTF-8。因此,任何无效的 UTF-8 序列(假设分布均匀,统计上几乎占所有字节的 50%)将被该序列替换0xef 0xbf 0xbd并导致数据丢失。
其他一些编码(例如 Windows-1252,通常由 Windows 上运行的实例使用)将使泄露二进制数据变得更加可行。
三、修复
Jenkins 安全团队通过添加安全配置修补了 CVE-2024-23897,该配置禁用了“ expandAtFiles ”功能。
+ public static boolean ALLOW_AT_SYNTAX = SystemProperties.getBoolean(CLICommand.class.getName() + ".allowAtSyntax");
//...
- return new CmdLineParser(this);
+ ParserProperties properties = ParserProperties.defaults().withAtSyntax(ALLOW_AT_SYNTAX);
+ return new CmdLineParser(this, properties);
通过向 WebSocket 端点添加源验证来修补 CVE-2024-23898(该ALLOW参数充当切换开关,使管理员能够覆盖更新的默认行为。提供一致允许或拒绝访问 WS CLI 的选项,不论来源):
public HttpResponse doWs(StaplerRequest req) {
if (!WebSockets.isSupported()) {
return HttpResponses.notFound();
}
+ if (ALLOW == null) {
+ final String actualOrigin = req.getHeader("Origin");
+ final String expectedOrigin = StringUtils.removeEnd(StringUtils.removeEnd(+Jenkins.get().getRootUrlFromRequest(), "/"), req.getContextPath());
+
+ if (actualOrigin == null || !actualOrigin.equals(expectedOrigin)) {
+ LOGGER.log(Level.FINE, () -> "Rejecting origin: " + actualOrigin + "; expected was from request: " + +expectedOrigin);
+ return HttpResponses.forbidden();
+ }
+ } else if (!ALLOW) {
+ return HttpResponses.forbidden();
+ }
Authentication authentication = Jenkins.getAuthentication2();
四、复现
环境:
https://github.com/vulhub/vulhub/tree/master/jenkins/CVE-2018-1000861
扫描二维码获取
更多精彩
洛米唯熊
原文始发于微信公众号(洛米唯熊):Jenkins CVE-2024-23897任意文件读取漏洞导致RCE
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论