T0ngMystic`s Blog

"Security studying, Strive to be Security Re-Searcher. Love everything that I want to do"

CVE-2023-22515-Confluence访问控制漏洞-任意管理员创建

image

2023-11-07 / 共计4065 字


CVE-2023-22515-Confluence访问控制漏洞-任意管理员创建

夏季的遗憾终会在冬季圆满。

The regrets of summer will eventually be fulfilled in winter.

2023年10月4日,Confluence发布了一个“CVE-2023-22515 - Confluence 数据中心和服务器中的访问控制漏洞”的漏洞通告。刚出来的时候就了解了一下,但没有时间去对其做详细分析。漏洞出来都一个月了,这几天见缝插个针,强行抽出点时间,分析分析是怎么个回事,并写写任意管理员注册的EXP

官方漏洞通告:https://confluence.atlassian.com/security/cve-2023-22515-broken-access-control-vulnerability-in-confluence-data-center-and-server-1295682276.html

最终效果: CVE-2023-22515-Confluence.gif


漏洞分析

先去atlassian官方下载Confluence源码,我这里使用的是Confluence8.4.2和Confluence8.4.3。

Confluence源码主要在/atlassian-confluence-8.4.2/confluence/WEB-INF/lib/com.atlassian.confluence_confluence-8.4.2.jar中,先查看一下8.4.2和8.4.3 jar更新情况,看看修改了哪些内容: image.png

可以看到在更新中struts.xml中新增了struts.override.acceptedPatterns,并删除了server-info.action image.png

新加了ReadOnlyApplicationConfig.class和ReadOnlySetupPersister,并且BootstrapStatusProviderlmpl.class中getApplicationConfig和getSetupPersister改成了ReadOnly image.png

在ReadOnly中对seter与大部分方法进行了抛出异常处理UnsupportedOperationException(“Mutation not allowed”),看到这里,可以了解到Confluence是基于Struts2的,其实如果对Struts相关历史漏洞有所了解的话,那么该漏洞可能出现的位置可以猜个大概了:(之后去了解了一下,发现到这就可以猜个大概了) image.png 根据官方给出的检测方法,可知最后是通过/setup/setupadministrator.action添加管理员用户: image.png

那么先在strtus拦截器配置中找到/setup/setupadministrator.action所对应的拦截方法看看(/setup下存在默认拦截器validatingSetupStack): image.png

在package:setup下找到setupadministrator.action,对应方法SetupAdministrator: image.png 在/setup的默认拦截器validatingSetupStack下是setupStack,setupStack下又是setup拦截器 image.png

找到setup拦截器对应的com.atlassian.confluence.setup.actions.SetupCheckInterceptor,从名称猜测该Interceptor多半是/setup下检查是否已经setup: image.png

跟进SetupCheckInterceptor看看,可以看到如果BootstrapUtils.getBootstrapManager().isSetupComplete() 和ContainerManager.isContainerSetup()都为true则表示已经完成setup了,那么就无法进入setupadministrator.action方法: image.png 跟进isSetupComplete,其中会调用到applicationConfig.isSetupComplete(),而在更新对比中,getApplicationConfig()和这里的applicationConfig都是ApplicationConfiguration类,那么既然BootstrapStatusProviderlmpl可以获取ApplicationConfiguration类,那么只要将其中的setupComplete修改为false,那么就多半就可以绕过这里的isSetupComplete检测: image.png

有了思路,那么现在就需要找一个有的地方有BootstrapStatusProviderlmpl,并设置setComplete为false从而打通利用链。结合Strtus2的Interceptor和confluence的interceptor,发现confluence存在一个<default-interceptor-ref>(strtus2并不是很了解,去su18那学习了一下,感兴趣的也可以看看): image.png

defaultStack中的拦截器如下,这里主要关注params: image.png

params对应方法com.atlassian.xwork.interceptors.SafeParametersInterceptor: image.png

通过简单的调试,走了SafeParametersInterceptor下的doIntercept(): image.png

可以看到在before中有使用OGNL表达式,那么这里是不是可以通过OGNL表达式从而设置setupComplete=false:(实际上这里是不行的) image.png

经过调试发现parameters在这里被过滤了: image.png

在刚进入filterSafeParameters时确实获取了参数,但是经过isSafeParameterName时给过滤掉了: image.png

isSafeParameterName代码如下: image.png

其中过滤了actionErrors,actionMessages,还进行了EXCLUDE_CLASS_PATTERN,SAFE_PARAMETER_NAME_PATTERN,MAP_PARAMETER_PATTERN三个正则表达式的匹配,最后还调用了isSafeComplexParameterName: image.png

可以看到isSafeComplexParameterName对参数进行了分隔,还进行了白名单限制,通过这一系列严格的过滤,这里的OGNL基本上的行不通了: image.png

但是,还记得doIntercept中还调用了父类的doInercept吗: image.png

public class SafeParametersInterceptor extends ParametersInterceptor{}

SafeParametersInterceptor继承于ParametersInterceptor,super.doIntercept()执行的是ParametersIntercepto下r的doInercept(),代码如下:

在进入setParameters中时参数并没有进行过滤,还是aaa.aa.aa=b: image.png

在setParameters中的newStack.setParameter(name, value.getObject());同样是使用的OGNL,可以看到aaa.aa.a=b在进入前没有被过滤掉,这里重新进行了参数获取,导致SafeParametersInterceptor中的before的过滤失效了,那么这里不就可以使用OGNL表达式进行漏洞利用了吗: image.png

到这里一切都明朗了,这下只要找到一个action对应的类中存在或继承了BootstrapStatusProviderlmpl或获取了BootstrapStatusProviderlmpl,那么就可以完成利用了。既然在开头看到更新中删除了server-info.action,那么就先看看它吧,server-info对应com.atlassian.confluence.core.actions.ServerInfoAction方法: image.png

查看ServerInfoAction中并没有我们需要的set方法,但是它继承了ConfluenceActionSupport,父类中若是存在也是可以利用的: image.png

经过查看ConfluenceActionSupport中有个getBootstrapStatusProvider方法,就获取到了BootstrapStatusProviderImpl类: image.png

在BootstrapStatusProviderImpl类的getApplicationConfig方法,即为漏洞修复的地方(ApplicationConfig类是ApplicationConfiguration的实现): image.png

并且在ApplicationConfig中可以看到setSetupComplete方法,修改了setupComplete的值。到这里我们直接使用OGNL表达式修改bootstrapStatusProvider.applicationConfig.setupComplete的值为false就可以绕过SetupCheckInterceptor中的isSetupComplete() 校验,从而完成利用: image.png


漏洞利用

至此,使用OGNL表达式,我们已经可以写出poc了:

/server-info.action?bootstrapStatusProvider.applicationConfig.setupComplete=false

在没有使用poc前访问/setup/setupadministrator.action则是显示Setup is already complete: image.png

访问/server-info.action?bootstrapStatusProvider.applicationConfig.setSetupComplete=false: image.png 再次访问/setup/setupadministrator.action,则不再是Setup is already complete(这里的Method Not Allowed只是setupadministrator.action不允许GET方法,使用POST即可创建管理员账号了): image.png 最终的任意管理员注册的EXP已放Github

文笔垃圾,技术欠缺,欢迎各位大师傅请斧正,非常感谢!


如果文章对您有帮助

欢迎关注公众号!

感谢您的支持!