SHIRO-550 反序列化漏洞分析

所需环境:

 

1、maven

2、jdk1.6 jdk1.8(默认java环境是1.8,1.6是用于配置下面的toolchains)

3、eclipse

 

一、搭建漏洞环境

 

下载漏洞示例代码 https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4

 

解压并使用eclipse导入samples下的web工程(maven工程)。

 

要配置一下maven,在maven/conf/toolchains.xml中的toolchains 中添加以下代码

 

  <toolchain>

    <type>jdk</type>

    <provides>

      <version>1.6</version>

      <vendor>sun</vendor>

    </provides>

    <configuration>

      <jdkHome>C:/Program Files/Java/jdk1.6.0_45</jdkHome>

    </configuration>

  </toolchain>

 

 

然后在pom.xml文件所在目录下执行mvn install命令就可以正常打包编译工程了。

 

 

 

二、漏洞简介

 

看看漏洞描述

https://issues.apache.org/jira/browse/SHIRO-550

 

 

 

意思就是说shiro默认使用了CookieRememberMeManager,其处理cookie的流程是:得到rememberMe的cookie值-->Base64解码-->AES解密-->反序列化。然而AES的密钥是硬编码的,就导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞。

 

三、漏洞分析

 

1、先看一下org.apache.shiro.web.mgt.CookieRememberMeManager类的结构

 

 

发现有getRememberedSerializedIdentity这个方法,从字面意思上来看跟rememberMe和序列化都有关系,那么果断在这个函数上下个断点吧。

 

2、在eclipse中开启调试模式,在org.apache.shiro.web.mgt.CookieRememberMeManager中的getRememberedSerializedIdentity下断点,发送payload。

 

 

 

运气不错,成功断在了getRememberedSerializedIdentity上。

 

单步向下跟踪在205行获取到了cookie中的值

 

 

 

 

 


函数返回了rememberMe 的base64解码数据。

 

 

 

3、继续单步执行,发现调到了getRememberedPrincipals函数中,接下来调用了convertBytesToPrincipals。

 

 

 

单步步入

 

 

 

看到了deserialize(窃喜)。

 

4、单步步入decrypt

 

 

 

489行单步步入,跳到了AbstractRememberMeManager中的getDecryptionCipherKey


 

分析代码发现decryptionCipherKey其实就是DEFAULT_CIPHER_KEY_BYTES,而DEFAULT_CIPHER_KEY_BYTES是硬编码在代码中的。

 

 

继续往下走,就到了org.apache.shiro.crypto.JcaCipherService.decrypt(byte[], byte[])中,跟踪到370行

 

 

发现AES的初始化向量iv就是rememberMe的base64解码后的前16个字节。

 

继续跟踪到org.apache.shiro.crypto.JcaCipherService.initNewCipher(int, byte[], byte[], boolean),然后进入org.apache.shiro.crypto.JcaCipherService.newCipherInstance(boolean),


 

408行 我们看到了AES的填充模式为CBC

 

这样,对于AES加密算法,我们既知道了密钥又知道了初始化向量和填充方式,那么整个数据包都可以随意构造了。

 

5、一直跟踪到org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(byte[])函数,返回序列化数据。我们又回到了org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(byte[], SubjectContext)中。

 

 

 

 

跟进deserialize,成功感觉就在眼前。

 

跟踪到org.apache.shiro.io.DefaultSerializer.deserialize(byte[]),77行我们看到了熟悉的readObject函数,binggo,成功弹出计算器。



分析了这么多明白的人应该知道怎么构造payload了,前16字节的密钥,后面加入序列化参数  然后AES加密再base64编码,发送cookie即可。

你可能感兴趣的:(shiro,反序列化)