芝士土拨鼠
- 关注
最近参加了某攻防活动,也是遇到了很多的shiro反序列化,上手后也是直接拿起工具就用,原理也仅仅是了解,菜鸟对于shiro也是有太多不了解的,接下来就详细分析一下shiro反序列化产生的原理。
shiro分类
在shiro版本小于1.2.5时,被称作shiro-550,shiro反序列化的产生原因主要是因为rememberMe内容,原因是AES密钥被硬编码在shiro源码中,导致在cookie中的rememberMe可以被插入恶意代码造成代码执行。在1.2.5之后,shiro使用了随机密钥,又因为padding oracle attack导致反序列化,被称作shiro-721。
详细分析
一.shiro环境搭建:
1.下载shiro1.2.4:
https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4
2.IDEA打开shiro,修改shiro/samples/web/pom.xml路径下jstl的依赖版本为1.2,没有就自己加一个
3.启动IDEA内置tomcat服务
加密分析
点击log in看到登录界面,开始一步一步分析。在AbstractShiroFilter.class下断点,大概在151行的位置,登录时会断在这里,
在第157行会创建subject,使用cookie,后续再分析。
步入executeChain
可以跟着来到AuthenticatingFilter.class,这里是在进行处理登录
再往下看,登录成功后触发this.onLoginSuccess
一直来到DefaultSecuirtyManager.class,找到rememberMeSuccessfulLogin函数
看到RememberMeManager不为空后,继续走到达AbstractRememberMeManager.java
跟进forgetIdentity,来到CookieRememberMeManager.class
继续步入this.forgetIdentity,再单步步入this.getCookie().removeFrom(request, response)
可以看到rememberMe和deleteMe字段,并且通过addCookieHeader写入cookie中,返回AbstractRememberMeManager.class,this.isRememberMe(token)检查是否选中登陆时Remember Me选项,接着单步步入rememberIdentity
convertPrincipalsToBytes是转化成bytes,就在这里还进行了serialize序列化,然后判断不为空后进入this.encrypt,单步步入encrypt函数,密码服务为AES/CBC/PKCS5Padding
接着进入this.getEncryptionCipherKey(),单步步入,发现CipherKey就是AbstractRememberMeManager.class开头的DEFAULT_CIPHER_KEY_BYTES=”kPH+bIxk5D2deZiIxcaaaA==”
获取了CipherKey返回后进入cipherService.encrypt函数中,生成初始化向量ivBytes后,进入具体的加密函数,最后return。
一步步return bytes后,回到rememberIdentity函数,下面的rememberSerializedIdentity实现了记住序列化身份的功能,跟进
在这里进行base64后,将信息加入到cookie中
然后一直返回,到AuthenticatingFilter#executeLogin处理登录,返回成功登陆
解密分析
在AbstractShiroFilter.class#doFilterInternal下断点,单步到DefaultSecurityManager#createSubject
进入resolvePrincipals,单步到getRememberedIdentity,RememberMeManager获取后进入rmm.getRememberedPrincipals(subjectContext)
第一个函数getRememberedSerializedIdentity,可以看到先获取cookie中的值,然后base64解密,生成二进制数后返回
第二个函数convertBytesToPrincipals,先获取解密服务,解密服务不为空后,将二进制数据传入decrypt函数进行解密,之后return this.deserialize(bytes)
在deserialize(bytes)中有readObject(),触发apache.commons利用链漏洞
结论
整个过程就是
• 读取cookie中rememberMe值
• base64解码
• AES解密
• 反序列化
只要获取到密钥,就可以进行反序列化操作,在1.2.5之后,shiro采取了随机密钥,虽然阻止了shiro550的利用方式。但由于padding oracle attack也导致了反序列化。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)