Shiro 权限绕过
2023-11-17 17:04:06

CVE-2023-22602

漏洞复现

参考链接:

https://forum.butian.net/share/2118

环境下载地址:

https://github.com/apache/shiro/tree/shiro-root-1.10.1

WebApp 里面添加上:

1
2
chainDefinition.addPathDefinition("/admin/**", "roles[admin]");
chainDefinition.addPathDefinition("/guest/**", "roles[guest]");

然后把 AccountInfoController 的 RequestMapping 改了

1
@RequestMapping("/admin/**")

启动以后发现 /admin/ab 会跳转到登陆界面,但是 /admin/.. 能直接进方法内。

漏洞分析

首先是访问正常的 /admin/abc 会在哪里判断权限不够呢,入口在这里:

1
2
3
org.apache.shiro.web.servlet.AbstractShiroFilter#doFilterInternal
-> org.apache.shiro.web.servlet.AbstractShiroFilter#getExecutionChain
-> org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain

这里面会调用到 executeChain ,然后又动态的给原 chain 做了个类似代理的操作(也可以理解为往中间添加了几个 Filter)。

那么他是怎么加的呢?

关键点在这(这个):

1
org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain

image-20231117172427740

可以看到首先是获取 requestURI,然后和 shiro 里的规则做匹配,匹配成功就要多走一个过滤器。

当传入 /admin/abcrequestURI自然是 /admin/abc,但是当传入 /admin/.. 时就不一样了:

image-20231117172817990

一直深入能到这里:

1
org.apache.shiro.web.util.WebUtils#getServletPath

(这里为了测试我把路由改成了 /test1/test2/.. ,鉴权改成 /test1/test2 需要权限)

image-20231117175503994

再进去就是 tomcat 的了,反正就是会把 ServletPath../ 去掉。

这肯定就匹配不上需要鉴权的路由了

那么为什么 Spring 可以匹配上呢?

找到 Spring 匹配路由的位置:

1
2
3
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal
-> initLookupPath
-> org.springframework.web.util.ServletRequestPathUtils#getParsedRequestPath

image-20231117180638626

为了一探究竟,看看这个 attribute 怎么来的:

1
org.springframework.web.util.ServletRequestPathUtils.ServletRequestPath#parse

image-20231117180827146

这就很简单了,说白了就是,Shiro 用的 getServletPath ,Spring 用的 getRequestURI 产生的差异。

修复方法

这里下载 1.13 的版本:

https://github.com/apache/shiro/tree/shiro-root-1.13.0-vote-1

上面有一个函数提到了但是没截图:

1
org.springframework.web.servlet.handler.AbstractHandlerMapping#initLookupPath

image-20231117182721649

在低版本的话,这里 if 是会直接进去的,但是高版本进入了 else 块。

函数里面判断的是这个属性是否为空:

1
org.springframework.web.servlet.handler.AbstractHandlerMapping#patternParser

如果这个属性不为空就进入 IF,而这个属性默认情况下是设置的。

但是为什么新版本不设置了呢,一直回溯就能到:

1
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#configurePathMatch

image-20231117183609484

这里判断如果值是 PATH_PATTERN_PARSER 就会 set 进去。

只不过新版的 Shiro 做了一些配置:

1
org.apache.shiro.spring.config.web.autoconfigure.ShiroEnvironmentPostProcessor

image-20231117183725643

image-20231117183920651

CVE-2022-32532

可以直接用这个:

https://github.com/Lay0us1/CVE-2022-32532/tree/master

漏洞复现

其实感觉很简单,首先是需要从路由匹配相应的 Filter

在这:

1
org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain

image-20231120102213021

由于 . 本身是不匹配换行的,就可以绕过了。

修复方法

那么新版是怎么修复的呢?

image-20231120102630722

可以看到虽然代码一点没变,但是能匹配成功了,这是因为在里面一点:

1
org.apache.shiro.util.RegExPatternMatcher#matches

image-20231120102757708

只要第二个参数大于 32 就可以返回 true

image-20231120103420401

Prev
2023-11-17 17:04:06
Next