標題:Apache Shiro 身份驗證繞過漏洞復現(CVE-2016-6802)

taibeihacker

Moderator

0x00 漏洞详情​

shiro在路徑控制的時候,未能對傳入的url編碼進行decode解碼,導致攻擊者可以繞過過濾器,訪問被過濾的路徑。

0x01 漏洞影响​

shrio 1.3.2

0x02 环境搭建​

由於這個版本還沒有shiro-spring-boot-starter,只能從GitHub 上獲取項目進行測試,https://github.com/godzeo/shiro_1.2...接下來還需要在samples/web/pom.xml文件中,將jstl的版本指定為1.2。
1049983-20201129040541867-453756220.png
通過idea編輯器對其進行編譯成war包,然後放到tomcat中webapps目錄中運行。已編譯好的war包:https://github.com/backlion/demo/blob/master/samples-web-1.2.4.war
1049983-20201129040542456-1710886761.png

0x03 漏洞复现​

訪問http://192.168.1.9:8080/account/ind...此時使用burp截斷,然後在訪問路徑的前添加/任意目錄名/./,即可繞過認證權限進行訪問。 1.首先直接訪問後台主頁,然後直接302跳轉
1049983-20201129040542944-1430062652.png

2.如果在訪問路徑前加上/任意目錄名/./,即可越權訪問
1049983-20201129040543595-928214420.png
3.這裡可以對其後台主頁源碼查看確實是和繞過後訪問的頁面內容是一致的。
1049983-20201129040544190-885911265.png

0x04 漏洞分析​

關於這個漏洞,網上公開的資料非常少,唯二能找到的有用的就是GitHub上的commit記錄,以及CVE的描述信息。
GitHub commit 信息:https://github.com/apache/shiro/commit/b15ab927709ca18ea4a02538be01919a19ab65afCVE 描述:https://cve.mitre.org/cgi-bin/cvena...t信息,可以定位到缺陷是在WebUtils.java中的getContextPath方法。
uq3jytq42uh22225.png

CVE 描述如下:
Apache Shiro before 1.3.2 allows attackers to bypass intended servlet filters and gain access by leveraging use of a non-root servlet context path.
根據這個CVE描述以及commit信息,我們可以知道,漏洞是出現在Non-ROOT ContextPath的情況下,獲取ContextPath時造成的,不過詳細信息還無從得知。
既然是與ContextPath相關,所以部署樣例項目的時候,需要部署到某個ContextPath下面,不能使用ROOT。我們先在getContextPath函數的入口處247 行打個斷點,並且發送一個正常的需要登錄才能訪問的請求看一下這附近代碼的處理邏輯;
curl -v 'http://192.168.1.9:8080/samples-web-1.2.4/account/index.jsp'
1049983-20201129040545546-1086001728.png
斷下來之後可以看到,這裡就是取了ContextPath,並無特殊操作,我們跟著return繼續向下跟。如果不了解ContextPath,建議先自行Google 一下。
gpoh2wrzhwx22227.png

跟到org.apache.shiro.web.util.WebUtils#getPathWithinApplication這個函數,可以發現,我們剛剛獲取的ContextPath其實是為了計算出RequestURI,參考畫線的兩行代碼;
gae14rwzo1g22228.png

繼續一直跟到了org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain這個函數中,可以看到這裡最終其實是獲取了RequestURI的,這裡稍微單步跟一下,不難發現103行附近的for循環,是用我們獲取到RequestURI進行一個匹配處理,對匹配到情況執行相應的操作。
我們這裡請求的是account/index.jsp,剛好匹配到了/account/**這個模式。在配置文件(shiro.ini) 中,/account/**這個目錄是需要登錄後的用戶才能訪問的,猜測這里後續的操作則是校驗當前用戶是否已經登錄,或者說是否有權限;
sgjexryausi22229.png

這裡直接F9放行,可以發現確實302跳轉到了登錄頁面。這樣一來,思路就清晰了,出問題的地方是ContextPath,而ContextPath是用來生成RequestURI的,而RequestURI又是決定這個請求是否需要鑑權的。所以我們只需要構造出畸形的ContextPath,使其生成出畸形的RequestURI,就可以繞過ApacheShiro的鑑權機制了。
那麼應當如何構造呢?根據commit的補丁代碼,可以看到是是進行了解碼和normalize操作,那肯定是因為有非normal的路徑導致的,猜測只需要構造/x/./這樣的路徑,讓其取到錯誤的ContextPath即可。
重新斷下來之後,可以看到ContextPath的值已經變成/x/./sample_web_war了,再向下跟一下,看看計算出的RequestURI是什麼?經過normalize和解碼之後,RequestURI的值為/sample_web_war/account/index.jsp。
so5am3ijlxs22230.png

繼續向下跟到剛剛看到過的匹配部分,不難看出現在的RequestURI已經無法正常匹配到/account/**這個模式了,也就不會進入校驗是否登錄的階段,我們把這次請求放行之後看看是否正常。
curl --path-as-is -v 'http://192.168.1.9:8080/x/./samples-web-1.2.4/account/index.jsp'
1049983-20201129040549252-1127241613.png
成功的返回了需要登錄之後才能看到的頁面內容。主要還是因為對ContextPath和RequestURI處理不一致導致的。

0x05 参考文献​

 
返回
上方