0x01 写在前面

在 Shiro550 漏洞中,Cookie 所使用的 AES 加密密钥为硬编码,所以我们可以构造恶意序列化数据并使用固定的 AES 密钥进行正确加密恶意序列发送给服务端,进而达到攻击的目的。但在该漏洞公布后,Shiro 官方修复了这一漏洞,将AES密钥修改成了动态生成。也就是说,对于每一个 Cookie,都是使用不同的密钥进行加解密的

0x02 漏洞原理

在Shiro721漏洞中,由于Apache Shiro cookie中通过 AES-128-CBC 模式加密的rememberMe字段存在问题,用户可通过Padding Oracle Attack来构造恶意的rememberMe字段,并重新请求网站,进行反序列化攻击,最终导致任意代码执行

虽然使用Padding Oracle Attack可以绕过密钥直接构造攻击密文,但是在进行攻击之前我们需要获取一个合法用户的Cookie

0x03 环境搭建

web-app没配明白,还是拿的Drunkbaby师傅打包好的环境

https://codeload.github.com/Drun1baby/JavaSecurityLearning/zip/refs/heads/main

有空学学环境搭建,对于后期的学习是很有必要的

0x04 漏洞条件

漏洞影响版本是 1.2.5 <= Apache Shiro <= 1.4.1

Apache Shiro Padding Oracle Attack 的漏洞利用必须满足如下前提条件:

  • 开启 rememberMe 功能
  • rememberMe 值使用 AES-CBC 模式解密
  • 能获取到正常 Cookie,即用户正常登录的 Cookie 值
  • 密文可控

0x05 漏洞分析

密钥生成

具体的分析流程https://goodapple.top/archives/261

在Shiro550中,密钥是硬编码

1
2
3
4
5
public AbstractRememberMeManager() {
this.serializer = new DefaultSerializer<PrincipalCollection>();
this.cipherService = new AesCipherService();
setCipherKey(DEFAULT_CIPHER_KEY_BYTES);
}

而在Shiro721中,密钥的生成方式变为了动态生成

1
2
3
4
5
6
public AbstractRememberMeManager() {
this.serializer = new DefaultSerializer<PrincipalCollection>();
AesCipherService cipherService = new AesCipherService();
this.cipherService = cipherService;
setCipherKey(cipherService.generateNewKey().getEncoded());
}

布尔条件

我们知道,Padding Oracle Attack攻击是一种类似于sql盲注的攻击,这就要求服务器端有能够被我们利用的布尔条件

  • 当收到一个有效的密文(一个被正确填充并包含有效数据的密文)时,应用程序正常响应(200 OK)
  • 当收到无效的密文时(解密时填充错误的密文),应用程序会抛出加密异常(500 内部服务器错误)
  • 当收到一个有效密文(解密时正确填充的密文)但解密为无效值时,应用程序会显示自定义错误消息 (200 OK)

我们可以通过响应头来判断明文填充是否正确,进而爆破出中间值

0x06 漏洞利用

自动化工具:ShiroExploit.V2.51

提供目标url和有效Cookie

img

使用 dnslog.cn 进行漏洞检测爆破该Cookie的密钥

img

后面的流程550一样,拿到密钥就能getShell

参考

https://drun1baby.top/2023/03/08/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96Shiro%E7%AF%8702-Shiro721%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90/

https://goodapple.top/archives/261