一、前言
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路徑
所以導致權限繞過