CVE-2016-4437
https://xz.aliyun.com/t/11633#toc-10
https://github.com/vulhub/vulhub/tree/master/shiro/CVE-2016-4437
https://github.com/apache/shiro/commit/4d5bb000a7f3c02d8960b32e694a565c95976848
0x00 概述
Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中。攻击者可以使用Shiro的默认密钥伪造用户Cookie,触发Java反序列化漏洞,进而在目标机器上执行任意命令。
影响范围:
- shiro 1.x < 1.2.5
0x01 漏洞分析
这里用 vulhub 的环境源码来追一下,找一下关键点。
这里是调用 login 方法,往下追一下,rememberme 的具体调用
登录方法最后登录成功会有一个onSuccessfulLogin
方法进行 rememberme 操作。
296判断是否标记使用 rememberme,然后 297 执行操作
org.apache.shiro.mgt.AbstractRememberMeManager#convertPrincipalsToBytes
这里可以看到getCipherService
不为空的时候,会将 principals 序列化的代码进行加密。
org.apache.shiro.mgt.AbstractRememberMeManager#encrypt
这个是具体的加密函数,getCipherService()
获取加密服务,getEncryptionCipherKey()
获取加密 key。
在初始化这里,可以看到具体的配置,加密服务是 aes,key 是明文base64编码后硬编码在代码中。
org.apache.shiro.web.mgt.CookieRememberMeManager#rememberSerializedIdentity
这里将序列化的代码存储cookie 中。
然后我们看一下从字节转换为对象的过程,即反序列化
org.apache.shiro.mgt.AbstractRememberMeManager#convertBytesToPrincipals
可以看到先经过 decrypt
解密,然后deserialize
反序列化
org.apache.shiro.io.DefaultSerializer#deserialize
然后找到实际的反序列化实现
org.apache.shiro.io.ClassResolvingObjectInputStream#resolveClass
关键点在于ClassUtils.forName(osc.getName());
org.apache.shiro.util.ClassUtils#forName
可以看到这里会有 classloader 的不同,但是实际没有继续往下追的必要了,对漏洞的影响不大
0x02 修复分析
修复代码就是将硬编码删除,改为启动之后自动生成一个 key。