XMLdecoder安全漏洞分析

Posted 雷神众测

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XMLdecoder安全漏洞分析相关的知识,希望对你有一定的参考价值。

No.1

声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。

雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。


No.2

前言

之前看到关于xmldecoder的解析流程分析文章然后我就想着自己也跟一下,我测试的java版本是1.8.0_171。


No.3

测试代码

import java.io.BufferedInputStream;

import java.io.File;

import java.io.FileInputStream;

import java.beans.XMLDecoder;

public class Xmldecoder {

public static void XMLDecode_Deserialize(String path) throws Exception {
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
XMLDecoder xd = new XMLDecoder(bis);
xd.readObject();
xd.close();
}

public static void main(String[] args){

//XMLDecode Deserialize Test

String path = "/Users/l1nk3r/Desktop/poc.xml";

try {
XMLDecode_Deserialize(path);
} catch (Exception e) {
e.printStackTrace();
}
}
}

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

<java version="1.8.0_131" class="java.beans.XMLDecoder">

<object class="java.lang.ProcessBuilder">

<array class="java.lang.String" length="2">

<void index="0">

<string>open</string>

</void><void index="1"><string>/Applications/Calculator.app</string>

</void>

</array>

<void method="start" />

</object>

</java>


No.4

前置知识

这里我选择在 java.lang.ProcessBuilder 接收 array 类型数据传入的地方下个断点。

可以看到整个解析流程涉及到的类和构造方法大概就是如下所示,这里我们看到一个在 package:com.sun.beans.decoder 中 DocumentHandler 类中 parse 解析了,我们的传入的xml文件。

XMLdecoder安全漏洞分析

这里可以跟进一下 DocumentHandler 类,这个类继承了 DefaultHandler 。

XMLdecoder安全漏洞分析

跟进一下 DefaultHandler 类,我们可以知道它是使用 sax 来解析 xml 的默认 handler ,而且代码里来看它主要实现了 EntityResolver ,  DTDHandler ,  ContentHandler ,  ErrorHandler 这四个 handler 。

package org.xml.sax.helpers;

import java.io.IOException;

import org.xml.sax.InputSource;

import org.xml.sax.Locator;

import org.xml.sax.Attributes;

import org.xml.sax.EntityResolver;

import org.xml.sax.DTDHandler;

import org.xml.sax.ContentHandler;

import org.xml.sax.ErrorHandler;

import org.xml.sax.SAXException;

import org.xml.sax.SAXParseException;

回过头来看 DocumentHandler 这个类,在这个类的构造方法中,我们看到了 XMLDecoder 对每种支持的标签都实现了一个继承与 ElementHandler 的类。

XMLdecoder安全漏洞分析

所以从目前来看 DocumentHandler 这个构造函数主要的作用就是创建各个标签对应的 ElementHandler 并进行调用。当然关于 DocumentHandler 类因为是继承了 DefaultHandler 类,这一点我们前面聊到了,而 DefaultHandler 类中解析xml的工作主要交付给了 ContentHandler 接口,所以我们可以借鉴一下这个接口是怎么个解析xml内容的,这里直接借鉴一下@fnmsd师傅写的内容,因为我觉得我自己写的话没有他写的这么的棒。


startElement
 处理开始标签,包括属性的添加
 DocumentHandler:XML解析处理过程中参数包含命名空间URL、标签名、完整标签名、属性列表。根据完整标签名创建对应的ElementHandler并添加相关属性,继续调用其startElement。


ElementHandler: 除了array标签以外,都无操作。


endElement
 结束标签处理函数
 DocumentHandler: 调用对应ElementHandler的endElement函数,并将当前ElementHandler回溯到上一级的ElementHandler。


ElementHandler: 没看有重写的,都是调用抽象类ElementHandler的endElement函数,判断是否需要向parent写入参数和是否需要注册标签对象ID。

characters
DocumentHandler: 标签包裹的文本内容处理函数,比如处理java.lang.ProcessBuilder包裹的文本内容就会从这个函数走。函数中最终调用了对应ElementHandler的addCharacter函数。


addCharacter
 ElementHandler: ElementHandler里的addCharacter只接受接种空白字符(空格 ),其余的会抛异常,而StringElementHandler中则进行了重写,会记录完整的字符串值。


addAttribute
 ElementHandler: 添加属性,每种标签支持的相应的属性,出现其余属性会报错。


getContextBean
 ElementHandler: 获取操作对象,比如method标签在执行方法时,要从获取上级object/void/new标签Handler所创建的对象。该方法一般会触发上一级的getValueObject方法。


getValueObject
 ElementHandler: 获取当前标签所产生的对象对应的ValueObject实例。具体实现需要看每个ElementHandler类。


isArgument
 ElementHandler: 判断是否为上一级标签Handler的参数。


addArgument
 ElementHandler: 为当前级标签Handler添加参数。


XMLDecoder相关的其它

 两个成员变量,在类的实例化之前,通过对parent的调用进行增加参数。


parent
 最外层标签的ElementHandler的parent为null,而后依次为上一级标签对应的ElementHandler。

owner
 ElementHandler: 固定owner为所属DocumentHandler对象。

DocumentHandler: owner固定为所属XMLDecoder对象。

而sax解析xml文件中的单个node节点(根节点)的流程在 DefaultHandler 中一般是三步走: startElement->characters->endElement  。

针对node节点(非根)的解析流程在中是四步走 DefaultHandler 中一般是四步走: startElement->characters->endElement->characters。

所以总结来看本质上最有关系的还是这三个构造方法 startElement、characters、endElement 。

然后,我们可以看看 DocumentHandler 中的这些 ElementHandler 的继承关系,这里重点表扬一下 idea 的 uml 的功能,使用方法很简单,选择一个你想要看的方法,右键选择 Diagrams 。

XMLdecoder安全漏洞分析

然后每次选择 add Class to Diagram 就可以增加你要看的相关类。

XMLdecoder安全漏洞分析

最后就生成了下面这张图。

XMLdecoder安全漏洞分析

而关于xmldecoder对应的xml文件语法书写如下所示:

    每个元素表示方法调用。

    “对象”标签表示一个表达式 ,其值将用作封闭元素的参数。

    “void”标签表示将被执行的语句 ,但其结果将不会用作封闭方法的参数。

    包含元素的元素使用这些元素作为参数,除非它们具有标签:“void”。

    方法的名称由“method”属性表示。

    XML的标准“id”和“idref”属性用于对前面的表达式进行引用,以便处理对象图形中的循环。

    “类”属性用于明确指定静态方法或构造函数的目标; 其值是该类的完全限定名称。

    如果没有由“class”属性定义目标,则使用“void”标签的元素将使用外部上下文作为目标来执行。

    Java的String类被特别处理,并写入

Hello,world ,其中使用UTF-8字符编码将字符串的字符转换为字节。


No.5

流程跟进

这里跟进一下上面的那些基础知识分析过的内容,首先按照我们的了解来看,针对xml文件的解析最早应该是使用 DefultHandler 中 startElement ,我们在这里下个断点。

XMLdecoder安全漏洞分析

回过头来看一下xml文件内容,最开始的节点叫java,所以这里解析出来对应的对应的 handler 是 JavaElementHandler 。

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_131" class="java.beans.XMLDecoder">
<object class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="2">
<void index="0">
<string>open</string>
</void>
<void index="1">
<string>/Applications/Calculator.app</string>
</void>
</array>
<void method="start" />
</object>
</java>

而 JavaElementHandler 中的 addAttribute 构造函数的作用就是添加相应的属性,比如 version 的属性是版本信息这里是 1.8.0_131 ,而另一个就是 class 这里是 java.beans.XMLDecocer 。

public void addAttribute(String var1, String var2) {if (!var1.equals("version")) {if (var1.equals("class")) {this.type = this.getOwner().findClass(var2);
} else {super.addAttribute(var1, var2);
}
}

所以开始第一次 addAttribute 的结果是 version 和它对应的值,当然这个解析过程不是一次,单单是下面内容就会执行两次解析过程。

java version="1.8.0_131" class="java.beans.XMLDecoder"

XMLdecoder安全漏洞分析
XMLdecoder安全漏洞分析

当然关键不在这,我想知道为什么能够执行 java.lang.ProcessBuilder 这个类,从前面debug过程来看,如果。startElement 解析道这里处理之后对应的 handler 应该是 ObjectElementHandler 。

<object class="java.lang.ProcessBuilder">

<array class="java.lang.String" length="2">

<void index="0">

<string>open</string>

</void><void index="1"><string>/Applications/Calculator.app</string>

</void>

</array>

<void method="start" />

</object>

在这里下一个断点,果然进来了, ObjectElementHandler 里面的 addAttribute 方法没有能够解析 class 的选项。

XMLdecoder安全漏洞分析

但是由于 ObjectElementHandler 继承了 NewElementHandler ,所以这里便使用 NewElementHandler 中的 addAttribute 方法来处理,这里自然有了能够处理 class 的能力了。

XMLdecoder安全漏洞分析

这里的 type 自然就是名字是 java.lang.ProcessBuilder 的类。

XMLdecoder安全漏洞分析

这里处理完了之后就会继续调用 ArrayElementHandler 处理 array 的内容了,然后调用 VoidElementHandler 处理 void 标签的内容,而 VoidElementHandler 也是继承来自于 ObjectElementHandler ,自然而然也是回到了 ObjectElementHandler 中的 addAttribute 中了。

XMLdecoder安全漏洞分析

这里我就下了两个断点,我们可以看到 void 标签中的 index 和 method 处理过程自然都进入到了这里。

XMLdecoder安全漏洞分析
XMLdecoder安全漏洞分析

当然前面过程 void 标签处理完之后,首先会进入 DocumentHandler 的 endElement 方法进行处理,而这个方法中调用了 ElementHandler 中的 endElement 构造方法。

public void endElement(String var1, String var2, String var3) {

try {

this.handler.endElement();
} catch (RuntimeException var8) {

this.handleException(var8);
} finally {

this.handler = this.handler.getParent();
}
}

而在 endElement 构造方法中调用了 getValueObject ,这个方法设置了在 endElement 中被设置成了一个抽象类,我们通过在 java.lang.ProcessBuilder 处下一个断点,可以看到自然进到了 NewElementHandler 中的 getValueObject 了。

public void endElement() {
ValueObject var1 = this.getValueObject();if (!var1.isVoid()) {if (this.id != null) {this.owner.setVariable(this.id, var1.getValue());
}

if (this.isArgument()) {if (this.parent != null) {this.parent.addArgument(var1.getValue());
} else {this.owner.addObject(var1.getValue());
}
}
}
}

XMLdecoder安全漏洞分析
XMLdecoder安全漏洞分析

再回顾一下继承关系,这里我放大了一下这部分内容。

XMLdecoder安全漏洞分析

上面的 NewElementHandler 中的构造方法 getValueObject 在 ObjectElementHandler 、 ArrayElementHandler 、 MethodElementHandler 中分别被重写了。

XMLdecoder安全漏洞分析

因为我们 payload 里面关于命令执行使用的是 object 标签,所以自然就进来到了 ObjectElementHandler 中,然后这里有调用了 getContextBean 方法,而根据继承关系,这个方法调用的是 NewElementHandler 中的 getContentBean 方法

protected final Object getContextBean() {return this.type != null ? this.type : super.getContextBean();
}

而 NewElementHandler 中的 getContextBean 方法又是因为继承关系调用了来自于 ElementHandler 中的 getContextBean 方法。

protected Object getContextBean() {if (this.parent != null) {
ValueObject var2 = this.parent.getValueObject();if (!var2.isVoid()) {return var2.getValue();
} else {throw new IllegalStateException("The outer element does not return value");
}
} else {
Object var1 = this.owner.getOwner();if (var1 != null) {return var1;
} else {throw new IllegalStateException("The topmost element does not have context");
}
}

而这里的 getValueObjcet 操作根据我的断点执行了两次。

XMLdecoder安全漏洞分析

我们可以看一下结果,第一次进入 NewElementHandler 中进行 getValueObject 实际上在 type 里面是没有 class 的值的。而第二次进入 NewElementHandler 中进行 getValueObject 操作的时候 type 是取到相关的 class 的值。

XMLdecoder安全漏洞分析
XMLdecoder安全漏洞分析

那么根据上面所说这里势必会进入到 ObjectElementHandler 中的 getValueHandler 方法进行处理,而在这个方法的最后是调用了 Expression 中的 getValue 方法,这里可以看到我们要执行的命令以及 class 对象都已经传入了。

XMLdecoder安全漏洞分析

而进一步动态调试我们可以看到 Expression 中的 getValue 已经返回我们需要的命令执行对象类,以及命令参数了。

XMLdecoder安全漏洞分析

然后会重新回到 Void 标签对应的 getValueObject 函数,由于 ViodElementHandler 继承 ObjectElementHandler ,而我们这里设置的 method 等于 start ,因此这里通过 Expression 的反射机制调用了 start 函数,所以到这里自然命令执行了。

XMLdecoder安全漏洞分析

这个是从师傅文章里看到的小贴士,自己跟下来之后确实是这样

    PS: 虽然ObjectElementHandler继承自NewElementHandler,但是其重写了getValueObject函数,两者是使用不同方法创建类的实例的。

    再PS: 其实不加java标签也能用,但是没法包含多个对象了。

然后再补充一下@fnmsd师傅画的流程图

XMLdecoder安全漏洞分析


No.6

补丁

Oracle关于这个xmldecoder造成的漏洞的CVE编号分别是CVE-2017-3506、CVE-2017-10271、CVE-2019-2725。最早关于CVE-2017-3506的补丁只是根据Object标签进行了限制。

XMLdecoder安全漏洞分析

而根据我们前面的继承关系可以讲 object 替换成 void 即可,它们实际上是不受影响的,因此便出现了CVE-2017-10271,而针对CVE-2017-10271的补丁限定了所有具有执行的节点。

XMLdecoder安全漏洞分析

但这次 CVE-2019-2725 主要是 class 标签,class 标签可代替 object 标签来生成对象,因此这次漏洞本质还是xmldecoder的问题,而补丁也是针对class标签来处理的。

XMLdecoder安全漏洞分析


No.7

修复建议

1、代码层防护。使用白名单,参考修复部分代码如下:

XMLdecoder安全漏洞分析

    2、采用第三方防护设备进行防护,如waf、云waf等。


No.8

招聘启事

安全招聘
————————

公司:安恒信息
岗位:Web安全 安全研究员
部门:安服战略支援部
薪资:13-30K
工作年限:1年+
工作地点:杭州(总部),广州
岗位剩余编制:3人
工作环境:一座大厦,健身场所,医师,帅哥,美女,高级食堂…

【岗位职责】
1.定期面向部门、全公司技术分享;
2.前沿攻防技术研究、跟踪国内外安全领域的安全动态、漏洞披露并落地沉淀;
3.负责完成部门渗透测试、红蓝对抗业务;
4.负责自动化平台建设
5.负责针对常见WAF产品规则进行测试并落地bypass方案

【岗位要求】
1.至少1年安全领域工作经验;
2.熟悉HTTP协议相关技术
3.拥有大型产品、CMS、厂商漏洞挖掘案例;
4.熟练掌握php、java、asp.net代码审计基础(一种或多种)
5.精通Web Fuzz模糊测试漏洞挖掘技术
6.精通OWASP TOP 10安全漏洞原理并熟悉漏洞利用方法
7.有过独立分析漏洞的经验,熟悉各种Web调试技巧
8.熟悉常见编程语言中的至少一种(Asp.net、Python、php、java)

【加分项】
1.具备良好的英语文档阅读能力;
2.曾参加过技术沙龙担任嘉宾进行技术分享;
3.具有CISSP、CISA、CSSLP、ISO27001、ITIL、PMP、COBIT、Security+、CISP、OSCP等安全相关资质者;
4.具有大型SRC漏洞提交经验、获得年度表彰、大型CTF夺得名次者;
5.开发过安全相关的开源项目;
6.具备良好的人际沟通、协调能力、分析和解决问题的能力者优先;
7.个人技术博客;
8.在优质社区投稿过文章;


岗位:安全红队武器自动化攻城狮
薪资:13-30K
工作年限:2年+
工作地点:杭州(总部)

【岗位职责】
1.负责红蓝对抗中的武器化落地与研究;
2.平台化建设;
3.安全研究落地。

【岗位要求】
1.熟练使用Python、java、c/c++等至少一门语言作为主要开发语言;
2.熟练使用Django、flask 等常用web开发框架、以及熟练使用mysql、mongoDB、redis等数据存储方案;
3:熟悉域安全以及内网横向渗透、常见web等漏洞原理;
4.对安全技术有浓厚的兴趣及热情,有主观研究和学习的动力;
5.具备正向价值观、良好的团队协作能力和较强的问题解决能力,善于沟通、乐于分享。

【加分项】
1.有高并发tcp服务、分布式等相关经验者优先;
2.在github上有开源安全产品优先;
3:有过安全开发经验、独自分析过相关开源安全工具、以及参与开发过相关后渗透框架等优先;
4.在freebuf、安全客、先知等安全平台分享过相关技术文章优先;
5.具备良好的英语文档阅读能力。

设计师

————————

【职位描述】
负责设计公司日常宣传图片、软文等与设计相关工作,负责产品品牌设计。

【职位要求】
1、从事平面设计相关工作1年以上,熟悉印刷工艺;具有敏锐的观察力及审美能力,及优异的创意设计能力;有 VI 设计、广告设计、画册设计等专长;
2、有良好的美术功底,审美能力和创意,色彩感强;精通photoshop/illustrator/coreldrew/等设计制作软件;
3、有品牌传播、产品设计或新媒体视觉工作经历;

【关于岗位的其他信息】
企业名称:杭州安恒信息技术股份有限公司
办公地点:杭州市滨江区安恒大厦19楼
学历要求:本科及以上
工作年限:1年及以上,条件优秀者可放宽


简历投递至 strategy@dbappsecurity.com.cn



【工作地点】

杭州、广州


简历投递至 strategy@dbappsecurity.com.cn


安全服务工程师/渗透测试工程师


工作地点:新疆


1、掌握渗透测试原理和渗透测试流程,具备2年以上渗透测试工作经验,能够独立完成渗透测试方案和测试报告;
2、熟悉风险评估、安全评估;
3、熟练掌握各类渗透工具,如Sqlmap、Burpsuite、AWVS、Appscan、Nmap、Metasploit、Kali等;
4、熟练掌握Web渗透手法,如SQL注入、XSS、文件上传等攻击技术;
5、至少熟悉一种编程语言(php/java/python),能够独立编写poc者优先;
6、具有良好的沟通能力和文档编写能力,动手能力强;
7、对工作有热情,耐心、责任心强,具备沟通能力和良好的团队意识;
8、加分项:有安全开发经验/可进行代码审计工作;
9、加分项:有安全和网络相关证书,如CISSP、CISA、CISP 、CCNP、CCIE等认证者;
岗位职责:
1、参与安全服务项目实施,其中包括渗透测试与安全评估,代码审计,安全培训,应急响应;
2、独立完成安全服务项目报告编写,输出安全服务实施报告;

专注渗透测试技术

全球最新网络攻击技术


END


以上是关于XMLdecoder安全漏洞分析的主要内容,如果未能解决你的问题,请参考以下文章

Restlet XMLDecoder 远程代码执行漏洞分析(CVE-2013-4221)

xmldecoder反序列化漏洞分析

[Java安全]XMLDecoder反序列化学习

[Java安全]XMLDecoder反序列化学习

JAVA漏洞重现:XMLDecoder反序列化漏洞

XMLDecoder反序列化漏洞检测思考