[备份] 浅谈 Shiro CVE-2022-32532

0x00 漏洞介绍

Spring-SecurityCVE-2022-22978 漏洞爆出后,陈师傅我是killer师傅迅速在星球《漏洞百出》给出了实际的案例:在SpringMVC下的利用场景以及拓展思路。当天阅读完发现这并不是Spring Security特有的漏洞,而是一种半通用的思路,连夜分析了Apache ShiroSpring MVC以及其他可能的Java组件,甚至分析了DjangoRuby on Rails等其他语言框架,在凌晨发送了两篇漏洞报告,分别到ShiroSpring的安全团队。对于SpringMVC中的问题我将在后文中解释,他们认为这并不是漏洞,仅是一个issue或者说改进功能

两句话评价CVE-2022-32532漏洞:这是一个鸡肋洞,需要罕见的配置下才可以绕过。假设能够绕过shiro的身份验证,在后端程序中大概率还会有其他的验证(以前的shiro绕过都有类似的问题)

0x01 基本原理

无论是CVE-2022-22978还是CVE-2022-32532本质都是以下的内容

Java中的正则默认情况下.并不包含\r\n字符,因此某些情况下正则规则可以被绕过

虽然说编写正则是开发者的责任,如果是完善的正则表达式则不会出现这类漏洞。但在开发者的意识中:如果配置了/permit/.*路径规则,他的目标应该是拦截所有/permit/下的请求,如果出现了意料之外的问题,可以认为是一种安全风险。从框架角度来说,有必要针对这种问题改善部分代码,目标是在通常的意识中不会出现意外的情况。针对于这种问题的修复其实很简单,加入一个flag即可

0x02 源码分析

简单阅读Shiro源码后发现这样一个类:RegExPatternMatcher

参考上文的原理,一眼即可看出可能存在安全风险

但不能仅因为一个类而确定安全漏洞,至少搭建出一个可用的漏洞环境,才有必要发送漏洞报告

shiro中默认配置的MatcherAntPathMatcher类,用于路径的匹配。而RegExPatternMatcher仅仅是shiro向开发者提供的另一个Matcher实现,在整个shiro项目中都没有出现,需要用户自行配置

img

使用shiro的过程中通常会有以下的配置

其中的map记录了路径匹配的规则,跟入ShiroFilterFactoryBean分析,分析SecurityManager如何处理以上的配置

createFilterChainManager方法处理完配置之后得到FilterChainManager对象。并配置一个Resolver类,该类名称很长,实际上可以理解为一个工具类,负责对路径进行匹配,根据规则处理每一个请求,判断该请求路径是否匹配到规则,将在后文分析。首先来看createFilterChainManager方法

配置中的anon等字符串映射到对应的Filter中,如果我们想要自定义filter首先应该看懂这些默认的filter代码

FormAuthenticationFilter的父类是AuthenticatingFilter类,它的继承实现关系如图

img

在服务端收到请求并传递到ServletController之前首先交给Filter处理

OncePerRequestFilter基类用于防止多次执行Filter并保证一次请求只会走一次拦截器链

AdviceFilter提供了AOP风格的支持,类似于SpringMVC中的Interceptor,其中定义了前置和后置增强处理的方法

PathMatchingFilter基于AOP提供了请求路径匹配功能及拦截器参数解析的功能

AccessControlFilter类是更偏向于上层的类,提供了访问控制的基础功能,比如是否允许访问或当访问拒绝时如何处理等

回到FormAuthenticationFilter类分析

进入AccessControlFilter分析如何进行路径匹配

可以发现分析和处理URL的类是PathMatchingFilter

PathMatchingFilter类中找到了matcher.matches方法调用,并且发现了默认情况下使用了AntPathMatcher类而不是正则的Matcher

其实以上这么多的分析,目的是研究自定义Filter如何使用RegExPatternMatcher

在阅读了一些shiro相关的开源项目后,发现他们总是继承AccessControlFilter做一些自定义。因为该类可以使用父类的pathsMatch方法进行匹配,且该类提供了几个实用的方法,在做web开发中很方便上手:

基于以上的原理,结合真实的场景,会出现以下这样的自定义Filter

虽然ShiroFilterFactoryBean提供了设置自定义Filter的方法,但该方法仅适用于使用Ant类型的Mathcer如果想要使用RegExPatternMatcher还有坑

可能是shiro设计方面的缺陷,在PathMatchingFilterChainResolver的两个构造方法中都使用了AntPathMatcher类,不支持在构造的时候设置Mathcer只提供了setMathcer这样的方法,在ShiroFilterFactoryBean的构造方法中同样不支持自定义Matcher,都默认使用了AntMatcher

为了解决这个坑,自定义MyShiroFilterFactoryBean继承自ShiroFilterFactoryBean类,添加自定义的MyFilter并设置匹配规则为/permit/.*字符串,表示需要拦截/permit/下所有的路径,设置到Filter链管理器DefaultFilterChainManager中。并在最后指定PathMatchingFilterChainResolverpathMatcher属性为RegExPatternMatcher否则会使用默认的Ant类型Matcher

我在github的一些开源shiro程序中看到自定义PathMatchingFilterChainResolver类的例子,也是另一种设置pathMatcher属性的方式

给出一段来自真实开源项目的代码,他自定的Filter继承自AuthorizationFilter类,并且自定义了PathMatchingFilterChainResolver

0x03 漏洞总结

评价该漏洞:比较鸡肋的洞

漏洞的利用条件:目标配置了RegExPatternMatcher情况下且正则规则中包含了“.”则存在漏洞

漏洞的利用场景如下:

0x04 拓展思考

JavaWeb项目中并不完全使用ShiroSpring-Security进行权限管理,在一些老站和入门程序中会使用SpringMVCInterceptor功能

例如这里自定义一个Interceptor继承子HandlerInterceptor类,如果认证失败则不会到达Controller

配置该InterceptorSpringMVC中,设置路径为/permit/.*期望拦截所有/permit/下的请求

定义对应的Controller

我将该问题报告到Spring框架后回复如下

img

从邮件回复中可以看出SpringMVC团队认为不应该用Interceptor来保证安全性,应该交给Spring Security来负责安全

他们不打算发布CVE但认可了该漏洞或者说是错误,并打算在下一次新版本发布中修复和向我致谢