shiro反序列化工具_Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)源码解析

1c284c726376d114049a41a783993752.png

Apache Shiro

Apache Shiro是一个功能强大且灵活的开源安全框架,主要功能包括用户认证、授权、会话管理以及加密。在了解该漏洞之前,建议学习下Apache Shiro是怎么使用.

debug环境

  • jdk1.8
  • Apache Shiro 1.2.4
  • 测试demo

本地debug需要以下maven依赖

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.4</version>
        </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.2.4</version>
        </dependency>

漏洞产生流程

一般登录时,存在记住我的功能,如下图:

fd9c8708d2cee3eb571428c7aaf8c684.png

Apache Shiro框架就是在实现该功能时存在漏洞.

Apache Shiro如何记住我?

  1. 序列化用户身份对象.(这里为SimplePrincipalCollection)
  2. 对序列化后的数据进行AES加密,密钥为常量.
  3. base64编码
  4. 设置到cookie中,cookie name等于rememberMe.

Apache Shiro如何解析我?

  1. 读取cookie中的rememberMe的值.
  2. 对其值进行base64解码.
  3. AES解密
  4. 反序列化

我们如何攻击?

通过以上,我们可以看出,只要手动构造一个反序列化payload,进行AES加密(密钥我们知道的)和base64编码,即可在反序列化时执行任何操作.

源码解析

记住我源码分析

打开登录界面,输入admin/vulhub,勾选Remember me,点击登录.首先进入用户代码中调用Apache Shiro验证接口的方法.

cd04b6c551540cdb9b00443d42ffb5fb.png

接着正式进入Apache Shiro处理. 一些不重要的调用过程省略,调用栈如下:

0231f72824746187d3c48f527a03b148.png

我们在org.apache.shiro.mgt/AbstractRememberMeManager.onSuccessfulLogin下断点.

389ff30ef3509cbad4059a32399f2bfc.png

从上面代码我们发现,首先程序清理了验证信息.接着调用rememberIdentity来保存新的验证信息.跟进该方法.

a9ea8cd4ba729aa8963a01fee855d1d8.png

我们发现该方法首先去获取一个PrincipalCollection对象.该对象就是保存在cookie中的对象.接着调用rememberIdentity保存该对象.跟进rememberIdentity方法.

c748cf2516b10ff7bfadc8514d9e3a6a.png

我们先看它是如何反序列化和AES加密的.跟进byte[] bytes = convertPrincipalsToBytes(accountPrincipals);.

5f2c9a8d23f25dd50e02ba4459e7d3a3.png

从以上代码可以发现,调用serialize序列化为byte数组.这一步不做分析.我们重点看看如何进行AES加密的.跟进encrypt(bytes).

449c38af6a673629bb5a0e6318fb24ae.png

首先该方法获取AES加密service.再通过getEncryptionCipherKey()得到密钥.最后对序列化后的对象进行加密.其中密钥是一个常量,该常量在org/apache/shiro/mgt/AbstractRememberMeManager.AbstractRememberMeManager设置.常量值如下:

67a51b758e351e133b4fbdd21a25c157.png

回到rememberIdentity方法,我们继续来看下面的rememberSerializedIdentity方法.

340929fbba5b79d9181e15e6025af67b.png

通过以上过程,Apache Shiro完成了如何记住我.

解析我源码分析

在源码分析之前,提一个debug遇到的坑,Apache Shiro在设置rememberme这个cookie的同时也会设置一个JSessionid cookie,当通过浏览器进行发送请求,请删除掉JSessionid cookie,否则Apache Shiro通过JSessionid获取验证信息,并不会经过解析我的过程,也就无法debug 我们在上一步登录后,删除JSessionid cookie,访问http://localhost:8080.在org/apache/shiro/mgt/DefaultSecurityManager.getRememberedIdentity下断点.

b2264f00c0b102c209ae5e417ce7cd5f.png

该方法主要获取存储在cookie中的Principal对象,我们跟进getRememberedPrincipals方法内.

cbf281a743486edf1d9d2acba96a28be.png

从上述源码可以发现,通过getRememberedSerializedIdentity进行cookie的提取和base64解密.接着通过convertBytesToPrincipals进行AES解密和反序列化得到Principals对象.我们重点看看convertBytesToPrincipals该方法.

578f5051f5adeb68a9d3fbac8b140bf5.png

很显然,该方法中通过decrypt进行AES解密.跟进decrypt.

93d8b78b08a5cda48da92f74a3dbdb0c.png

该方法和加密基本一样.先获取cipherService,再通过密钥解密. 再回到convertBytesToPrincipals方法中.调用deserialize进行反序列化.至此反序列化漏洞的触发过程就结束了.

修复

我们再来看看1.2.5如何修复的. 1.2.5:

c66494d4bfbc6a628d273434522f1c52.png

1.2.4:

3416e593afb9c7b40bef7a4ec93afeac.png

通过上述可以看出1.2.5将密钥动态生成.避免了攻击者可以自己生成序列化恶意对象.这个漏洞可以说是硬编码密钥导致的反序列化漏洞.

最后

关于该漏洞的利用可以参考vulhub.该文章旨在分享,后面也会就vulhub上的demo来做一系列的漏洞原理的分享.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值