Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
当使用Spring配置Shiro的Filter时候,就有可能导致权限绕过的情况。
Apache Shiro < 1.7.1
本次实验通过SpringBoot搭建的环境,配置了Shiro的Filter路径,实验环境:https://github.com/jweny/shiro-cve-2020-17523
记住此处的authc对应的key是"/admin/*"
所以漏洞的poc就是:http://localhost:9090/admin/%20
竟然是分析,我就从详细讲解下Shiro的Filter处理过程,先来看到刚才的Bean是通过ShiroFilterFactoryBean类来配置的Config属性,直接跟进去就能看到其中的getObject方法
getObject方法是实现了FactoryBean接口的方法
而这个instance变量是属于AbstractShiroFilter类
再来看看这个createInstance的方法
protected AbstractShiroFilter createInstance() throws Exception {
log.debug("Creating Shiro Filter instance.");
//获取shrio的安全管理容器
SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
String msg \= "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
}
if (!(securityManager instanceof WebSecurityManager)) {
String msg \= "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
}
//获取过滤链管理器,就是shrio的全部过滤器,里面保存着路径和对应的过滤器或者过滤链
FilterChainManager manager = createFilterChainManager();
//Expose the constructed FilterChainManager by first wrapping it in a
// FilterChainResolver implementation. The AbstractShiroFilter implementations
// do not know about FilterChainManagers - only resolvers:
//初始化Ant风格的url匹配器,传入上面的过滤链管理器
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);
//Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
//FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
//here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
//injection of the SecurityManager and FilterChainResolver:
//初始化门户过滤器,所有请求都应该经过这个过滤器
return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}
注意SpringShiroFilter这个filter,它是所有请求的入口类
然后再来注意它的doFilterInternal方法,其中有个executeChain方法,根据request获取对应的chain,进行拦截请求。
这里就是过滤器的处理链开始的地方,从这里就可以开始下断点开始往下跟
再往下看就能发现调用了getChain的方法
跟进后程序就跳进org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain
而关键Sink点就在这个pathMathes方法中
跟进方法中,会找到org.apache.shiro.util.AntPathMatcher#doMatch方法
方法中通过tokenizeToStringArray方法分别获取需要匹配的格式路径和URL路径
至此返回false,但由于Spring的Mapping匹配路径是/admin路径
所以导致权限绕过