曲速未來 消息:使用污點跟蹤在Apache Struts中發現OGNL注入區塊鏈
在這篇文章中,詳細地介紹漏洞的發現,并準確顯示遠程用戶從http請求輸入的結果如何被評估為OGNL表達式。
在這篇文章中,詳細地介紹漏洞的發現,并準確顯示遠程用戶從http請求輸入的結果如何被評估為OGNL表達式。
Struts的架構
首先,我將簡要介紹Struts如何處理http請求。下圖所示:
粗略地講,當Struts的收到一個HTTP請求,它會先使用預配置ActionMapper來構造ActionMapping,其包含諸如namespace,actionName,method和params從請求。這ActionMapping隨后被傳遞到Dispatcher,其中一個ActionProxy和ActionInvocation創建。然后,這些類將工作委托給相應的類Action和Result類來處理請求。這里將通過這個迷宮遵循http請求,并查看請求的各個元素如何最終被評估為OGNL。
根據第一原則進行污點追蹤
從傳入開始進行污點跟蹤HttpServletRequest,展示它是如何在該namespace領域結束的ActionProxy。除了更清楚地了解namespace屬性如何被污染之外,此次查詢也將更加通用,并且能夠識別其他先前的OGNL注入問題。這次用于污點跟蹤的初始查詢可以在這里找到。可對自定義數據流庫進行了一些改進,并包括通過子類中的各種方法進行跟蹤Collections。應該清楚它們CollectionEdges.qll和ExtraEdges.qll庫中的文檔做了什么。正如你所看到的,通過使用QL庫,就可以在查詢之間重用和共享代碼,這意味著隨著時間的推移,事情變得更容易,更容易。
仔細看看這個的各個組成部分DataFlow::Configuration。首先,看一下source,它指定了用戶輸入的來源。標準QL庫提供了一個名為的類RemoteUserInput,它表示可能不受信任的輸入。這個類通常適用于通用污點跟蹤,它包含來自HttpServletRequest類的各種來源。當狩獵的漏洞就會喜歡把它擴大到包括多個數據源,所以說一下這個的dataflow_extra庫:
它基本上將任何看起來像getter作為源的東西,除了getAttribute和getContextPath,通常從服務器端設置。給了這些來源:
對于水槽,上次使用了isOgnlSink。
對于其他流程步驟,使用了如下圖所示:
前兩個邊緣,standardExtraEdges并且collectionsPutEdge是通用邊緣用于跟蹤集合。使用isTaintedFieldStep。這條邊是跟蹤這樣的情況:
如前所述,如果在分配之前訪問受污染的字段,則可能導致虛假結果。所以將其包括在內,因為從查看Struts的體系結構,看到來自http請求的污染數據首先用于創建ActionMapping和ActionProxy,然后在生命周期的后期訪問這些對象的污染字段以執行操作。所以這個邊緣的假設似乎對考慮的問題有效。
最后,還添加了taintStringFieldFromQualifier優勢:
QL數據流庫實際上具有相當精確的通過現場分配和訪問進行污點跟蹤的能力(得益于Anders Schack-Mulligen的辛勤工作)。例如,默認情況下會跟蹤此信息:
但是,為了保持跟蹤精確,當分析能夠找到將污染數據分配給該特定字段的顯式分配時,僅認為字段受到污染。這意味著默認情況下來自受污染源的字段可能不被視為污染,例如:
這是一個公平的假設,因為來自源的字段可能并不總是受到污染,例如:
所以需要明確告訴QL什么時候來源的字段應該被認為是污點。然后就可通過taintStringFieldFromQualifier幫助做到這一點。通過使用這個,希望任何字段訪問被污染,如果對象本身被污染,只希望它如果字段是字符串類型這樣做。這背后的基本原理是使來自源的所有字段訪問都受到污染,但是如果因為在源級別,用戶輸入通常以字符串形式出現,所以只希望在被訪問的字段是字符串類型時發生這種情況。這不會限制對源的字段訪問。
接下來是消毒劑
使用了ToStringSanitizer和MapMethodSanitizer,但擴展它以涵蓋所有對象和地圖類型,因為已經在Struts中發現了一些這些方法的更多覆蓋,給了偽造的結果。該StrutsTestSanitizer排除的代碼處于測試代碼,并且ognlSanitizers采取的各種消毒劑的方法等callMethod,cleanupActionName并且cleanupMethodName該固定s2-032,s2-033和s2-037考慮。
運行此查詢,最后得到了13個結果。
查看數據流路徑,便注意到其中許多都經歷了一個名為的方法
getValidators:
被污染context在這里用作從緩存中key獲取cfgs對象。除非攻擊者也可以控制此緩存的內容,否則不太cfgs可能包含任何可能導致OGNL注入的內容。所以就添加一個消毒劑來過濾掉這個結果:
在檢查了一些其他路徑后,便添加了兩個清潔劑來排除不太可能被擊中的路徑:
在仔細檢查代碼路徑之后排除這些的確切原因,超出了本文的范圍。添加這些消毒劑以清理結果后,現在可以得到7個結果與最終查詢。點擊第一個結果,看到經過幾個步驟后,可以登陸了以下getMapping方法DefaultActionMapper:
如前所述,這發生在生命周期的早期階段,其中ActionMapper使用傳入HttpServletRequest來創建ActionMapping。點擊幾個步驟,進入了parseNameAndNamespace方法:
現在很清楚為什么alwaysSelectFullNamespace必須要使應用程序可以被利用。看看如何namespace在此函數中設置,這是namespace從用戶控制的唯一分支uri。
在受到污染的數據之后,還有幾個步驟,最終在Dispatcher:
這是Dispatcher創建一個ActionProxy來自的階段ActionMapping。正如從第584行所看到的那樣namespace,從第ActionMapping593行和第593行中可以看出,它用于構造ActionProxy。從現在開始,可以假設一個namespace領域ActionProxy可能會受到污染。在getNamespace路徑瀏覽器中單擊下一個后,便看到ActionProxy現在正在使用相應Result的處理請求。
然后namespace在這里進入determineActionURL第86行,然后進入findString第425行,該第425行評估namespace為引擎蓋下的OGNL表達式。
剛剛完成了HttpServletRequestStruts 的整個生命周期,甚至沒有運行它。此外,通過使用數據流分析,基本上同時查看了許多流路徑,并且能夠識別不同Struts配置的問題。
路徑瀏覽器的一個警告是,默認情況下,只顯示4條路徑,因此要查看更多路徑和結果,需要過濾掉已經看到的一些結果。為此目的,所以正在查詢中包含了一個清潔劑:
將其添加到isBarrier謂詞并注釋掉相應的行以查看之前未見過的結果。
獎金材料
通過結果列表,可以看到除了CVE-2018-11776中的那些之外,還有其他一些有趣的:
FileUploadInterceptor跟蹤Struts漏洞的人應該不陌生。可能是Struts近年來最嚴重的漏洞,S2-045影響了這個攔截器。
可以看到開始了multiWrapper.getErrors。這里multiWrapper是類的MultiPartRequestWrapper,是它的子類HttpServletRequest。該getErrors方法是一種覆蓋方法,用于存儲處理請求時發生的任何錯誤,并且可能包含用戶控制的數據。該error對象來源于此,然后被傳遞到textProvider.getText方法。在幾次傳遞之后,然后將其輸入到getDefaultMessage方法中
幾步之后,它最終進入了該translateVariables方法
它被評估message為引擎蓋下的OGNL表達式。結果仍然存在,因為問題的修復涉及在創建MultiPartRequestWrapper用作源的對象之前清理用戶輸入。
結論
在這篇文章中,展示了QL如何能夠在從傳入HttpServletRequest到OGNL評估的所有方式中跟蹤Struts中的用戶輸入。通過在QL中使用數據流庫,查詢給了7個結果,其中5個對應于過去的真實RCE漏洞。總的來說,該查詢發現了這些RCE:s2-008(部分),s2-032,s2-033,s2-037,s2-045,s2-057。
本文內容由 曲速未來 (WarpFuture.com) 安全咨詢公司整理編譯,轉載請注明。 曲速未來提供包括主鏈安全、交易所安全、交易所錢包安全、DAPP開發安全、智能合約開發安全等相關區塊鏈安全咨詢服務。
1.TMT觀察網遵循行業規范,任何轉載的稿件都會明確標注作者和來源;
2.TMT觀察網的原創文章,請轉載時務必注明文章作者和"來源:TMT觀察網",不尊重原創的行為TMT觀察網或將追究責任;
3.作者投稿可能會經TMT觀察網編輯修改或補充。