Shiro反序列化加密&解密过程
网络安全测评专家
卓识网安
shiro反序列化的起源是因为shiro在认证时可以携带rememberMe字段(在cookie中携带),rememberMe中存储一些序列化数据。
rememberMe的通过cookie存储在用户本地,当cookie中的SessionID失效时,shiro会在cookie中携带rememberMe进行认证,从而达到无需再次认证的效果。
“
// 环境 //
”
github下载shiro1.2.4
导入maven项目,并修改pom文件,将下图位置版本改为1.2
“
// 请求 //
”
shiro认证的第一个数据包
shiro认证的第二个数据包
“
// 过程分析//
”
加密过程
加密和解密的过程均进过AbstractRememberMeManager类处理
DefaultSecurityManager#rememberMeSeccussfulLogin
当登录时选择rememberMe之后,会进入rememberMeSuccessfulLogin生成响应的rememberMe字段内容
DefaultSecurityManager#rememberMeSuccessfulLogin
跟进onSuccessfulLogin()方法,根据处理方式
AbstractRememberMeManager#onSuccessfulLogin
跟进forgetIdentity()方法,处理请求&响应
CookieRememberMeManager#forgetIdentity
CookieRememberMeManager#forgetIdentity
CookieRememberMeManager#forgetIdentity
在addCookieHeader方法中,将rememberMe=deleteMe字段添加至响应头中。
回到onSuccessfulLogin
如果设置rememberMe则进入rememberIdentity()
AbstractRememberMeManager#onSuccessfulLogin
跟进
AbstractRememberMeManager#rememberIdentity
AbstractRememberMeManager#rememberIdentity
AbstractRememberMeManager#rememberIdentity
先进行序列化,然后加密
AbstractRememberMeManager#serialize
DefaultSerializer#serialize
调用原生序列化方法进行序列化,序列化之后,回到convertPrincipalsToBytes()方法进行加密
AbstractRememberMeManager#convertPrincipalsToBytes
加密方法
AbstractRememberMeManager#encrypt
getCipherService() //获取加密模式
加密算法为AES,模式为CBC,填充为PKCS5Padding
在cipherService.encrypt()方法中,传递了两个参数,getEncryptionCipherKey()是获取秘钥的方法。跟进getEncryptionCipherKey()
成员变量encryptionCipherKey为private。
通过setter方法赋值
利用“Find Uages”向上查找赋值的位置。
查找到AbstractRememberMeManager#setCipherKey
继续“Find Uages”
此时传递进setCipherKey方法的参数为常量
在加密之后回到rememberIdentity方法。
AbstractRememberMeManager#rememberIdentity
回到rememberIdentity之后,继续跟进rememberSerializedIdentity
CookieRememberMeManager#rememberSerializedIdentity
在rememberSerializedIdentity方法中,152行对参数serialized进行base64编码,serialized参数是在执行convertPrincipalsToBytes方法后得到的结果。然后将base64编码后的字符串放入cookie中。
加密的调用过程
1DefaultSecurityManager#rememberMeSuccessfulLogin
2AbstractRememberMeManager#onSuccessfulLogin
3CookieRememberMeManager#forgetIdentity
4SimpleCookie#removeFrom
5addCookieHeader() //以上生成响应rememberMe字段
3AbstractRememberMeManager#rememberIdentity
4AbstractRememberMeManager#rememberIdentity
5AbstractRememberMeManager#convertPrincipalsToBytes
6AbstractRememberMeManager#serialize
7DefaultSerializer#serialize //序列化
6AbstractRememberMeManager#encrypt // AES
5CookieRememberMeManager#rememberSerializedIdentity
6Base64.encodeToString() //base64
6cookie.setValue()
解密过程
刷新页面,拦截请求数据包,删除cookie中的sessionID即可触发解密rememberMe的片段。
AbstractRememberMeManager#getRememberedPrincipals
CookieRememberMeManager#getRememberedSerializedIdentity
参数base64即为cookie中的rememberMe的值

