Shiro550漏洞复现
漏洞概述
shiro框架可以实现自动登录,当用户选择开启免登录功能时,shiro会自动对用户对象序列化并加密,通过Set-Cookie: rememberMe发送给客户端。
当用户下次访问网站时,如果存在cookie rememberMe,在过滤器中会对该字段的值进行解密,来判断是否是合法免登录用户,服务端处理rememberMe流程:
- 获取rememberMe cookie值
- BASE64解码
- 取前16位作为AES解密的IV
- 取[16:]作为待解密数据
- 通过硬编码密钥kPH+bIxk5D2deZiIxcaaaA==+IV使用AES/CBC/pkcs5解密(>1.4.1版本采用AES/GCM)
- 反序列化解密后数据
因为AES是硬编码,导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞。
影响版本
Apache Shiro <= 1.2.4
漏洞复现
核心类:
RememberMeManager (接口类,定义了处理rememberMe的接口)
AbstractRememberMeManager (实现RememberMeManager接口)
CookieRememberMeManager (AbstractRememberMeManager的子类)
JcaCipherService (数据加解密类)
DefaultSerializer (序列化/反序列化类)
OncePerRequestFilter类的doFilter方法为shiro过滤器

最后会调用AbstractRememberMeManager的getRememberedPrincipals方法来处理rememberMe的值

调用子类CookieRememberMeManager的getRememberedSerializedIdentity方法将rememberMe的值进行BASE64解码

调用convertBytesToPrincipals方法对base64解码后的数据解密、反序列化

在解密流程中调用了JcaCipherService的decrypt方法

入参ciphertext为解码后的数据,key为密钥KEY,硬编码在AbstractRememberMeManager类中

最后调用JcaCipherService的crypt方法完成解密

在convertBytesToPrincipals方法中,解密后调用DefaultSerializer的deserialize方法来反序列化

漏洞修复
升级到最新版本
Apache Shiro 1.2.5版本修复方法就是将默认Key加密改为生成随机的Key加密
https://github.com/apache/shiro/commit/4d5bb000a7f3c02d8960b32e694a565c95976848

漏洞挖掘
特征判断
- 返回包cookie中存在rememberMe=deleteMe
- 返回包cookie中存在rememberMexxxx=deleteMe,相应的请求中的cookie也要设置为rememberMexxxx
利用工具
DNSLOG payload生成
1 |
|