天天看点

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用

​<code>​apache common beanutils​</code>​是​<code>​apache common​</code>​工具集下的另一个项目,提供了一系列对javabean的操作方法。什么是javabean:​​什么是javabean​​。

如下​<code>​cat​</code>​就是一个javabean。

​<code>​commons-beanutils​</code>​中提供了一个静态方法​<code>​propertyutils.getproperty​</code>​,让使用者可以直接调用任意javabean的​<code>​getter​</code>​方法。

此时​<code>​propertyutils.getproperty​</code>​会自动调用​<code>​cat​</code>​的​<code>​getname​</code>​方法,获取返回值。其实就是会自动调用参数1的getter方法。

其实这个利用链上半段使用的还是​<code>​priorityqueue​</code>​,而​<code>​priorityqueue​</code>​的核心就在于找可以利用的​<code>​java.util.comparator​</code>​对象。

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用
Java反序列化(十)CommonsBeanutils分析及Shiro中的利用

在​<code>​commons-beanutils​</code>​包中就存在一个:​<code>​org.apache.commons.beanutils.beancomparator​</code>​。

​<code>​beancomparator​</code>​是用来比较两个javabean是否相等的两个类,实现了​<code>​java.util.comparator​</code>​接口。查看一下他的compare方法。

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用

这个方法接收了两个对象,如果​<code>​this.property​</code>​属性值为空,则直接比较这两个对象。如果不为空,则使用​<code>​propertyutils.getproperty​</code>​获取两个对象的​<code>​this.property​</code>​的值。然后进行比较。

上面说了​<code>​propertyutils.getproperty​</code>​这个方法会自动去调用一个​<code>​javabean​</code>​的​<code>​getter​</code>​方法,这个点是任意代码执行的关键。有没有什么getter方法可以执行恶意代码呢?

当然是有的,在​<code>​templatesimpl#getoutputproperties()​</code>​方法中会调用​<code>​newtransformer​</code>​方法(后面的利用链就不说了,不明白的去了解一下templatesimpl的利用链)。并且是​<code>​public​</code>​。支持外部调用。而且​<code>​getoutputproperties​</code>​是以get开头的,符合getter的定义。

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用

所以,​<code>​propertyutils.getproperty( o1, property )​</code>​这段代码,当​<code>​o1​</code>​是一个​<code>​templatesimpl​</code>​对象,而​<code>​property​</code>​的值为​<code>​outputproperties​</code>​时,将会自动调用getter,也就是​<code>​templatesimpl#getoutputproperties()​</code>​方法,触发代码执行。

最终代码如下

所需的maven

在shiro550的实际利用中,目标可能没有使用​<code>​commons-collections​</code>​。这就导致无法使用cc链进行rce。这个时候还有其他方法可以进行rce吗?

可以看到shiro的pom.xml中有​<code>​commons-beanutils​</code>​的依赖,版本为​<code>​1.8.3​</code>​。也就是说shiro本身自带了​<code>​commons-beanutils​</code>​依赖,只要使用了shiro组件,就必定有​<code>​commons-beanutils​</code>​。

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用

那么是否可以利用本文提到的​<code>​commonsbeanutils​</code>​链进行利用?

当我构造好payload发送过去的时候,服务端报错了,报错如下

查看报错​<code>​java.io.invalidclassexception: org.apache.commons.beanutils.beancomparator; local class incompatible: stream classdesc serialversionuid = -2044202215314119608, local class serialversionuid = -3490850999041592962​</code>​。这个错误是什么意思?

什么是​<code>​serialversionuid​</code>​?

如果两个不同版本的库使用了同一个类,而这两个类可能有一些方法和属性有了变化,此时在序列化通信的时候就可能因为不兼容导致出现隐患。因此,java在反序列化的时候提供了一个机制,序列化时会根据固定算法计算出一个当前类的serialversionuid值,写入数据流中;反序列化时,如果发现对方的环境中这个类计算出的serialversionuid不同,则反序列化就会异常退出,避免后续的未知隐患。 当然,开发者也可以手工给类赋予一个serialversionuid值,此时就能手工控制兼容性了。

所以出现这个错误的原因就是我序列化的时候用的是​<code>​commons-beanutils 1.9.4版本​</code>​。而shiro自带的是​<code>​commons-beanutils 1.8.3版本​</code>​,出现了serialversionuid对应不上的问题。

解决方法也很简单,将​<code>​commons-beanutils版本​</code>​修改为​<code>​1.8.3​</code>​即可。

当我修改完版本之后,重新生成序列化文件的时候报错了。错误如下

提示找不到​<code>​comparablecomparator​</code>​这个类。

跟踪堆栈信息,

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用

看到​<code>​org.apache.commons.collections.comparators.comparablecomparator;​</code>​,从包名即可看出,这个类是来自于commons-collections。

​<code>​commons-beanutils​</code>​本来依赖于​<code>​commons-collections​</code>​,但是在shiro中,它的​<code>​commons-beanutils​</code>​虽然包含了一部分​<code>​commons-collections​</code>​的类,但却不全。这就导致正常使用shiro的时候不需要依赖于​<code>​commons-collections​</code>​,但反序列化利用的时候需要依赖于​<code>​commons-collections​</code>​

难道没有​<code>​commons-collections​</code>​就无法进行反序列化利用吗?当然有。

分析​<code>​comparablecomparator​</code>​在哪里使用了,在​<code>​beancomparator​</code>​构造方法中使用了,如下图。下面那个构造方法可以指定​<code>​comparator​</code>​,就无需实例化​<code>​comparablecomparator​</code>​。

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用

现在的问题是我们如何去寻找一个的类,这个类需要满足以下条件

1.实现java.util.comparator接口

2.实现java.io.serializable接口

3.java、shiro或commons-beanutils自带,且兼容性强。则不需要其他的依赖。

p牛找到了​<code>​caseinsensitivecomparator​</code>​类。

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用

这个caseinsensitivecomparator类是java.lang.string类下的一个内部私有类,其实现了comparator和serializable,且位于java的核心代码中,兼容性强,是一个完美替代品。

通过​<code>​string.case_insensitive_order​</code>​即可拿到上下文中的​<code>​caseinsensitivecomparator​</code>​对象,用它来实例化​<code>​beancomparator​</code>​:

修改好代码之后,又报错了,

integer无法转换为string。那么将​<code>​1​</code>​改为​<code>​"1"​</code>​即可

发送这个利用链生成的payload,成功执行任意代码:

Java反序列化(十)CommonsBeanutils分析及Shiro中的利用