jenkins 无限制 rce 分析
字数 1275 2025-08-29 08:31:47

Jenkins 无限制 RCE 漏洞分析

漏洞概述

本文详细分析了 Jenkins 中一个无限制远程代码执行漏洞的利用链,该漏洞结合了 CVE-2018-1000861(动态路由越权调用)和 CVE-2019-1003000(Groovy 沙箱绕过)两个漏洞,最终实现了无需任何权限的远程代码执行。

漏洞背景

  • Jenkins 在 2018-12-05 公布了一个动态路由越权调用漏洞(CVE-2018-1000861)
  • 2019-01-08 公布了 Pipeline 插件中 Groovy 沙箱绕过漏洞(CVE-2019-1003000)
  • 结合这两个漏洞可以实现无限制的 RCE

技术分析

1. Stapler 动态路由机制

Jenkins 使用 Stapler 框架处理 HTTP 请求,其核心路由机制如下:

  1. 根据 URL 路径逐级解析路由节点
  2. 对每个节点,在继承家族树中查找匹配 11 种规则的函数
  3. 匹配规则包括:getXxx、doXxx、jsXxx 等开头的函数
  4. 通过反射调用匹配的函数,并将返回值作为下一个节点

2. 路由访问限制绕过

Jenkins 实现了 StaplerProxy 接口,会检查 READ 权限:

public Object getTarget() {
    if (!hasPermission(READ)) {
        throw new AccessDeniedException("需要整体/读取权限");
    }
    return this;
}

但存在白名单路径 /securityRealm 可以绕过权限检查:

private static final Set<String> ALWAYS_READABLE_PATHS = ImmutableSet.of(
    "/login", "/logout", "/accessDenied", "/adjuncts/", "/error", "/oops",
    "/signup", "/tcpSlaveAgentListener", "/federatedLoginService/", 
    "/securityRealm", "/instance-identity"
);

3. 利用链构建

完整的利用链如下:

  1. 访问 /securityRealm(白名单路径)
  2. 返回 HudsonPrivateSecurityRealm
  3. 调用 getUser 方法,返回 User
  4. User 类实现 DescriptorByNameOwner 接口
  5. 调用 getDescriptorByName 方法,返回 Jenkins
  6. 最终获取任意 Descriptor 实例

4. 寻找 RCE 点

通过分析官方补丁,发现 CpsFlowDefinition$DescriptorImpl 是关键点:

public class CpsFlowDefinition extends FlowDefinition {
    public static class DescriptorImpl extends FlowDefinitionDescriptor {
        public FormValidation doCheckScript(@QueryParameter String value) {
            // 处理 Groovy 脚本
        }
    }
}

5. Groovy 沙箱绕过

虽然 Pipeline 插件使用了 Groovy 沙箱,但存在多种绕过方式:

  1. 使用 Grab 注解
@Grab('org.apache.commons:commons-collections4:4.0')
import org.apache.commons.collections4.functors.*
  1. 使用 ASTTest 注解
def x = 1
@ASTTest(phase=INSTRUCTION_SELECTION, value={ 
    assert System.exit(0); null 
})
def y = 2

漏洞复现步骤

  1. 通过 /securityRealm/user/[任意用户名] 绕过权限检查
  2. 调用 getDescriptorByName 获取 CpsFlowDefinition$DescriptorImpl
  3. 调用 doCheckScript 方法并传入恶意 Groovy 脚本
  4. 使用 Grab 或 ASTTest 注解绕过沙箱限制
  5. 实现任意代码执行

防御措施

  1. 升级 Jenkins 到最新版本
  2. 限制匿名用户权限
  3. 禁用不必要的插件
  4. 监控异常 Groovy 脚本执行

参考链接

  1. Jenkins Security Advisory 2019-01-08
  2. Jenkins Security Advisory 2018-12-05
  3. Pipeline Plugin GitHub
  4. Hacking Jenkins Part1
Jenkins 无限制 RCE 漏洞分析 漏洞概述 本文详细分析了 Jenkins 中一个无限制远程代码执行漏洞的利用链,该漏洞结合了 CVE-2018-1000861(动态路由越权调用)和 CVE-2019-1003000(Groovy 沙箱绕过)两个漏洞,最终实现了无需任何权限的远程代码执行。 漏洞背景 Jenkins 在 2018-12-05 公布了一个动态路由越权调用漏洞(CVE-2018-1000861) 2019-01-08 公布了 Pipeline 插件中 Groovy 沙箱绕过漏洞(CVE-2019-1003000) 结合这两个漏洞可以实现无限制的 RCE 技术分析 1. Stapler 动态路由机制 Jenkins 使用 Stapler 框架处理 HTTP 请求,其核心路由机制如下: 根据 URL 路径逐级解析路由节点 对每个节点,在继承家族树中查找匹配 11 种规则的函数 匹配规则包括:getXxx、doXxx、jsXxx 等开头的函数 通过反射调用匹配的函数,并将返回值作为下一个节点 2. 路由访问限制绕过 Jenkins 实现了 StaplerProxy 接口,会检查 READ 权限: 但存在白名单路径 /securityRealm 可以绕过权限检查: 3. 利用链构建 完整的利用链如下: 访问 /securityRealm (白名单路径) 返回 HudsonPrivateSecurityRealm 类 调用 getUser 方法,返回 User 类 User 类实现 DescriptorByNameOwner 接口 调用 getDescriptorByName 方法,返回 Jenkins 类 最终获取任意 Descriptor 实例 4. 寻找 RCE 点 通过分析官方补丁,发现 CpsFlowDefinition$DescriptorImpl 是关键点: 5. Groovy 沙箱绕过 虽然 Pipeline 插件使用了 Groovy 沙箱,但存在多种绕过方式: 使用 Grab 注解 : 使用 ASTTest 注解 : 漏洞复现步骤 通过 /securityRealm/user/[任意用户名] 绕过权限检查 调用 getDescriptorByName 获取 CpsFlowDefinition$DescriptorImpl 调用 doCheckScript 方法并传入恶意 Groovy 脚本 使用 Grab 或 ASTTest 注解绕过沙箱限制 实现任意代码执行 防御措施 升级 Jenkins 到最新版本 限制匿名用户权限 禁用不必要的插件 监控异常 Groovy 脚本执行 参考链接 Jenkins Security Advisory 2019-01-08 Jenkins Security Advisory 2018-12-05 Pipeline Plugin GitHub Hacking Jenkins Part1