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路径
所以导致权限绕过