Shiro-550反序列化漏洞分析
加密过程
org.apache.shiro.mgt.AbstractRememberMeManager
首先找到硬编码key的位置
1 |
|
登陆,记得勾选Remember Me
org.apache.shiro.mgt.AbstractRememberMeManager#onSuccessfulLogin
remeberMe为true,接下来进入remeberIdentity
org.apache.shiro.mgt.AbstractRememberMeManager#rememberIdentity
进入rememberIdentity
org.apache.shiro.mgt.AbstractRememberMeManager#rememberIdentity
第一个函数convertPrincipalsToBytes
中先序列化用户名,然后用硬编码的key进行了aes加密
org.apache.shiro.mgt.AbstractRememberMeManager#convertPrincipalsToBytes
先进行序列化操作,再调用encrypt
进行加密
org.apache.shiro.mgt.AbstractRememberMeManager#encrypt
这里可知加密方法为AES/CBC/PKCS5Padding
,通过getEncryptionCipherkey
获取密钥
ciphrtService
key的来源
org.apache.shiro.mgt.AbstractRememberMeManager#getEncryptionCipherKey
很明显这个函数就是用来获取key的,可以看到key的来源是encryptionCipherKey
在构造函数中,把硬编码keyDEFAULT_CIPHER_KEY_BYTES
作为参数传入setCipherKey
,再经过setEncryptionCipherKey
函数赋值给encryptionCipherKey
,这样key就是已知的了。
1 |
|
1 |
|
1 |
|
继续加密
进入加密函数,两个参数分别是序列化后的root,和硬编码key
org.apache.shiro.mgt.AbstractRememberMeManager#rememberIdentity
回到rememberIdentity
方法,convertPrincipalsToBytes
方法执行完后返回了AES加密后的二进制字节流,接下来进入rememberSerializedIdentity
org.apache.shiro.mgt.CookieRememberMeManager#rememberSerializedIdentity
这里的逻辑就很清楚了,把刚刚加密过的数据进行base64编码后再存入cookie
总结
主要逻辑就是用序列化->AES->base64的方式处理cookie
1 |
|
解密过程
根据加密过程可以知道,解密过程一定经过了base64解码、AES解密、反序列化这几个步骤,接下来详细分析这几个步骤的执行过程,并找到反序列化点
1 |
|
org.apache.shiro.mgt.AbstractRememberMeManager#decrypt
在decrypt
方法这里下一个断点
调用栈
org.apache.shiro.mgt.DefaultSecurityManager#resolvePrincipals
作用是调用getRememberedIdentity
org.apache.shiro.mgt.DefaultSecurityManager#getRememberedIdentity
作用是调用getRememberedPrincipals
org.apache.shiro.mgt.AbstractRememberMeManager#getRememberedPrincipals
分别调用了getRememberedSerializedIdentity
和convertBytesToPrincipals
,前者对cookie进行base64解码,后者进行AES解密和反序列化。
base64解码
org.apache.shiro.web.mgt.CookieRememberMeManager#getRememberedSerializedIdentity
这里出现了读取cookie的操作
1 |
|
org.apache.shiro.web.servlet.SimpleCookie.readValue
getName()返回rememberMe
,最终返回cookie中remeberMe的值
org.apache.shiro.mgt.AbstractRememberMeManager#convertBytesToPrincipals
调用decrypt
和deserialize
,进行AES解密和反序列化操作
AES解密
org.apache.shiro.mgt.AbstractRememberMeManager#decrypt
进行解密,getCipherService()
获取加密方法AES/CBC/PKCS5Padding
org.apache.shiro.cryoti.JcaCipherService#decrypt
继续进入decrypt
org.apache.shiro.cryoti.JcaCipherService#decrypt
接下来进入crypt
org.apache.shiro.cryoti.JcaCipherService#crypt
到这里已经基本完成解密,接下来就是反序列化操作了
反序列化
org.apache.shiro.mgt.AbstractRememberMeManager#convertBytesToPrincipals
回到上面的convertBytesToPrincipals
,继续进入deserialize
进行反序列化
org.apache.shiro.mgt.AbstractRememberMeManager#deserialize
调用deserialize
org.apache.shiro.io.DefaultSerializer#deserialize
出现readObject,将输入参数进行反序列化
总结
cookie base64解码 AES解密 反序列化
主要执行流程
1 |
|
漏洞利用
参考链接里的exp,Demo选择的Gadget是CommonsCollections2
1 |
|
弹出计算器
参考链接
http://www.lmxspace.com/2019/10/17/Shiro-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E8%AE%B0%E5%BD%95/
https://blog.csdn.net/god_zzZ/article/details/108391075
https://www.anquanke.com/post/id/225442#h3-6
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!