如何通过CB链分析构建 CommonsBeanutils 反序列化利用链?
摘要:代码审计 | CB链分析 —— CommonsBeanutils 反序列化利用链 目录 环境准备 CB链的执行终点 怎么触发 getOutputProperties() 跟源码 入口:PriorityQueue CB 链 vs CC2 对比
代码审计 | CB链分析 —— CommonsBeanutils 反序列化利用链
目录
环境准备
CB链的执行终点
怎么触发 getOutputProperties()
跟源码
入口:PriorityQueue
CB 链 vs CC2 对比
构造参数分析
BeanComparator 构造方法的坑
add 占位的问题
POC
补充
环境准备
Maven 依赖:
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
CB 链本身只需要 commons-beanutils,但 1.9.2 内部依赖了 CC,调试方便起见加上就行。
CB 链本身只需要 commons-beanutils,但 1.9.2 内部依赖了 CC
(用 maven 下载源码才能搜到原代码)
JDK 8u65
CB链的执行终点
CB 链还是用的 TemplatesImpl 加载恶意字节码,这点和之前的 CC 链一样。
之前用的都是 TemplatesImpl.newTransformer() 为起点,然后一路走下去:
TemplatesImpl.getOutputProperties() → getTransletInstance() → 恶意类.newInstance() → Runtime.exec()
CB 链不再利用 TemplatesImpl 的 newTransformer 调用 getOutputProperties 方法,而是换了一种触发方式。
怎么触发 getOutputProperties()
核心在 BeanComparator 类的 compare 方法:
Object value1 = PropertyUtils.getProperty( o1, property );
Object value2 = PropertyUtils.getProperty( o2, property );
PropertyUtils.getProperty(obj, "outputProperties") 内部用反射找到 getOutputProperties() 方法然后调用。
只要 o1 是 TemplatesImpl 对象,property 是 "outputProperties",就能触发。
跟源码
简单跟一下调用链:
compare
getProperty
getProperty(PropertyUtilsBean)
getNestedProperty
getSimpleProperty
invokeMethod(readMethod, bean, EMPTY_OBJECT_ARRAY) 就是反射调 getter,通过反射调用了 getOutputProperties()。
入口:PriorityQueue
BeanComparator 的 compare 方法签名:
compare( T o1, T o2 )
非常眼熟,正是 CC2 的 PriorityQueue 里面用的那套。
PriorityQueue.readObject() → heapify() → siftDown() → siftDownUsingComparator(),和 CC2 分析的是一样的。
readObject
heapify
siftDown
siftDownUsingComparator
c 和 queue[right] 都需要用到 add → offer 传入。
Object c = queue[child];
int right = child + 1;
add
offer 就是写入数组的方法:
CB 链 vs CC2 对比
回到 BeanComparator 的 compare:
补充对比:
CC2 里的 compare 是 TransformingComparator 的,但 TransformingComparator 是有版本限制的——CC4 版本的 TransformingComparator 才继承了 Serializable 接口,可以被反序列化从而被利用。
