Apache Shiro550
之前有做过vulhub漏洞复现-Apache Shiro(CVE-2016-4437) 反序列化漏洞复现,这里记录一下调试分析过程。
Apache Shiro是一个开源安全框架,提供身份验证、授权、密码学和会话管理。在Apache Shiro <= 1.2.4版本中存在反序列化漏洞,而整体的思路就是Shiro的“记住我”功能是设置cookie中的rememberMe值来实现。当后端接收到来自未经身份验证的用户的请求时,处理Cookie的流程是
- 检索cookie中RememberMe的值
- Base64解码
- 使用AES解密
- 反序列化
这里的每一步我们都能构造(AES加解密的密钥是写死在代码中的),所以我们可以构造RememberMe的值,然后让其反序列化执行。
环境搭建
所需环境
编辑器: IDEA 2020(用的pj版本,会用到一个Tomcat Server)
java版本:jdk1.7.0_80
Server版本 : Tomcat 8.5.75(直接下载core下面的zip)
shiro版本:shiro-root-1.2.4
搭建
下载完shiro后手动增加version代码
<version>1.2</version>
随后导入进来,如果有已经打开的项目先close
导入过程不要动,静静等它下载完!ok后点击锤子后面的Edit Configurations
(下图最上面红色方框那个位置),按下图配置
选出samples-web:war
后ok,运行
漏洞分析
加密过程
我们要研究的是开启RememberMe后登录的过程,所以从org.apache.shiro.mgt.AbstractRememberMeManager#onSuccessfulLogin
处开始即可,这里是判断是否开启RememberMe然后开始操作的地方,所以从这里下个断点,然后开始debug
这里先清除认证信息,然后通过isRememberMe()判断是否有认证信息,也就是是否开启了RememberMe选项框,跟进rememberIdentity()方法
首先调用getIdentityToRemember函数来获取用户身份(用户root),接着跟进rememberIdentity构造方法
其实convertPrincipalsToBytes方法将accountPrincipals(也就是用户root)转换为字节形式,我们可以跟进研究一下
这里将Principals(用户root)序列话后进行encrypt加密,跟进encrypt函数
这里我们可以在debug中看到加密方式,而encrypt函数其实就是调用AES方法对序列化后的用户root进行加密,加密的密钥由getEncryptionCipherKey()得到,然而这里跟进getEncryptionCipherKey()函数会发现其值为常量
这一步加密完成后我们继续返回跟进rememberSerializedIdentity
base64编码后,设置到cookie中,其实到这里就是存入的全部流程,序列化—>AES加密—>base64编码—>设置到cookie中的rememberme字段。
解密过程
加密过程那就从收到认证开始分析,我们从org.apache.shiro.mgt.DefaultSecurityManager#getRememberedIdentity
开始断点分析
跟进到getRememberedPrincipals
再跟进到getRememberedSerializedIdentity
与convertBytesToPrincipals
,看一下分别是用来干嘛的。
首先在getRememberedSerializedIdentity
我们发现它读取了cookie并进行base64解码,这里进到convertBytesToPrincipals
函数
发现在convertBytesToPrincipals
函数中,对cookie进行decrypt并反序列化,而decrypt明显就是AES解密了。
解密的流程到这就结束了,读取cookie中的rememberMe—>base64解码—>AES解密—>反序列化
参考分析调试apache shiro反序列化漏洞(CVE-2016-4437)
参考Shiro 550 反序列化漏洞 详细分析+poc编写