如何通过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 接口,可以被反序列化从而被利用。
阅读全文