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 的具体调用

image-20231106152932289

image-20231106153042805

登录方法最后登录成功会有一个onSuccessfulLogin方法进行 rememberme 操作。

image-20231106153749074

image-20231106153934265

296判断是否标记使用 rememberme,然后 297 执行操作

image-20231106154015689

image-20231106154124869

image-20231106154234230

org.apache.shiro.mgt.AbstractRememberMeManager#convertPrincipalsToBytes

这里可以看到getCipherService不为空的时候,会将 principals 序列化的代码进行加密。

image-20231106154303920

org.apache.shiro.mgt.AbstractRememberMeManager#encrypt

这个是具体的加密函数,getCipherService()获取加密服务,getEncryptionCipherKey()获取加密 key。

image-20231106155615187

在初始化这里,可以看到具体的配置,加密服务是 aes,key 是明文base64编码后硬编码在代码中。

image-20231106155826235

image-20231106155920312

org.apache.shiro.web.mgt.CookieRememberMeManager#rememberSerializedIdentity

这里将序列化的代码存储cookie 中。

image-20231106154602173

然后我们看一下从字节转换为对象的过程,即反序列化

org.apache.shiro.mgt.AbstractRememberMeManager#convertBytesToPrincipals

可以看到先经过 decrypt 解密,然后deserialize反序列化

image-20231106160625360

org.apache.shiro.io.DefaultSerializer#deserialize

然后找到实际的反序列化实现

image-20231106160756600

org.apache.shiro.io.ClassResolvingObjectInputStream#resolveClass

关键点在于ClassUtils.forName(osc.getName());

image-20231106160919570

org.apache.shiro.util.ClassUtils#forName

image-20231106161139214

可以看到这里会有 classloader 的不同,但是实际没有继续往下追的必要了,对漏洞的影响不大

image-20231106161216391

image-20231106161400870

0x02 修复分析

修复代码就是将硬编码删除,改为启动之后自动生成一个 key。

image-20231106161929432