您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Apache Shiro 權限繞過漏洞CVE-2020-11989的分析是怎樣的,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼和會話管理。使用Shiro的易于理解的API,可以快速、輕松地獲得任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。內置了可以連接大量安全數據源(又名目錄)的Realm,如LDAP、關系數據庫(JDBC)、類似INI的文本配置資源以及屬性文件等。
Apache Shiro 1.5.3之前版本,由于Shiro攔截器與requestURI的匹配流程和Web框架的攔截器的匹配流程有差異,攻擊者構造一個特殊的http請求,可以繞過Shiro的認證,未授權訪問敏感路徑。此漏洞存在兩種攻擊方式。
First Attack
傳入的payload首先被服務器接收,并傳送給Shiro攔截器處理(org.apache.shiro.web.servlet.OncePerRequestFilter#doFilter方法作為入口)。
調用createSubject方法創建Subject,并調用execute方法進入Shiro FilterChain中。
進入org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain方法中,首先獲取請求URI路徑。
在Shiro1.5.2版本中,對于requestURI處理的方式存在一些不同,此處也是漏洞觸發點所在。Shiro1.5.2使用的是request.getContextPath(),request.getServletPath(),request.getPathInfo()拼接的方式。由于getServletPath()方法會對requestURI進行一次url解碼,在之后的decodeAndCleanUriString方法中進行第二次url解碼。
回到getChain方法中,迭代獲取攔截器的表達式。
這里重點關注/hello/*表達式。代碼進入pathMatches方法,最終調用org.apache.shiro.util.AntPathMatcher#doMatch方法進行傳入的requestURI與攔截器表達式進行匹配。
匹配過程中,分別將攔截器表達式與requestURI以/作為分隔符進行字符串到數組的轉換,通過循環匹配數組中對應的元素,判斷requestURI是否符合攔截器表達式匹配形式。
如果表達式中存在通配符*,會將containsStar標志位賦值為true,進入 else if (patIdxEnd == 0)判斷條件,返回true。
最終回到doMatch方法中,通過判斷表達式數組的元素個數與requestURI的元素個數,以及表達式中是否包含**,完成后續的匹配。
跟進到Spring處理URI的代碼,進入org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal方法,獲取requestURI。由于Spring獲取requestURI時使用getRequestURI()方法,此方法不會進行URL解碼。只會在decodeAndCleanUriString完成一次url解碼。
進入lookupHandlerMethod方法,調用addMatchingMappings方法,獲取Spring攔截器。
進入org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#getMatchingCondition方法調用doMatch方法進行requestURI和攔截器表達式的匹配。
Spring攔截器匹配流程和Shiro大致相同,同樣是將字符串轉換為數組進行匹配。
由于Spring只進行了一次URL解碼,所以將未完全解碼的部分作為一個整體,從而完成了攔截器表達式與requestURI的匹配。
Second Attack
漏洞觸發點同樣是Shiro在修復CVE-2020-1957漏洞時,使用request.getContextPath(),request.getServletPath(),request.getPathInfo()拼接的方式,進行requestURI的獲取。<br>直接跟蹤到uri = valueOrEmpty(request.getContextPath()) + "/" + valueOrEmpty(request.getServletPath()) + valueOrEmpty(request.getPathInfo());
在調用getContextPath()方法獲取context-path時,會調用removePathParameter方法清除掉分號以及分號到下一個/中間的數據。
接下來進入for循環中匹配candidate與conotext-path是否相同。
如果不同,則從傳入的URL中繼續讀取下一級目錄,直到condidate與context-path相同,返回從URL截取的目錄作為contextPath。由于context-path獲取方式和removePathparameters方法對URL的處理,攻擊者可以請求,讓contextPath變量獲取到帶有分號的非預期值。
在進行requestURI拼接時,構造出根路徑帶有分號的requestURI。利用CVE-2020-1957漏洞原理,經過decodeAndCleanUriString方法時,截斷reqeustURI中分號后的數據,并返回。從而繞過了shiro權限控制。
回顧CVE-2020-1957漏洞
在URI正規化處理時,先調用decodeAndCleanUriString方法進行路徑的解碼,并清理URI。
進入decodeAndCleanUriString方法,發現此方法會以分號將傳入的URI進行截斷,并將分號以及分號后面的數據進行清空,返回分號前面的URI數據,從而讓/a/b;/c變為/a/b。
繼續跟進到Spring攔截器的decodeAndCleanUriString方法中。
從代碼中可以發現,Spring對于分號處理的方式與Shiro不同,Spring會先獲取分號的位置,并檢測分號后是否存在/,如果有,將/的位置記錄在slashIndex變量中,并將分號前的數據與/之后的數據進行拼接,從而讓/a/b;/c變為/a/b/c。返回處理后的requestURI。
補丁分析
對比Shiro 1.5.2與Shiro 1.5.3版本的改動,在org.apache.shiro.web.util.WebUtils類中添加了刪除requestURI結尾的/的代碼。
補丁主要優化了getPathWithinApplication方法,并單獨定義了getServletPath方法,getPathInfo方法。補丁修復后,調用getPathWithinApplication方法獲取requestURI只會在進行getServletPath方法中進行一次url解碼,保持與Spring獲取requestURI過程中相同的url解碼次數。防御了雙重url編碼繞過。
獲取requestURI直接調用getServletPath方法和getPathInfo方法進行拼接,由于不需要與contextpath拼接,從而防御了First Attack攻擊。
搭建Apache Shiro漏洞環境,使用構造的payload進行攻擊,最終繞過授權訪問到未授權資源,效果如圖:
正常訪問:
First Attack
Second Attack
目前受影響的Apache Shiro版本:
Apache Shiro < 1.5.3
Apache Shiro最新版本已經修復此漏洞,請受漏洞影響的用戶下載最新版本, 下載鏈接:http://shiro.apache.org/download.html
以上就是Apache Shiro 權限繞過漏洞CVE-2020-11989的分析是怎樣的,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。