Jenkins动态路由漏洞分析与利用:从ACL绕过到RCE

本文深入分析了Jenkins动态路由机制中的安全漏洞,包括ACL绕过、用户信息泄露、SSRF攻击链以及预认证RCE的可能性,探讨了CVE-2018-1000861等漏洞的利用方式与修复方案。

Jenkins动态路由漏洞分析与利用:从ACL绕过到RCE

引言

在软件工程中,持续集成与持续交付(CI/CD)是开发者减少常规工作的最佳实践。Jenkins作为最知名的CI/CD工具,因其易用性、强大的Pipeline系统和容器集成,成为全球使用最广泛的CI/CD应用。根据Snyk 2018年的JVM生态系统报告,Jenkins在CI/CD服务器市场中占据约60%的份额。

对于红队而言,Jenkins是每个黑客都希望控制的战场。一旦控制Jenkins服务器,攻击者可以获得大量源代码和凭据,甚至控制Jenkins节点!在DEVCORE红队案例中,有多起案例是从Jenkins服务器作为入口点入侵整个企业。

漏洞概述

在去年的安全审查中,我们发现了7个漏洞,包括:

  • CVE-2018-1999002 - 任意文件读取漏洞
  • CVE-2018-1000600 - GitHub插件中的CSRF和权限检查缺失
  • CVE-2018-1999046 - 未授权用户可访问代理日志
  • CVE-2018-1000861 - 通过精心构造的URL执行代码
  • CVE-2019-1003000 - 脚本安全与Pipeline插件中的沙箱绕过
  • CVE-2019-1003001 - 脚本安全与Pipeline插件中的沙箱绕过
  • CVE-2019-1003002 - 脚本安全与Pipeline插件中的沙箱绕过

本文将重点讨论CVE-2018-1000861,这是一个通过动态路由机制实现的ACL绕过漏洞。

权限级别

在Jenkins中,ACL角色分为三种类型:

  1. 完全访问权限:可以完全控制Jenkins,执行任意Groovy代码。
  2. 只读模式(ANONYMOUS_READ=True):所有内容可见可读,但无法执行脚本。
  3. 认证模式(ANONYMOUS_READ=False):默认模式,无有效凭据无法查看任何信息。

漏洞分析

Jenkins使用命名约定动态解析URL并调用方法。URL按/分割,从jenkins.model.Jenkins作为入口点逐级匹配令牌。如果令牌匹配以下命名约定,则递归调用:

  • get<token>()
  • get<token>(String)
  • get<token>(Int)
  • get<token>(Long)
  • get<token>(StaplerRequest)
  • getDynamic(String, …)
  • doDynamic(…)
  • do<token>(…)
  • js<token>(…)
  • 带有@WebMethod注解的类方法
  • 带有@JavaScriptMethod注解的类方法

问题点

  1. 一切皆是java.lang.Object的子类:所有对象都存在getClass()方法,该方法符合命名约定,可在动态路由中调用。
  2. 白名单绕过:在ANONYMOUS_READ=False模式下,入口点会进行白名单URL前缀检查。但如果能从白名单入口跳转到其他对象,仍可绕过此检查。

利用方式

通过交叉引用对象绕过ACL策略,利用以下gadget:

1
/securityRealm/user/[username]/descriptorByName/[descriptor_name]/

该gadget调用以下方法序列:

  • jenkins.model.Jenkins.getSecurityRealm()
  • .getUser([username])
  • .getDescriptorByName([descriptor_name])

在Jenkins中,所有可配置对象都扩展hudson.model.Descriptor类型,约500个类类型可通过此方法访问。尽管大多数开发者在危险操作前会再次检查权限,但此漏洞仍可作为绕过ACL限制的垫脚石。

漏洞链案例

  1. 预认证用户信息泄露:通过搜索功能缺乏权限检查,列出所有用户。
    • PoC: http://jenkins.local/securityRealm/user/admin/search/index?q=[keyword]
  2. 与CVE-2018-1000600链接触发全响应SSRF:通过GitHub插件提取凭据或触发SSRF。
    • PoC: http://jenkins.local/securityRealm/user/admin/descriptorByName/org.jenkinsci.plugins.github.config.GitHubTokenCredentialsCreator/createTokenByPassword?apiUrl=http://169.254.169.254/%23&login=orange&password=tsai
  3. 预认证远程代码执行:通过链接触发RCE(详情见第二部分)。

待办事项

  • 在ANONYMOUS_READ=False模式下获取Plugin对象引用,以绕过CVE-2018-1999002和CVE-2018-6356的ACL限制。
  • 在ANONYMOUS_READ=False模式下找到另一种gadget调用getDescriptorByName(String)方法。

致谢

感谢Jenkins安全团队特别是Daniel Beck的协调和漏洞修复。时间线如下:

  • 2018年5月30日 - 向Jenkins报告漏洞
  • 2018年6月15日 - Jenkins修复漏洞并分配CVE-2018-1000600
  • 2018年7月18日 - Jenkins修复漏洞并分配CVE-2018-1999002
  • 2018年8月15日 - Jenkins修复漏洞并分配CVE-2018-1999046
  • 2018年12月5日 - Jenkins修复漏洞并分配CVE-2018-1000861
  • 2018年12月20日 - 向Jenkins报告Groovy漏洞
  • 2019年1月8日 - Jenkins修复Groovy漏洞并分配CVE-2019-1003000、CVE-2019-1003001和CVE-2019-1003002

本文详细分析了Jenkins动态路由机制的安全问题,提供了漏洞利用的实践案例和修复建议,为安全研究人员和开发者提供了深入的技术参考。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计