您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何進行Shiro權限繞過CVE-2020-1957漏洞分析,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
2020年3月23號,Shiro開發者Brian Demers在用戶社區發表帖子,提醒shiro用戶進行安全更新,本次更新進行了三個修復,其中就包括了對編號為CVE-2020-1957的Shrio授權繞過漏洞的修復。漏洞影響shiro 1.5.2版本以下。
根據Shiro開發者在1.5.2版本中提交的commit中關于PathMatchingFilter類的測試用例,可以直接關聯到JIRA issueSHIRO-682,該issue在1.5.0版本中進行了修復。而1.5.2版本中更新則是對其繞過的修復。
SHIRO-682的修復了spring框架下uri = uri + ‘/’ 繞過Shiro防護的問題。然后下面的描述則清晰得描述了造成改錯誤的原因。
在Spring web項目中,請求URI/resource/menus和/resource/menus/都可以訪問到服務器的資源。
但在Shiro中的URL路徑表達式pathPattern可以正確匹配/resource/menus,但不能正確匹配/resource/menus/,導致過濾鏈無法正確匹配,從而繞Shiro的防護機制。
Shiro框架通過攔截器功能來實現對用戶訪問權限的控制和攔截。Shiro中常見的攔截器有anon,authc等攔截器。
1.anon為匿名攔截器,不需要登錄就能訪問,一般用于靜態資源,或者移動端接口
2.authc為登錄攔截器,需要登錄認證才能訪問的資源。
用戶可以在Shiro.ini編寫匹配URL配置,將會攔截匹配的URL,并執行響應的攔截器。從而實現對URL的訪問控制,URL路徑表達式通常為ANT格式。如下配置,訪問 /index.html主頁的時候,Shiro將不會對其進行登錄判斷,anon攔截器不需要登錄就能進行訪問。而對于/user/xiaoming 等 /user/xiaogang等接口,authc攔截器將會對其進行登錄判斷,有登錄認證才能訪問資源。
[urls] /index.html = anon /user/** = authc
Shiro的URL路徑表達式為Ant 格式,路徑通配符支持?***。
?:匹配一個字符 *:匹配零個或多個字符串 **:匹配路徑中的零個或多個路徑
其中*表示匹配零個或多個字符串,/*可以匹配/hello,但匹配不到/hello/因為*通配符無法匹配路徑。假設/hello接口設置了authc攔截器,訪問/hello將會被進行權限判斷,如果請求的URI為/hello/呢,/*URL路徑表達式將無法正確匹配,放行。然后進入到spring(Servlet)攔截器,spring中/hello形式和/hello/形式的URL訪問的資源是一樣的。
明白上文的內容,漏洞復現就很容易了,復現環境代碼主要參考網上的開源demo。
1.下載demo代碼shiro-basic。
2.導入idea
3.Shiro版本1.4.2
<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>
4.修改ShiroConfig配置文件,添加authc攔截器的攔截正則
@Bean ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); ... ... //map.put("/*", "authc"); map.put("/hello/*", "authc"); bean.setFilterChainDefinitionMap(map); return bean; }
5.修改路由控制器方法
@GetMapping("/hello/{currentPage}") public String hello(@PathVariable Integer currentPage) { return "hello"; }
6.啟動應用
訪問/hello/1接口,可以看到被authc攔截器攔截了,將會跳轉到登錄接口進行登錄。
訪問/hello/1/,成功繞過authc攔截器,獲取到了資源。
漏洞初始成因可以定位到 PathMatchingFilterChainResolver的getChain函數下,該函數作用根據URL路徑匹配中配置的url路徑表達式來匹配輸入的URL,判斷是否匹配攔截器,匹配成功將會返回響應的攔截器執行鏈,讓ShiroFither執行權限操作的。
其對于URL路徑表達式和輸入URL的匹配主要通過pathMathches函數進行匹配。
pathMatches函數其最終會調用shiro.util.AntPathMatcher類中doMatch的對于ant格式的pathPattern和requestURI進行匹配。
//pathMatches:135, PathMatchingFilterChainResolver (org.apache.shiro.web.filter.mgt) protected boolean pathMatches(String pattern, String path) { PatternMatcher pathMatcher = this.getPathMatcher(); return pathMatcher.matches(pattern, path); }
doMatch:109, AntPathMatcher (org.apache.shiro.util),當Shiro 的Ant格式的pathPattern 中的的*通配符是不支持匹配路徑的,所以/hello/*不能成功匹配/hello/1/,也就不會觸發authc攔截器進行權限攔截。從而成功繞過了Shiro攔截器,而后再進入到spring攔截器中,/hello/1/與/hello/1能獲取到相同的資源。
該漏洞是由中國開發者在2019年3月25日在ShiroGitHub項目上提交的issue,并PR了分支代碼589f10添加漏洞修復代碼,最終分支代碼在1.5.0版本進行了合并,合并時間為2019年11月20日。
1.5.0版本修復源自tomsun28提交的PR代碼,代碼修復位置為pathsMatch:125, PathMatchingFilter (org.apache.shiro.web.filter),該修復方式是通過判斷requestURI是否以/為結尾,如果以/結尾的話,則去掉尾部的/符號在與URL表達式進行比較。
也就是當requestURI為/hello/1/等以/為結尾的URI的時候,都會被清除最后的/號,再進行URL路徑匹配。
觀察1.5.2版本中新添加的測試用例。
切換測試版本到1.5.1中,然后從中上面的測試用例提取payload進行繞過。
在1.5.1版本中,添加/還是會直接跳轉到登錄。
繞過payload,/fdsf;/../hello/1,成功繞過。
問題同樣可以定位到getChain函數中對于requestURI的獲取中,如下圖所示,this.getPathWithinApplication(request)獲取的requestURI為/fdsf,而不是我們輸入的/fdsf;/../hello/1,從而導致后面的URI路徑模式匹配返回False,從而再次繞過了shiro攔截器。
getPathWithinApplication函數中會調用WebUtils (org.apache.shiro.web.util)中的getRequestUri函數獲取RequestUri。
public static String getRequestUri(HttpServletRequest request) { String uri = (String)request.getAttribute("javax.servlet.include.request_uri"); if (uri == null) { uri = request.getRequestURI(); } return normalize(decodeAndCleanUriString(request, uri)); }
RequestUri函數中最終調用decodeAndCleanUriString函數對URI進行清洗。
private static String decodeAndCleanUriString(HttpServletRequest request, String uri) { uri = decodeRequestString(request, uri); int semicolonIndex = uri.indexOf(59);//獲取;號的位置 return semicolonIndex != -1 ? uri.substring(0, semicolonIndex) : uri; }
如果URI中存在;號的話,則會刪除其后面的所有字符。/fdsf;/../hello/1/最終也就變成了/fdsf。
再1.5.2版本中對其進行了修復,獲取requestURI的方式從request.getRequestUri直接獲取的方式更改為獲取request的ContextPath,ServletPath,PathInfo,然后再重新拼接而成。
輸入的/fdsf;/../hello/1/,將會被拼接為//hello/1/1再進行URI路徑匹配,則無法繞過攔截器。
在web容器中,Shiro的攔截器是先與spring(Servlet)執行,兩者攔截器對于URI模式匹配的差異,導致Shiro攔截器的繞過,而Shiro對其進行了兩次修復,其一為刪除requestURI后面的/號進行URL路徑匹配,算是簡單的修復了添加/號繞過的方式,而后在1.5.2版本中通過requestURI自主拼接的方式修復了/fdsf;/../hello/1/等使用了;號方式的繞過。
而后又會有什么形式的繞過,或者又有什么其它容器導致的差異化繞過。則未可知。
1.升級1.5.2版本及以上
2.盡量避免使用*通配符作為動態路由攔截器的URL路徑表達式。
關于如何進行Shiro權限繞過CVE-2020-1957漏洞分析就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。