(本文作者是orange,以其第一人稱敘述。)
這是我在Black Hat USA 2018和DEFCON 26上的案例研究,PPT可在這里下載:
? Breaking Parser Logic! Take Your Path Normalization Off and Pop 0days Out
這兩年我一直在關注網絡安全中的“不一致”的問題。什么叫做“不一致”的問題呢? 打個比方,就像我去年在Black Hat展示的GitHub的由SSRF導致RCE案例中出現的, URL解析器和URL獲取器之間的不一致導致整個SSRF繞過!
這里還推薦一篇文章@ 0x09AL,Bypassing Web-Application Firewalls by abusing SSL/TLS ,從中足以看出“不一致”問題的可怕。
所以今年,我開始關注路徑解析器和路徑規范化中的“不一致”的問題!
編寫一款設計良好的解析器很難。因為不同的實體都有著不同的標準和實施方式。一般為了在不影響業務邏輯的情況下來修復錯誤,都會增加一個過濾器而不是直接給漏洞打補丁。那如果過濾器和被調用方法之間存在任何不一致,就可以輕松繞過安全機制!
在閱讀文檔說明的時候,我注意到一個叫URL Path Parameter的功能。 一些研究人員早就指出過這個功能可能會導致安全問題,但是是說它仍然取決于編程是否有問題! 畫個思維導圖,然后我發現這個功能可以完美地應用在多層體系結構上,而且是默認情況下就很容易受到攻擊。如果你使用反向代理,并且是Java作為后端服務,那么就危險了!
早先在2015年第一次發現這個攻擊面是在一次紅隊測試中。我覺得這個問題很牛x,想看看有多少人知道,然后就在WCTF 2016中出了一道相關的題目。
不過后來事實證明,沒人知道這個問題,因為沒有參賽隊伍做出這個題。
今年我打算分享這個問題。為了說服審查委員會,我要更多的案例證明它有效!然而在尋找案列的過程中發現這個攻擊面不僅可以泄漏信息,還可以繞過ACL(例如優步的OneLogin bypass),并在幾個賞金計劃中導致RCE。 這篇文章介紹的就是其中之一!
(PPT里有以上的案例說明)
↓多層架構的不一致性!
首先,感謝亞馬遜的漏洞披露計劃。與亞馬遜安全團隊合作感覺特別好(當然Nuxeo團隊也是)。
整個故事始于一個域名collaborate-corp.amazon.com,它貌似是一個內部協作系統。 從網頁下面的copyright來看,這個系統是用一個開源項目Nuxeo構建的。 它是一個非常龐大的Java項目,起初我就想提高一下Java審計技能。所以就從它開始了。
我的個人習慣是拿到java源碼之后先去看pom.xml,看看有沒有引用一些過時的包什么的。在java漏洞里面很多問題都是OWASP Top 10 – A9上列的已知易受攻擊的組件,比如Struts2,FastJSON,XStream或具有反序列化問題的組件等等。
Nuxeo的包大部分都是最新的。不過還是有一個“老朋友”——Seam Framework。 Seam是JBoss開發的Web應用程序框架,幾年前它是一個相當流行的Web框架,到現在仍有許多基于Seam的應用程序:P
1. 路徑規范化錯誤導致ACL繞過
通過WEB-INF / web.xml查看訪問控制時,我發現Nuxeo使用自定義的身份驗證過濾器NuxeoAuthenticationFilter并映射/ *。 從過濾器來看大多數頁面都需要身份驗證,但是有一個白名單,例如login.jsp。這些都是在bypassAuth方法中實現的。
從上面可以看出來,bypassAuth檢索當前請求的頁面,與unAuthenticatedURLPrefix進行比較。 但bypassAuth如何檢索當前請求的頁面? Nuxeo編寫了一個從HttpServletRequest.RequestURI中提取請求頁面的方法,第一個問題出現在這里!
為了處理URL路徑參數,Nuxeo以分號截斷所有尾隨部分。 但是URL路徑參數是多種多樣的。 每個Web服務器都有自己的實現。 Nuxeo的方式在WildFly,JBoss和WebLogic等容器中可能是安全的。 但它在Tomcat下就不行了! 因此getRequestedPage方法和Servlet容器之間的區別會導致安全問題!
根據截斷方式,我們可以偽造一個與ACL中的白名單匹配但是到達Servlet中未授權區域的請求!
我們選擇login.jsp作為前綴! ACL繞過可能如下所示:
如圖所示,繞過了重定向進行身份驗證,不過大多數頁面還是返回500錯誤。這是因為servlet邏輯無法獲得有效的用戶原則,因此它會拋出Java NullPointerException。 但這并不影響進一步操作。
附: 雖然有一個更快捷的方式來實現這個目的,不過還是值得寫下第一次嘗試!
2. 代碼重用功能導致部分EL調用
我之前也說到,Seam框架中有許多安全隱患。所以下一步我要做的就是回到第一個問題中去訪問未經認證的Seam servlet!
這個部分我將逐一詳細解釋這些“功能”.
為了控制瀏覽器應該重定向的位置,Seam引入了一系列HTTP參數,并且在這些HTTP參數中也存在問題… actionOutcome就是其中之一。 2013年,@meder發現了一個遠程代碼執行漏洞。見CVE-2010-1871:JBoss Seam Framework remote code execution for details!但今天,我們將討論另一個 – actionMethod!
actionMethod是一個特殊的參數,可以從查詢字符串中調用特定的JBoss EL(Expression Language)。這看起來相當危險,但在調用之前有一些先決條件。詳細的實現可以在方法callAction中找到。為了調用EL,必須滿足以下前提條件:
1.actionMethod的值必須是一對,例如:FILENAME:EL_CODE
2.FILENAME部分必須是context-root下的真實文件
3.文件FILENAME必須包含內容“#{EL_CODE}”(雙引號是必需的)
例如:
context-root下有一個名為login.xhtml的文件:
可以通過URL調用EL user.username
3. 雙重評估導致EL注入
之前的功能看起來沒啥毛病,你無法控制context-root下的任何文件,因此無法在遠程服務器上調用任意EL。 然而,還有一個更瘋狂的功能:
如果返回一個字符串,并且該字符串看起來像一個EL就糟糕了, Seam框架將再次調用!
請看更細節的調用堆棧信息
1.CallAction(Pages.java)
2.handleOutcome(Pages.java)
3.handleNavigation(SeamNavigationHandler.java)
4.interpolateAndRedirect(FacesManager.java)
5.interpolate(Interpolator.java)
6.interpolateExpressions(Interpolator.java)
7.createValueExpression(Expressions.java)
有了這個功能,如果我們可以控制返回值,我們可以執行任意EL!
這與二進制利用中的ROP(Return-Oriented Programming)非常相似。 所以我們需要找到一個合適的工具!
這里我用的是 widgets/suggest_add_new_directory_entry_iframe.xhtml
為什么選用這個呢?這是因為request.getParameter返回一個我們可以從查詢字符串控制的字符串! 雖然整個標記是分配變量,但我們可以濫用語義!
現在將第二階段payload放在directoryNameForPopup中。 對于第一個bug,我們可以將它們鏈接在一起以執行任意EL而無需任何身份驗證! PoC:
雖然我們現在可以執行任意EL,但仍然無法反彈shell。 為什么?繼續看。
4. EL黑名單繞過導致RCE
Seam也知道EL的問題。 從Seam 2.2.2.Final開始,用一個EL黑名單來阻止危險的調用! 不幸的是,Nuxeo使用最新版本的Seam(2.3.1.Final),因此必須找到繞過黑名單的方法。 黑名單可以在resources/org/jboss/seam/blacklist.properties中找到。
研究一下發現黑名單只是一個簡單的字符串匹配,我們都知道黑名單一般都是下下策。 我剛看到這個,就想起了Struts2 S2-020。這兩個有相似之處。 使用類似數組的運算符來處理黑名單模式:
把
“”.getClass().forName(“java.lang.Runtime”)
改成
“”[“class”].forName(“java.lang.Runtime”)
最后,在JBoss EL中編寫shellcode。 我們使用Java反射API來獲取java.lang.Runtime對象,并列出所有方法。 getRuntime()返回Runtime實例,exec(String)執行我們的命令!
最后總結一下所有所有步驟并將它們連在一起利用:
1.路徑規范化錯誤導致ACL繞過
2.繞過白名單訪問未經授權的Seam servlet
3.使用Seam功能actionMethod調用文件中的小工具suggest_add_new_directory_entry_iframe.xhtml
4.在HTTP參數directoryNameForPopup中準備第二階段payload
5.使用類似數組的運算符繞過EL黑名單
6.使用Java反射API編寫shellcode
7.坐等shell
這是整個漏洞利用:
通過執行perl腳本,成功反彈shell:
修復分為三塊:
1. JPBoos
最麻煩的是Seam框架。 我已于2016年9月向security@jboss.org報告了這些問題。但他們的回復是:
由于EOL這些問題似乎沒有官方補丁。 但是,許多Seam應用程序仍然被廣為使用。 所以如果你使用Seam。 建議你用Nuxeo的方案來緩解這個問題。
2. Amazon
亞馬遜安全團隊隔離了服務器,與報告者討論了如何解決,并列出了他們采取的方案! 與他們合作是一個很好的經歷:)
3. Nuxeo
在亞馬遜發出通知后,Nuxeo迅速發布了8.10版的補丁。 補丁重寫了方法callAction()! 如果需要Seam的補丁,可以在這里下載!
時間線
2018年3月10日01:13 GMT + 8通過aws-security@amazon.com向亞馬遜安全團隊報告
2018年3月10日01:38 GMT + 8收到回復他們正在調查
2018年3月10日03:12 GMT + 8要求我參加安全團隊的電話會議
2018年3月10日05:30 GMT + 8與亞馬遜召開電話會議,了解他們為此漏洞采取的措施
2018年3月10日16:05 GMT + 8詢問是否可以公開披露
2018年3月15日04:58 GMT + 8 Nuxeo發布了新版本8.10,修補了RCE漏洞
2018年3月15日23:00 GMT+8 與亞馬遜召開電話會議,了解情況并討論公開細節
2018年4月 5日05:40 GMT + 8獲得亞馬遜獎金