Shiro身份验证绕过(CVE-2022-40664)
1、漏洞介绍
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。该组件于2022年10月13日Shiro官方发布1.10.0版本,最新版本之前存在身份验证绕过漏洞,编号CVE-2022-40664。
2、漏洞逆向审计
通过分析Github上的shiro官方仓库中的commit,来查看1.10.0版本与上一版本的代码变更情况。commit传送门:GitHub-Commit-Shiro
由于版本变更的代码较多,我们进行逐一的分析。
可以看以下为第一个业务逻辑更改,通过下图可以看出在调用GuiceShiroFilter方法时参数多加了一个ShiroFilterConfiguration对象,可以继续看commit中其他的类更改,均为增加了ShiroFilterConfiguration类对象。现在就明确追踪目标,向下追踪ShiroFilterConfiguration类对象的定义。
追踪到ShiroFilterConfiguration类,发现此类是1.10.0版本新增的代码,创建了isFilterOncePerRequest等方法,我们对注解进行翻译,内容如下:
*设置过滤器是每次请求执行一次,还是每次调用过滤器时执行一次。建议使用
*如果您正在使用{@link javax.servlet.RequestDispatcher RequestDisputcher}转发,请保持禁用状态
*或包含请求(JSP标记、编程方式或通过框架)。
*@param filterOncePerRequest此筛选器是否每个请求执行一次。
通过注解可以看出此次更新为禁用javax.servlet.RequestDispatcher RequestDisputcher(Java请求转发功能),可以看出此漏洞为Java请求转发绕过Shiro的过滤器从而达到身份绕过!
我们创建两个本地项目,并分别导入shiro1.7.0和shiro1.10.0,追一下代码区别。
可以看出在过滤器处,1.10.0多了个条件校验位filterOncePerRequest,追踪此参数。
此参数即为禁用javax.servlet.RequestDispatcher请求转发方法,这也证实了我们之前的猜测。
3、RequestDispatcher介绍
定义一个对象,从客户端接收请求并将其发送到服务器上的任何资源(例如servlet,HTML文件或JSP文件)。servlet容器创建RequestDispatcher对象,该对象用作位于特定路径或特定名称的服务器资源的包装。此接口旨在包装servlet,但servlet容器可以创建RequestDispatcher对象以包装任何类型的资源*。*
RequestDispatcher定义了两个方法分别为forward和include。
我们去追踪这两个方法,通过查看代码逻辑发现即使是shiro1.10.0在spring项目中也是默认不拦截forward和include方法的,在新版本中新增加了ShiroFilterConfiguration类,可以通过这个类来设置外部的过滤器来禁用forward和include方法。
4、漏洞复现
创建个Springboot项目并引入shiro1.7.0依赖,设计controller接口,一个为利用forward进行请求转发至另一个接口,而另一个接口为正常的身份验证接口,存在shiroFilter进行过滤,但这里只是利用shiro默认的设置,不对RequestDispatcher进行限制。
在外部过滤器中配置加白所有请求转发函数,保证我们接口中的forward可以正常转发。
下面我们请求第二个存在身份验证的接口,发现返回身份验证失败。
直接请求第一个接口发现可以直接绕过身份验证。
5、修复建议
升级shiro版本至1.10.0,且设计外部过滤器时,禁用所有请求转发的方法,示例代码如下: