Shiro权限绕过1
Shiro漏洞复盘系列--1.5.0版本以下的权限绕过复现分析。(无CVE编号)
# 简介
影响版本:shiro < 1.5.0
# 配置
依赖:
<!-- shiro dependence -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>
shiro配置:
@Configuration
public class shiroConfig {
@Bean
Auth auth() {
return new Auth();
}
@Bean
SecurityManager securityManager() {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(auth());
return manager;
}
@Bean
ShiroFilterFactoryBean shiroFilterFactoryBean() {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager());
// 配置认证权限
bean.setLoginUrl("/login");
HashMap<String, String> map = new HashMap<>();
map.put("/login", "anon");
map.put("/user", "anon");
map.put("/admin", "authc");
bean.setFilterChainDefinitionMap(map);
return bean;
}
}
# 分析
正常访问/admin
路由,因为过滤器的配置,所以会302跳转到/login
路由下:
在/admin
路由后面加/
,访问/admin/
路由,发现可以绕过shiro的鉴权:
# shiro
shiro处理URL从而进行匹配的方法为org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain
,打下断点,发送请求:
在获取到请求的URL之后,会进入到pathMatches
方法中进行匹配:
连续跟进到doMatch
方法中:
return pattern.endsWith(this.pathSeparator) ? path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator);
在这一行中,pattern为/admin
,pathSeparator为/
,path为/admin/
,所以返回的!path.endsWith(this.pathSeparator)
就为false
,shiro就认为没有匹配到对应路由,绕过了shiro的权限验证。
# Spring
Spring处理URL的逻辑在org.springframework.web.util.UrlPathHelper#getLookupPathForRequest
方法中:
public String getLookupPathForRequest(HttpServletRequest request) {
String pathWithinApp = this.getPathWithinApplication(request);
if (!this.alwaysUseFullPath && !this.skipServletPathDetermination(request)) {
String rest = this.getPathWithinServletMapping(request, pathWithinApp);
return StringUtils.hasLength(rest) ? rest : pathWithinApp;
} else {
return pathWithinApp;
}
}
获取到请求路径之后并返回到getHandlerInternal
方法中,进入lookupHandlerMethod
中寻找HandlerMethod:
跟进该方法,在获取到mappingRegistry
之后会在map中尝试获取路由:
this.pathLookup
中储存了我们配置的三个路由和另外一个/error
路由,调用get
方法尝试匹配我们的请求路径:
获取的结果为null
,之后会调用addMatchingMappings
方法,便利mappingRegistry
中的每一个map进行匹配:
主要匹配的逻辑是在getMatchingMapping
方法中:
接着跟进到getMatchingCondition
方法中,再跟入this.patternsCondition.getMatchingCondition(request)
:
获取到lookupPath
之后再跟入getMatchingPatterns
方法:
再跟入getMatingPattern
方法:
这个方法最后的返回值如下:
return this.useTrailingSlashMatch && !pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath) ? pattern + "/" : null;
会在pattern
(/admin
)后加一个/
:
逐层返回,获取到对应的hanlderMethod
,spring处的URL匹配成功:
# 修复
通过diff一下新版本的代码,可以发现shiro对于此漏洞的修复方案是对URL和匹配的pattern的末尾做了去/
号的处理。
下篇文章将会复现分析 shiro < 1.5.2 版本下的权限绕过问题。
- 02
- CommonsBeanUtils04-19
- 03
- 基于Tomcat全局存储进行回显04-16