freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Z3专栏 | CommonsCollections8、9、10
2021-12-16 20:11:22
所属地 辽宁省

介绍

本篇学习CommonsCollections8、9、10。CommonsCollections系列最后一篇,但不是JAVA代码审计系列最后一篇。

预备知识:tree数据结构

CC8

先看代码,如图

templates对象在被调用newTransformer时会命令执行
创建了InvokerTransformer类型对象transformer,调用toString方法,看倒数第二行,把iMethodName即toString改为了newTransformer
下一行使用transformer对象创建comp对象
先总结下这些代码,当使用comp对象对两个元素进行compare时,就会调用两个元素的newTransformer方法

继续看,使用comp对象创建了TreeBag,然后将templates对象放进去。看完代码感觉和CC2很像,所以猜测,TreeBag应该是在反序列化时,对内部的元素调用了compare方法。
看下readObject方法,如图

使用comp对象创建了TreeMap,然后交给doReadObject处理

如图调用了map.put,而这个obj正是templates对象

put方法在TreeMap类里实现
如图,看一下代码
当root为null时,会调用compare(key,key)
因为这个元素是第一个添加到tree里的,所以根节点为空,即为null。当添加后,根节点root就是这个元素

ok至此CC8就分析完了

总结

首先是构造comp对象,只要调用comp的compare(templates对象)就会造成命令执行
和CC2很像,CC2是通过优先队列添加元素时需要建堆,调用compare
而CC8通过TreeBag反序列化时,添加根元素会调用compare(key,key)

CC9

代码如图

第一个红框内的代码很熟悉了,最终构造entry对象,只要调用entry.hashCode()或entry.toString()就会命令执行(学习CC5时总结的)
第二个红框内代码看着很多,其实就是新建个Hashtable对象,随便加个元素,然后通过反射将这个元素的key修改为entry。

读完代码了,分析下原因,猜测应该是Hashtable对象反序列化时对元素计算了hash。根据CC7的经验知道Hashtable的readObject方法调用了readHashtable,然后新建空table,再把元素put进去。
直接看readHashtable代码

看下reconstitutionPut方法
如图,调用了key的hashCode方法,而key正是前面构造的entry对象,所以导致了命令执行

疑问

为什么不直接在hashtable放entry对象,而是先随便放个键值对,然后将key改为entry?
看下put方法,如图,put时调用了key.hashCode

难道是防止在构造payload时触发命令执行?
no,看CC9代码,Transformer链在倒数第二行才换为了真正的链,在这之前都不会触发,其实类似问题在CC6遇到过,回想一下。如果直接put,导致key.hashCode -> LazyMap.get(key) ,就会导致LazyMap在map中添加这个键,在反序列化时,因为键已经存在,就不会调用Transformer生成新键值对,就不会造成命令执行。

总结

构建TiedMapEntry类型对象,调用它的hashCode方法导致代码执行

利用hashtable在反序列化时调用了键的hashCode方法,配合1,导致代码执行

CC10

代码很长,但看起来很熟悉,和CC6很像,先看一部分,如图

红框内代码很熟悉了,触发点是entry的hashCode方法
然后创建HashSet对象,添加元素"foo"
继续看

后面这部分代码很多,但其实就是将HashSet刚刚添加的元素"foo",修改为entry。

为什么不直接添加entry?CC9里刚分析过,CC6和CC9都用的这种方式。

总结

回想下CC6的反序列化步骤:
先是HashSet反序列化 -> 对元素entry计算hash -> lazyMap调用get方法 -> 通过InvokerTransformer调用Runtime的exec执行命令
而CC10是
先是HashSet反序列化 -> 对元素entry计算hash -> lazyMap调用get方法 -> 通过InvokerTransformer调用templates的newTransformer -> 加载命令执行的静态代码块

大总结

至此CommonsCollection系列链全部学完了。从CC1到CC10,刚学前几篇都是新知识点,越到后面越简单,可以看见从4开始,就是3个链写在一篇文章里了。
因为知识点在前几篇已经都学过了,后面都是之前用过的知识点,常见套路就那么几个,学到后面几条链,几乎看一眼代码就知道它要做什么了。

总结下常用的几个套路吧,首先总结下用到的类型:

TemplatesImpl:

ysoserial的Gadgets.createTemplatesImpl方法可以创建一个TemplatesImpl对象,只要调用它的newTransformer方法就会命令执行

Transformer:

有很多种,如InvokerTransformer、ChainedTransformer、ConstantTransformer、InstantiateTransformer,用他们可以用来构造Transformer链,只要调用它的transform方法就会触发,学过的所有链,都离不开它,和它配合的有两个,一个是直接调用Runtime对象的exec,一个是调用TemplatesImpl对象的newTransformer

LazyMap、TreeBag、PriorityQueue:

他们都是用来触发Transformer的,LazyMap的get方法会触发,TreeBag和PriorityQueue利用TransformingComparator的compare触发,而TreeBag和PriorityQueue在反序列化时就会调用compare,所以可以用它俩生成最终的payload。而LazyMap需要其他类触发它的get方法

TiedMapEntry、Hashtable、AnnotationInvocationHandler:

他们可以用来触发LazyMap的get方法,Hashtable和AnnotationInvocationHandler对象在反序列化时就会触发。而TiedMapEntry需要被调用它的hashCode方法或toString方法

HashSet:

HashSet在反序列时可以触发TiedMapEntry的hashCode

BadAttributeValueExpException:

BadAttributeValueExpException在反序列化时触发TiedMapEntry的toString

文字描述不够生动,画张图,10条链都在这张图里了。


# java漏洞 # java # java反序列化 # Java代码审计 # JAVA安全
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录