shiro<1.2.4反序列化分析
0x01、环境搭建
下载地址:https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4
环境:Tomcat 8.5.27 + idea 2020.2 + jdk 1.8 +maven 3.6
下载之后之后直接打开,并open这个web文件夹即可,其他自行百度就行,其中还需要导入一些jstl的jar等等
0x02、漏洞原理
shiro默认使用了CookieRememberMeManager
,其处理cookie的流程是:
得到rememberMe的cookie值 --> Base64解码 --> AES解密 --> 反序列化
然而AES的密钥是硬编码的,就导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞。
payload 构造的顺序则就是相对的反着来:
恶意命令-->序列化-->AES加密-->base64编码-->发送cookie
在整个漏洞利用过程中,比较重要的是AES加密的密钥,该秘钥默认是默认硬编码的,所以如果没有修改默认的密钥,就自己可以生成恶意构造的cookie了。
shiro特征:
- 未登陆的情况下,请求包的cookie中没有rememberMe字段,返回包set-Cookie里也没有deleteMe字段
- 登陆失败的话,不管勾选RememberMe字段没有,返回包都会有rememberMe=deleteMe字段
- 不勾选RememberMe字段,登陆成功的话,返回包set-Cookie会有rememberMe=deleteMe字段。但是之后的所有请求中Cookie都不会有rememberMe字段
- 勾选RememberMe字段,登陆成功的话,返回包set-Cookie会有rememberMe=deleteMe字段,还会有rememberMe字段,之后的所有请求中Cookie都会有rememberMe字段
0x03、漏洞复现
复现文章https://blog.csdn.net/weixin_43571641/article/details/108182722
0x04、漏洞分析
简单介绍利用:
- 通过在cookie的rememberMe字段中插入恶意payload,
- 触发shiro框架的rememberMe的反序列化功能,导致任意代码执行。
- shiro 1.2.24中,提供了硬编码的AES密钥:kPH+bIxk5D2deZiIxcaaaA==
- 由于开发人员未修改AES密钥而直接使用Shiro框架,导致了该问题
4.1、加密
那既然我们要分析,那入口点在哪呢?Shiro≤1.2.4版本默认使用CookieRememberMeManager
而我们看看这边CookieRememberMeManager
类继承了AbstractRememberMeManager
,我们进去看看是什么梗
我们可以看到这边这个类里面有硬编码。然后它又继承了RememberMeManager
接口;我们继续进去看看是怎么回事
看名字的话可以知道这些是登陆成功,登陆失败,退出的一些service;既然如此,肯定会调用这个登陆成功的接口,然后再去实现这个接口。所以我们直接在这个接口下个断点,看看是怎么个流程;
这里看到调用了isRememberMe()
可以发现这个就是一个判断用户是否选择了RememberMe
选项。而我们是勾选了的
所以我们我们条件满足,这边判断返回True,我们则进入this.rememberIdentity(subject, token, info);
subject
存储的一些登陆信息如session等等,而authcInfo
存储的则是用户名;
而PrincipalCollection是一个身份集合,因为我们可以在Shiro中同时配置多个Realm,所以呢身份信息可能就有多个;因此其提供了PrincipalCollection用于聚合这些身份信息,具体我们不细讲,不深入去懂原理。
然后我们再F7继续跟进this.rememberIdentity(subject, principals);
这我们有点懵,将身份信息干嘛?我们进入该convertPrincipalsToBytes()
方法查看;
看到了serialize()
方法,难道这边开始是进行序列化了还是啥?
通过此处我们可以知道是跳了两层,到DefaultSerializer
类的serialize
方法;看到这里就懂了,这里先转为byte,写入缓冲区;然后进行了一个序列化,最后通过toByteArray()
方法返回序列化后的Byte数组。
然后返回到原来的地方convertPrincipalsToBytes()
内,接下来if判断getCipherService()
方法不为空,则进入条件里面里面。我们f7进去内部看看;
发现又是一个cipherService
,这是什么;我们翻译一下,因为大部分开发都会用简称;
也就是获取密码服务?? 什么密码服务?我们再继续F7跟进发现直接推出了。那我们就 Ctrl+左键
继续进去看。可以,发现是new了一个aes加密服务。
那我们点击debugger处,回到刚刚那个地方;我们就不用继续进入了,我们就思考一下,这边是要获取到加密服务,如果没获取到,则不进入。获取到的话,则进入该条件;
直接F8下来,进入,然后我们再手动添加变量监视。可以发现正如我们所想的,获取aes加密服务;
然后调用encrypt()
方法,而懂点英文的,都知道这个单词是加密的意思。那我们初步判断这是个加密方法。我们f7跟进去看看什么情况。
我们可以知道这个参数是byte[] serialized
,也就是说,此处加密我们刚刚的序列化流的数据。
然后这边this.getCipherService()
我们刚刚手动添加变量查看了,这边是获取到了aes加密服务;然后判断不问空,那肯定不为空啊,刚刚上面分析过了。然后我们进入条件判断股内部。
ByteSource byteSource = cipherService.encrypt(serialized, this.getEncryptionCipherKey());
这里调用cipherService.encrypt()
方法并且传入序列化数据,和getEncryptionCipherKey
方法。加密过程,我们就应该不怎么感兴趣了;有兴趣的可以自己研究
我们通过getEncryptionCipherKey()
名字可以知道是获取key的一个方法。那我们f7进入看看
哦豁,那我们再进一层看一下;发现直接就返回了,emmmmm....怎么跟别人不一样。那我们就不追了
第一步有说到,硬编码存储在这个地方,而构造方法就在这下面,可以看到这边设置了key。
我们继续回到原来的地方,知道这边是获取加密的key就ok了。然后这边使用平台的默认字符集将字符串编码为 byte 序列,并将结果存储到一个新的 byte 数组中。那我们加密部分就结束了
4.2、解密
由于此处,我找不到,回溯不到,那咋办,烦恼;最后想到了我们加密的入口~~
既然自动跳到了这里,那么我们就直接在此处下个断点,重新开始
随后我们进入这个getRememberedSerializedIdentity()
方法,看看是什么东西。此处我们依然还很懵,没事;
一直f8,期间倒是没有什么有意思或者重点的地方;
直到我们走到这里,这个有一个this.getCookie().readValue(request, response)
,这是要读取cookice中的数据了,这必须跟入了;
这里给进到了这个readvalue()
方法中了,我们先看看什么情况。根据名字可以知道是读取值的一个方法。读取什么值?请求包的值。
通过getName()
方法得到了key为remeberMe。然后把value置空,再通过getCookie
获取到cookie。最后判断cookie不为空,则进入内部;随后获取到cookie的值;值则为序列化内容。然后再 return回序列化内容;
随后返回到上一处地方现在remeberMe
的值不是delete
;而是序列化内容,所以进入到第二个条件分支。
一直到这一步,进行base64解码,成为二进制数据,给了decoded的byte数组;
得到rememberMe的cookie值 --> Base64解码 --> AES解密 --> 反序列化
目前只进行了Base64解码,那还需要aes解码。我们继续跟进
返回到了上层,此处我们知道bytes是二进制数据,我们看看条件判断。当bytes数组不为空且长度大于0时,进入里面。那我们肯定满足,所以我们两步f8加一步F7进入到 convertBytesToPrincipals
看看是什么
可以看出我们接下来的步骤要依依实现了。判断key不为空,然后进入内部
而从这里开始,就是进行aes解密的步骤了,我们F7跟进方法查看
这里重新把恶意的bytes数组重新赋值给serialized
,然后再获取加密服务:AES/CBC/PKCS5Padding
同时到达了下一步;真真正正的开始解密了,其中两个参数,第一个是加密的bytes数组,第二个是获取到key,也就是硬编码;我们 就直接进入decrypt()
方法中
解密过程的话,我不擅长密码学,这种看着我头晕,涉及到aes啥的加密解密我就会跳过。所以依旧一样,跳!!!
此处继续返回到了上一层,我们可以看出这个byteSource是aes解密出来的序列化流,然后再默认字符集将字符串编码为 byte 序列,并将结果存储到一个新的 byte 数组serialized
中,那接下来我们就差反序列化了
得到rememberMe的cookie值 --> Base64解码 --> AES解密 --> 反序列化
我们继续return,返回到上一层
顾名思义,一看名字就知道是反序列化的方法,我们跟进deserialize()
方法查看
看到还有一层,我们继续F7跟进
形成反序列化漏洞的话,没有readObject()
怎么可能呢?所以我们看到了最后一道光,就这么愉快的结束了。
0x05、总结
其实这个还是得学习学习加密解密的方法,才能进行编写poc,但是此处只是了解个思路。具体可参考其他文章;我空余时间的话,会继续补全该篇文章,先去搞其他的玩意儿
[P牛博客](https://zeo.cool/2020/09/03/Shiro 550 反序列化漏洞 详细分析+poc编写/#解密过程:)
https://www.anquanke.com/post/id/225442#h2-7
https://mp.weixin.qq.com/s/ayZKDVnN7zEbKjo5w8uqxQ
shiro<1.2.4反序列化分析的更多相关文章
- (一)Shiro笔记——简介、 架构分析
1. Shiro是什么 Apache Shiro是一个强大灵活的开源安全框架,可以完全处理身份验证,授权,企业会话管理和加密. Apache Shiro的首要目标是易于使用和理解. 安全有时可能非常复 ...
- Spring整合Shiro 权限 角色 用户关系分析
Spring整合Shiro 权限 角色 用户关系分析 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 前置内容 之前我们学习了,使用注解的方式去完成权限的控制,当然,也是静态的,也就 ...
- Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)复现
Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)复现 环境搭建 docker pull medicean/vulapps:s_shiro_1 docker run -d ...
- fastjson及其反序列化分析--TemplatesImpl
fastjson及其反序列化分析 源码取自 https://www.github.com/ZH3FENG/PoCs-fastjson1241 参考 (23条消息) Json详解以及fastjson使用 ...
- [JavaWeb]反序列化分析(二)--CommonCollections1
反序列化分析(二)--CommonCollections1 链子分析 首先新建一个TransformedMap,其中二三参数为可控,后续要用到 当TransformedMap执行put方法时,会分别执 ...
- Java安全之SnakeYaml反序列化分析
Java安全之SnakeYaml反序列化分析 目录 Java安全之SnakeYaml反序列化分析 写在前面 SnakeYaml简介 SnakeYaml序列化与反序列化 常用方法 序列化 反序列化 Sn ...
- shiro550反序列化分析
拖了很久的shiro分析 漏洞概述 Apache Shiro <= 1.2.4 版本中,加密的用户信息序列化后存储在Cookie的rememberMe字段中,攻击者可以使用Shiro的AES加密 ...
- weblogic之CVE-2016-0638反序列化分析
此漏洞是基于CVE-2015-4852漏洞进行黑名单的绕过,CVE-2015-4852补丁主要应用在三个位置上 weblogic.rjvm.InboundMsgAbbrev.class :: Serv ...
- Apache Shiro<=1.2.4反序列化RCE漏洞
介绍:Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 漏洞原因:因为shiro对cookie里的rememberme字段进行了反序列化,所以如果知道了 ...
随机推荐
- Vue案例之todoLIst实现
使用Vue实现todolist案例,如有不对敬请大佬多多指教 功能: 1.增加功能:在新增版块里面的输入框内输入数据,点击后面的"添加"按钮,将输入的数据添加到列表中,默认是未完成 ...
- 【原创】Linux虚拟化KVM-Qemu分析(八)之virtio初探
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...
- IE浏览器兼容问题总结
IE浏览器兼容问题总结 引自掘金:https://juejin.cn/post/6844903825854185480 一.标准盒模型和怪异盒模型 浏览器的盒子模型分为两类: 标准的W3C盒子模型. ...
- secrets 管理工具 Vault 的介绍、安装及使用
原文:https://ryan4yin.space/posts/expirence-of-vault/ Vault 是 hashicorp 推出的 secrets 管理.加密即服务与权限管理工具.它的 ...
- 1、剑指offer-数组——二维数组中的查找
*题目描述* **在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含 ...
- 手淘架构组最新实践 | iOS基于静态库插桩的⼆进制重排启动优化 抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15% 编译期插桩
抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15% 原创 Leo 字节跳动技术团队 2019-08-09 https://mp.weixin.qq.com/s/Drmmx5JtjG ...
- Redis主从、哨兵模式的搭建
壹.Redis主从分离 准备三个redis配置文件(redis.conf),分别修改为redis6380.conf.redis6381.conf.redis6382.conf 一.配置Master 1 ...
- 类型检查 Type Checking 一些编程语言并不安全 类型化语言的优点 定型环境 (符号表) 断言的种类
Compiler http://staff.ustc.edu.cn/~bjhua/courses/compiler/2014/ http://staff.ustc.edu.cn/~bjhua/cour ...
- 消息中间件——rocketmq环境配置
产生原因 RocketMQ概述 RocketMQ 是一款分布式.队列模型的消息中间件,具有以下特点: 能够保证严格的消息顺序 提供丰富的消息拉取模式 高效的订阅者水平扩展能力 实时的消息订阅机制 亿级 ...
- Urlrewrite
Urlrewrite 地址重写,用户得到的全部都是经过处理后的URL地址 过滤用户的所有请求,符合规则的便对其进行重定向 rule结点中from默认使用的正则表达式来匹配,若用户访问服务器时的URL ...