0x00 前言
XmlDeocoder
是java自带的以SAX方式解析xml的类。其在反序列化经过特殊构造的数据时可执行任意命令。Weblogic中就因为默认包含的wls-wast
、wls9_async_response war
、_async
等包中采用xmldecoder处理XML数据,出现了多次具有严重影响的反序列化漏洞:CVE-2017-3506 -> CVE-2017-10271(10352) -> CVE-2019-2725 -> CVE-2019-2729
下面是在学习XmlDecoder
反序列化漏洞过程中的一点学习记录。本次分析使用JDK版本为1.7.0_80
0x01 Xmldecoder反序列化过程
1 | //XmlTest.java |
使用上面的代码进行本次的动态跟踪xmldecoder
反序列化流程
1.xml
中的内容为经过特殊构造的xml数据,效果为弹出计算器
1 |
|
在java.lang.ProcessBuilder
类的start
方法处下断点,可以看到calc
命令被传入执行,并且函数调用栈非常深。
下面在readObject
处下断点,开始对整个过程动态追踪。
XMLDecoder的解析过程是基于Java自带的SAX XML解析进行的。所有类都在com.sun.beans.decoder包中。
前面的调用栈有点深,这里不做详细记录了,直接跳到DocumentHandler
类的startElement
方法处跟踪对标签的解析。
在DocumentHandler
的构造函数中,针对不同的标签,对应类不同的ElementHandler
进行处理
首先解析object
标签,创建ObjectElementHandler,设置Owner和Parent
跟进addAttribute
方法进行属性设置,由于该方式没有对class属性做处理,因此会调用ObjectElementHandler父类的方法,即NewElementHandler
类的addAttribute
方法。
在该方法中进入对class属性的处理,设置type值为java.lang.ProcessBuilder
对应的对象
设置完属性值后,调用startElement
方法,这里不满足条件,直接退出。
然后开始解析array
标签,创建ArrayElementHandler,设置Owner和Parent
同样调用addAttribute
方法进行属性设置,这里继续调用了ArrayElementHandler
父类NewElementHandler
的addAttribute
方法
设置type为java.lang.String
类对应的对象
继续设置array的length
属性后,最后进入到startElement
方法,这里array具有length属性,继续调用getValueObject
方法
因为ArrayElementHandler
没有getValueObject()
方法,所以调用其父类NewElementHandler
的方法
在父类方法中,又调用本类的有参getValueObject
方法,在该方法中创建了值为String类型长度为length的数组并返回
然后开始处理void
标签,创建VoidElementHandler,设置Owner和Parent
然后调用VoidElementHandler
父类ObjectElementHandler
的addAttribute
方法设置index
属性
继续解析string
标签,创建对应StringElementHandler,设置Owner和Parent。因为继承关系,会调用父类ElementHandler
的startElement()
,其为空方法,直接返回。
接着解析到string
的闭合标签,开始endElement。调用父类的endElement()
方法。
调用本类getValueObject
方法
设置value值为string标签内的内容calc
然后闭合void
标签
然后闭合array
标签,接着继续解析下面的void
标签
调用其父类addAttribute
方法设置method
属性为start
随后调用endElement
方法闭合void
标签,调用其父类的无参getValueObject
方法
在父类getValueObject()
方法中调用本类有参getValueObject
方法
在本类方法中又调用了getContextBean
(注意此处,下面的调用链将为此处v3返回值)
继续跟进,会调用父类ElementHandler的getContexBean
方法
然后会调用parent.getValueObject
即ObjectElementHandler
的getValueObject
方法
而ObjectElementHandler
没有无参getValueObject()
方法,会调用其父类方法。然后又调用类其有参getValueObject
方法,并将返回值赋给value.
继续跟进,会调用getContextBean
方法
然后返回type值即为之前设置的java.lang.ProcessBuilder
对应的对象
最终将这个java.lang.ProcessBuilder
对应的对象赋值到上面提到的v3
之后v4会设置为this.method
,即为start
之后调用创建一个Expresstion
对象,并调用其getValue方法,此方法会在此目标上动态查找具有指定 methodName 的方法,并调用该方法。详情参加Expression。即调用java.lang.ProcessBuilder
的start方法,执行命令,弹出计算器。
0x02 其他利用标签
从上面的继承关系可以看到,VoidElementHandler
继承自ObjectElementHandler
,且仅改写了isArgument()方法,因此对整个触发过程中并无影响,所以此处使用void标签与object标签效果相同。
因此还可以使用下面的利用方式
1 |
|
0x03 后记
篇幅有点长了,这个漏洞也从2019年学到了2020年,菜鸡的java入门之路属实有点难。
后面将再起文章,分析weblogic xmldecoder的反序列化漏洞。
0x04 参考资料
http://jszx-jxpt.cuit.edu.cn/JavaAPI/java/beans/Expression.html