1. 程式人生 > >曲速未來 訊息:使用汙點跟蹤在Apache Struts中發現OGNL注入

曲速未來 訊息:使用汙點跟蹤在Apache Struts中發現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開發安全、智慧合約開發安全等相關區塊鏈安全諮詢服務。