Shiro权限绕过3
Shiro漏洞复盘系列--1.5.3版本以下的权限绕过复现分析。(CVE-2020-11989)
# 简介
漏洞影响范围:shiro < 1.5.3
利用条件:
- Spring 需要设置 ContextPath
- alwaysUseFullPath 必须设置为 false
# 配置
Spring的版本配置有坑点,主要与的alwaysUseFullPath值有关。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<!-- <version>2.4.3</version>-->
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- shiro dependence -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.2</version>
</dependency>
# 分析
设置 context-path 为 test:

访问/test/admin,被shiro拦截:

访问/;/test/admin,绕过shiro鉴权:

# shiro
依然是在org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain这个方法打下断点,调试shiro来处理URL请求的过程,跟进getPathWithinApplication方法:

通过gerRequestUri方法获得的结果是/:

所以跟进到该方法内部调试,在1.5.2的补丁版本中我们知道URL的获取规则变成了ContextPath、ServletPath、PathInfo三者拼接而成:

问题就处在getContextPath方法中,经过这个方法之后可以获得带;号的ContextPath:

三者拼接之后URL为/;/test//admin,之后传入decodeAndCleanUriString方法中,仅仅保留了;号前面的部分:

那么由shiro处理完成之后的结果就是/,从而绕过了shiro鉴权:

# Spring
Spring 是否调用 getPathWithinServletMapping 方法和 alwaysUseFullPath 的值有关,Spring官方称该值默认为 false,但是我在使用最新版Spring的时候却是默认为 true ,导致漏洞无法复现(待解决),下面两张图是不同版本的Spring的差异。
5.2.5版本的Spring:

5.3.4版本的Spring:

只有当alwaysUseFullPath为false的情况下才会进入getPathWithinServletMapping中,经过getPathWithinServletMapping处理之后可以正确获取到路径:

getPathWithinApplication方法中的处理逻辑在上一篇中已经分析过,这里不再赘述,getServletPath方法获取到的其实是Request对象的某个属性值:

正确获取到路径之后,就可以匹配对应的Controller了。
# 修复
漏洞的成因在于shiro和Spring对于;的处理逻辑不一样:
- shiro会直接截断
;号后面的部分 - Spring会截断
;号和其后第一个/的部分,然后剩余部分作拼接处理
1.5.3版本的shiro修复如下:

shiro使用了标准的getServletPath(request) + getPathInfo(request)来进行URL的处理,同时不再获取ContextPath,之后会进行格式化处理,就无法利用;进行绕过。
- 02
- CommonsBeanUtils04-19
- 03
- 基于Tomcat全局存储进行回显04-16