Shiro系列漏洞分析

Shiro简介

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

1
2
3
4
5
6
7
8
9
10
11
12
13
验证用户身份

用户访问权限控制,比如:1、判断用户是否分配了一定的安全角色。2、判断用户是否被授予完成某个操作的权限

在非 Web 或 EJB 容器的环境下可以任意使用Session API

可以响应认证、访问控制,或者 Session 生命周期中发生的事件

可将一个或以上用户安全数据源数据组合成一个复合的用户 “view”(视图)

支持单点登录(SSO)功能

支持提供“Remember Me”服务,获取用户关联信息而无需登录

只要rememberMe的AES加密密钥泄露,无论shiro是什么版本都会造成反序列化漏洞。

Shiro漏洞原理

Apache Shiro框架提供了记住我的功能(rememberMe),用户登录成功后会先对cookie值序列化后经过aes加密再base64编码后生成新的cookie值,而服务端在接收到cookie值后,经过base64解码–>aes解密–>反序列化–>原始cookie值。因此,攻击者只要找到aes的key,就可以构造一个恶意的对象,将其序列化–>aes加密–>base64编码–>cookie,再将生成的cookie作为rememberMe的字段发送给服务端,服务端解密后造成反序列化漏洞,

Shiro利用条件

由于使用了aes加密,那么漏洞利用的关键点在于获取aes加密的密钥,而在shiro1.2.4之前的版本中,使用的是硬编码,aes加密的密钥被写死在代码中,其默认base64编码后的值为 kPH+bIxk5D2deZiIxcaaaA==(或爆破密钥),因此可以直接利用进行序列化,再aes加密,再编码发送给服务端,造成漏洞。
目前已经更新了很多版本,但是官方并没有把反序列化漏洞本身解决,而是通过去掉硬编码的密钥,使其每次生成一个密钥来解决该漏洞。但是,目前一些开源系统、教程范例代码都使用固定的编码,也有很多开源项目内部集成了shiro并二次开发,可能会重现低版本shiro的默认固定密钥的风险。例如Guns开源框架内部集成了shiro并进行二次开发,作者自定义密钥并固定,此时用户如果不对密钥进行修改,即使升级shiro版本,也依旧存在固定密钥的风险。这里可以通过搜索引擎和github来收集密钥,提高漏洞检测和利用的成功率。

Shiro框架指纹识别

在请求包中的cookie字段设置rememberMe=1,返回包中Set-Cookie中存在rememberMe=deleteMe
url中存在shiro字样

漏洞复现

Shiro1.2.4 (CVE-2016-4437) shiro550

漏洞描述

Apache Shiro是一款开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用,同时也能提供健壮的安全性。
Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为rememberMe的Cookie中。攻击者可以使用Shiro的默认密钥伪造用户Cookie,触发Java反序列化漏洞,进而在目标机器上执行任意命令。

漏洞分析

Apache Shiro默认使用了CookieRememberMeManager,其处理cookie的流程是:服务端得到rememberMe的cookie值->Base64解码->AES解密->反序列化。然而在shiro1.2.4及之前的版本中AES的密钥是硬编码,直接固定在代码中,每次处理时都保持不变,因此,攻击者可以获取AES的key伪造恶意数据造成反序列化的漏洞。

复现

在登录窗口出点击登录抓包:

image-20221119153916916

有时需要在请求的cookie中添加rememberMe=1,在请求包中Set-Cookie发现rememberMe=deleteMe,基本可以确定使用的Shiro框架。
确定之后直接使用工具打:

image-20221119153950152

或者使用ysoserial工具生成.ser文件,再利用获取的keyAES加密构造的恶意反序列化数据,将其作为cookie发送给服务端。
java -jar ysoserial.jar CommonsBeanutils1 “touch /tmp/success” > poc.ser

漏洞详细分析:https://xz.aliyun.com/t/11633#toc-22

CVE-2020-1957(Shiro-682)权限绕过

漏洞描述

shiro是做身份认证和权限管理的一款apache框架,可以和spring一起使用。这次的权限绕过漏洞就出在shiro和spring boot搭配这里(对uri的处理方式不同)。
shiro框架通过拦截器来实现对用户访问权限的控制和拦截。Shiro常见的拦截器有anon,authc等。

  1. anon:匿名拦截器,不需登录就能访问,一般用于静态资源,或者移动端接口。
  2. authc:登录拦截器,需要登录认证才能访问的资源。

我们通过在配置文件中配置需要登录才可访问的url,实现对url的访问控制。其中,url的路径表达式为Ant格式。

漏洞分析

authc拦截器对访问“/admin/**”进行认证
URL中权限配置如下:

1
2
3
4
5
6
7
8
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
chainDefinition.addPathDefinition("/login.html", "authc"); // need to accept POSTs from the login form
chainDefinition.addPathDefinition("/logout", "logout");
chainDefinition.addPathDefinition("/admin/**", "authc");
return chainDefinition;
}

在shiro版本<1.5.0 中,利用spring和shiro对requestURI的处理不同,在spring中,/xxx/admin和/xxx/admin/都会被处理为/xxx/admin以访问相应的资源,而在shiro中,/xxx/admin和/xxx/admin/会被认为是两个不同的路径,因此,在Spring集成shiro时,在访问路径后添加 / 就有可能绕过权限认证。
在shiro1.5.0中已经修复了shiro对requestURI的请求方式的差异化,在Apache Shiro 1.5.2的版本中,在使用Spring动态控制器时,攻击者通过构造 /xxx/**..;/ **这样的跳转,可以绕过Shiro中对目录的权限限制。

绕过分析

当输入url为 /xxx/..;/admin/时:
首先进入shiro中,如果uri中有分号;,则返回分号前部分,否则返回整个uri,这里return “/xxx/..” ,随后进入权限认证,由于 /xxx/.. 无法与定义的权限认证配置相匹配,所以返回False,从而绕过认证(authc);
uri进入Spring中,传进来的参数uri为/xxx/..;/admin/,经过removeSemicolonContent(uri)后移除/与/之间分号及分号后面的内容,经过decodeRequestString(request, uri)后对uri进行解码;经过getSanitizedPath(uri)后将路径中//替换为/。此时返回的uri值为/xxx/../admin/ ,而 ../实际表示返回上一级,所以前面添加/xxx/的作用就是为了过渡 ../ ,因此实际路径为 /admin/ ,绕过验证。

复现

首先判断是否使用Shiro框架,与之前判断方法一致
直接访问 /admin/会跳转到登录页面(已经修复,适用于1.5.0之前版本):

image-20221119154044529

image-20221119154110449

构造 /xxx/..;/admin/ 绕过:

image-20221119154138718

成功访问:

image-20221119154202039

漏洞详细分析:https://xz.aliyun.com/t/11633#toc-22