Shiro权限绕过2
Shiro漏洞复盘系列--1.5.2版本以下的权限绕过复现分析。(CVE-2020-1957)
# 简介
漏洞影响范围:shiro < 1.5.2
# 配置
<!-- shiro dependence -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>
shiro config同上一篇文章。
# 分析
访问/admin/,已经无法绕过shiro过滤器的拦截:

访问/;/admin,成功绕过shiro拦截:

# shiro
还是在org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain,打下断点,发送请求:

主要在getPathWithApplication方法里:

这里会获取到请求的contextPath和requestUri,获取到uri为/;/admin之后进入decodeAndCleanUriString方法中:

decodeAndCleanUriString方法中把请求的uri按分号进行截断:

/;/admin经过shiro的处理之后,我们请求的路由就变成了/,由于/路由下没有设置过滤器,所以就shiro的过滤器无法匹配,绕过了shiro的权限认证。
# Spring
依然在org.springframework.web.util.UrlPathHelper#getLookupPathForRequest方法中打下断点,发送请求开始调试:

这次主要跟入getPathWithinApplication方法:

再跟入getRequestUri方法:

主要看decodeAndCleanUriString方法,这个方法中对请求的路由做了一些处理:

跟入第一个方法removeSemicolonContent,经过这部分代码处理之后/;/admin变成了//admin,在这个方法中,会把;到后面第一个/之间的字符串全部去掉(包括;),比如/;xxx/经过处理之后就变成了//:

再跟入第三个方法getSanitizedPath,在获取到//的索引值之后,直接删除该索引上对应的字符,//admin也就变了/admin:

最后也就返回了/admin的路由,之后就是正常匹配 hanlderMethod 的过程了,不再赘述:

# 修复
1.5.2版本的org.aoache.shiro.web.util.WebUtils#getRequestUri方法如下:
public static String getRequestUri(HttpServletRequest request) {
String uri = (String)request.getAttribute("javax.servlet.include.request_uri");
if (uri == null) {
uri = valueOrEmpty(request.getContextPath()) + "/" + valueOrEmpty(request.getServletPath()) + valueOrEmpty(request.getPathInfo());
}
return normalize(decodeAndCleanUriString(request, uri));
}
uri获取的规则变成了ContextPath 、ServletPath、PathInfo三者拼接而成:

getServletPath方法可以正确处理分号,再经过后续方法处理,/;/admin就被正常处理为了/admin,之后就会被shiro的过滤器正常拦截。
- 02
- CommonsBeanUtils04-19
- 03
- 基于Tomcat全局存储进行回显04-16