XStream反序列化漏洞分析

XStream反序列化漏洞分析

把之前看的XStream反序列化漏洞分析过程做个笔记,从前期JAVA的代理模式动态代理基础知识到XStream解析流程都有记录。

代理模式

代理是设计模式中的一种,代理类为委托类提供消息预处理、消息转发、事后消息处理等功能,JAVA中代理分为三种角色:代理类、委托类、接口。
在这里插入图片描述
以上的定义和图片过于官方和范文化,不方便理解,这里举一个具体简单理解的实例。
用户在成都想要买电脑,成都电脑代理商和北京电脑总公司都可以买,其中的电脑代理商指的就是代理类,电脑总公司就是委托类,他两都具有卖电脑这个方法,而且成都代理商的卖电脑方法其实还是北京总公司的卖电脑方法,大致情况参考如下手动画图。
在这里插入图片描述
抛出以下两个问题思考:

一、为什么要通过代理商买电脑?(代理模式的意义)

  1. 去北京总公司买电脑成本太高(直接调用委托类的方法太复杂)

二、通过代理商买电脑的好处?(代理模式的优势)增强作用

  1. 代理商可控制价格(参数增强)
  2. 同样价格代理商还送赠品(返回值增强)
  3. 代理商买电脑车接车送(方法逻辑增强)

代理模式包括静态代理和动态代理

静态代理的实现:
接口:
在这里插入图片描述

委托类:
在这里插入图片描述

代理类:
在这里插入图片描述

测试类:
在这里插入图片描述
在这里插入图片描述

动态代理的实现

委托类:
在这里插入图片描述

代理类:
在这里插入图片描述

测试类:
在这里插入图片描述

动态代理调用方法时是通过代理类的invoke方法调用的

参考:
https://www.bilibili.com/video/BV1qv4y1o79t?p=366&vd_source=2ad59243ca70d5beaed54382e53e0c18
https://www.cnblogs.com/cC-Zhou/p/9525638.html

EventHandler

EventHandler类是实现了InvocationHandler的一个代理类,EventHandler的构造方法传入四个参数,重点是第一个target对象和第二个action字符串。
在这里插入图片描述

其invoke方法调用了invokeInternal方法
在这里插入图片描述
invokerInternal方法由通过反射调用了构造方法中传入的target对象的action方法。
在这里插入图片描述
效果就是当EventHandler作为代理类用于创建动态代理时,执行动态代理的方法时,传入EventHandler的target对象的action方法会被执行。

我们new一个EventHandler对象,并把target设置设置为ProcessBuilder对象,action设置为start,将其作为代理类新建一个动态代理程序proxy。
在这里插入图片描述
通过动态代理程序执行委托类的方法
在这里插入图片描述

XStream

XStream是一个简单的基于Java库,Java对象序列化到XML,反之亦然(即:可以轻易的将Java对象和xml文档相互转换)。

代码实现XStream 对象转换为xml:
在这里插入图片描述
在这里插入图片描述
XStream xml转换为对象:

在这里插入图片描述
在这里插入图片描述

生成payload

我们利用XStream的toXML方法,将我们构造的代理类为EventHandler的动态代理对象转化成xml形式
在这里插入图片描述
在这里插入图片描述

<dynamic-proxy>
    <interface>HelloService</interface>
    <handler class="java.beans.EventHandler">
        <target class="java.lang.ProcessBuilder">
            <command>
                <string>calc</string>
            </command>
            <redirectErrorStream>false</redirectErrorStream>
        </target>
        <action>start</action>
    </handler>
</dynamic-proxy>

将生成的payload利用XStream的fromXML转换成JAVA对象并调用对象中的某一个方法
在这里插入图片描述

整个利用过程如下:

XML—动态代理对象—利用动态代理调用委托类的方法—代理类的invoke—EventHandler的invoke—通过反射调用target的action方法—Processbuilder.start(“calc”)

以下为XStream官方发布的payload
https://x-stream.github.io/CVE-2013-7285.html

但我们生成的payload需要满足两点后才能利用成功,一是目标机器要安装我们指定的接口,二是目标服务端在使用fromXML方法将xml转化成JAVA对象后又调用了对象的任意方法,这样利用起来限制条件太多,我们利用以下payload就不需要满足以上两点,payload中的java.lang.Comparable接口是JAVA JDK中自带的所以目标机器一定会有此接口,且XStream在反序列化解<sorted-set>标签时,会调用java.lang.Comparable中的compare To方法,因此也不需要目标机器在转化后又调用对象的某一方法。

<sorted-set>
    <dynamic-proxy>
        <interface>java.lang.Comparable</interface>
        <handler class="java.beans.EventHandler">
            <target class="java.lang.ProcessBuilder">
                <command>
                    <string>calc</string>
                </command>
            </target>
            <action>start</action>
        </handler>
    </dynamic-proxy>
</sorted-set>

XStream流程分析

TreeUnmarshaller 树解组程序,调用mapper和Converter把XML转化成java对象,里面的start方法开始解组,convertAnother方法把class转化成java对象。

TreeMarshaller 树编组程序,调用mapper和Converter把java对象转化成XML,里面的start方法开始编组,convertAnother方法把java对象转化成XML。

以下为TreeUnmarshaller 树解组程序主要部分及各部分的一些重要方法,mapper主要是利用realClass方法将xml解析转化成class,convert将class选择相应的convert后转化成JAVA对象。
在这里插入图片描述
解析过程开始:TreeUnmarshaller的start方法
在这里插入图片描述
ReadClassType方法:若classAttribute值为空则返回标签节点的class
在这里插入图片描述在这里插入图片描述
realClass在返回class之前会进行一步安全校验,判断返回的class是否在黑名单中,如果在黑名单中则报错。
在这里插入图片描述
获取到class之后利用lookupConverterForType找到对应的converter
在这里插入图片描述
Convert方法通过unmarshal方法将class转换成java实例对象
在这里插入图片描述
Ummarshal调用populateTreeMap
在这里插入图片描述
populateTreeMap调用putCurrentEntryIntoMap
在这里插入图片描述
这里调用readItem方法,并且将返回的Object对象放入target这个map中
在这里插入图片描述
ReadItem又获取下一个标签的class对象并将class对象转换成java对象
在这里插入图片描述
这次获取的标签为dynamic-proxy,因此返回的class为DynamicProxy
在这里插入图片描述
在这里插入图片描述
这里判断了一些标签内容是否为interface和handler,如果是interface就将获取的class放入interfaces这个列表,如果是handler就将代理对象赋值给handlerType
在这里插入图片描述
获取完class后,创建动态代理
在这里插入图片描述
生成EventHandler对象后将原先生成的动态代理替换
在这里插入图片描述
然后putCurrentEntryIntoMap方法执行完后,接着调用putAll方法
在这里插入图片描述
PutAll方法调用put方法
在这里插入图片描述
Put方法调用compare方法
在这里插入图片描述
compare方法又调用了compareTo方法
在这里插入图片描述
compareTo方法的介绍如下:
在这里插入图片描述
它是java.lang.Comparable的一个方法,所以相当于执行了委托类的任意方法,再后面就是动态代理机制了,调用EventHandler的invoke就可以弹出计算器了。

写在最后

今天降温了,天冷吃个火锅
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值