在本系列文章的最後一部分中,我們將研究工具包用戶如何獲得對程式流的控制,以及他們的開發策略對可靠性的影響。
- 老年木和勞工部
- 用接骨木書寫功勳(上)
- 用接骨木書寫功勳(下)
上一次,我們討論了Elderwood工具包如何為工具包用戶做幾乎所有的事情,除了給他們一個使用漏洞。我們認為應該由用戶發現漏洞,觸發並利用它,然後將其與工具包集成。我們的分析表明,他們對如何做到這一點的知識很差,囙此開發的可靠性受到影響。在接下來的部分中,我們將遍歷用戶必須自己編寫的利用漏洞的每個部分。
檔案物件模型(DOM)
HTML檔案物件模型(DOM)是HTML頁面的表示形式,用於訪問和修改内容。瀏覽器通過JavaScript向DOM提供一個介面。此介面允許網站具有互動式和動態生成的內容。此介面非常複雜,存在許多安全性漏洞,例如攻擊者在CFR中使用的釋放後使用漏洞。例如,Elderwood組負責在Internet Explorer中發現並利用至少三個此類先前的漏洞。
釋放漏洞後使用
釋放後使用漏洞發生在程式釋放塊,然後在程式執行的某個稍後點嘗試使用該塊時。如果在重用塊之前,攻擊者能够在其位置分配新數據,則他們可以獲得對程式流的控制。
免費使用
- 程式分配然後釋放塊A
- 攻擊者分配塊B,重新使用先前分配給塊A的記憶體
- 攻擊者將數據寫入塊B
- 程式使用釋放的塊A,訪問攻擊者留在那裡的數據
為了利用CVE-2012-4792,利用漏洞分配並釋放了一個CButton對象。雖然在Internet Explorer的其他地方維護了對已釋放對象的弱引用,但利用此漏洞可使用自己的數據覆蓋CButton對象。然後利用此漏洞利用弱引用觸發對CButton對象的虛擬函數調用,從而控制程式執行。
準備堆
在發生16個相同大小的分配之後,Internet Explorer將切換到使用低碎片堆(LFH)進行進一步的堆分配。由於這些分配存在於不同的堆中,囙此無法利用它們,必須忽略它們。為了安全跳過前16個分配,利用漏洞作者通過在div標記上分配className内容,創建了3000個大小與CButton對象相似的字串分配。
所選字串的內容(重複“ab”s)並不重要。重要的是它創建的分配大小。LFH對於小於256位元組的分配有8位元組的細微性,囙此80到88位元組之間的分配將從同一區域分配。下麵是記憶體中字串的記憶體轉儲示例:
然後,利用此漏洞的作者將每個其他div標記的類名指定為空,從而在調用CollectGarbage()時釋放先前創建的字串。這將在分配的堆記憶體中創建漏洞,並創建可預測的分配模式。
接下來,作者創建500個按鈕元素。與以前一樣,它們彼此釋放空間以創建孔,並調用CollectGarbage()以啟用分配的重用。
在利用漏洞的許多重用程式碼示例中,用於堆操作的JavaScript數組稱為arrObject。這恰好是JavaScript食譜第70頁中給出的一個如何創建數組的示例的變數名。
觸發漏洞
下麵的程式碼負責創建釋放後使用條件。applyElement和appendChild調用創建正確的條件和新的分配。在q標記上設定outerText内容,然後調用CollectGarbage()之後,將發生空閒。
此時,有一個指向已釋放記憶體的指針(過時的指針)。為了繼續利用此漏洞,必須將其指向的記憶體替換為攻擊者控制的數據,然後才能使用指針。
值得注意的是,漏洞觸發器是try/catch塊中封裝的攻擊的唯一部分。在測試中,我們確認此try/catch不是觸發漏洞或成功利用漏洞的必要條件。如果作者擔心未處理的异常,他們可以將所有程式碼包裝在try/catch中,而不僅僅是這一部分。這種情況表明,漏洞觸發器獨立於開發人員自己編寫的任何程式碼,可能是自動生成的。
此外,漏洞觸發器是fuzzer可以自己生成的攻擊程式碼的一部分。這樣的安全測試工具可能在每次加載頁面時都會在try/catch塊中包裝許多DOM操作,以便在不重新啟動瀏覽器的情况下最大限度地進行測試。考慮到程式碼中還有許多其他不必要的操作,很可能一個fuzzer的輸出被粘貼到攻擊程式碼中,並且它使用的try/catch保持不變。
替換對象
為了將釋放的CButton對象替換為受其控制的記憶體,攻擊者使用來自LFH的20個分配,然後以第21個分配為目標進行替換。選擇第21次分配的目標可能是通過觀察或實驗,而不是對堆記憶體的精確瞭解。正如我們將在下一節中討論的,這個假設會導致利用漏洞的不可靠行為。如果作者對堆操作有了更好的理解並更改了這幾行程式碼,那麼利用此漏洞可能會更有效。
window.location行有兩個用途:創建替換對象並觸發陳舊指針的使用。與為該漏洞創建的大多數其他堆分配一樣,調用unescape()函數來創建字串。這次略有不同。利用此漏洞的作者使用%u編碼來完全控制分配中的第一個DWORD,即對象的vtable。
對於被替換的對象,記憶體將如下所示:
設定window.location後,瀏覽器將轉到字串中提供的URL。此位置更改將釋放當前頁創建的所有分配,因為它們不再是必需的。這會觸發對已釋放對象的使用,此時攻擊者將獲得對瀏覽器行程的控制權。在這種情況下,這會導致瀏覽器在當前域中加載“/[unprintablebytes]https://www.google.com/settings/account”。由於此URL不存在,在CFR網站上加載漏洞的iframe將顯示一個錯誤頁面。
總之,利用此漏洞可使用攻擊者控制的數據覆蓋已釋放的CButton對象。在這種情況下,使用了一種非常脆弱的科技來覆蓋釋放的CButton對象,囙此利用漏洞攻擊無法可靠地控制被利用瀏覽器的執行。與覆蓋大量最近可能已釋放的對象不同,利用漏洞編寫器假定他們覆蓋的第21個對象始終是正確的已釋放CButton對象。這降低了利用漏洞的可靠性,因為它假定釋放的CButton對象在空閒清單中的預定位置。
現在該漏洞可以被利用,可以通過使用我們在上一篇文章中提到的提供的地址0x10ab0d0c將其與工具包集成。通過將控制權轉移到在該地址加載的SWF,提供的ROP鏈和暫存負載將由受害者運行。
可靠性
與普遍的看法相反,即使在它“支持”的平臺上,利用漏洞也可能失敗。釋放後使用的利用漏洞依賴於對堆的複雜操作來執行受控制的記憶體分配。關於記憶體狀態的假設可能會被總可用記憶體、以前訪問過的網站、存在的CPU數量,甚至主機上運行的軟件的更改所破壞。囙此,我們認為利用可靠性是在這些不同場景中成功執行有效負載與總嘗試的一種度量。
我們類比了現實世界中對CVE-2012-4792使用老年木的情况,以確定其總體可靠性。我們構建了一個Windows XP測試系統,其中包含了利用漏洞所需的Internet Explorer、Flash和Java版本。我們的測試程式從一個隨機的網站開始,從幾個流行的網站中選擇,然後到我們的測試網站託管漏洞。我們認為這是一個接近真實世界的使用,因為被破壞的網站不太可能是任何人的主頁。
在這些理想條件下,我們在測試中確定開發的可靠性為60%。儘管沒有必要創建漏洞來觸發漏洞以成功利用它,如前幾段程式碼所述,但我們發現,如果不執行這些操作,可靠性將下降到50%左右。我們在下麵描述了導致這種低可靠性的一些原因:
- 對SWF提供的常數記憶體位址的依賴。如果記憶體分配發生在攻擊假設的其他位置和此地址,瀏覽器將崩潰。例如,如果在0x10ab0d0c加載了非ASLR的挿件,則利用漏洞永遠不會成功。如果在默認加載地址0x10000000處加載大型模塊,則在Windows XP上也可能發生這種情況。
- 假設陳舊的CButton指針將重用第21個對象。如果陳舊的CButton指針重用任何其他地址,則此假設將導致利用漏洞失敗。在這種情況下,利用此漏洞將從“ab”字串的分配中解除對0x00410042的引用。
- 使用垃圾收集器觸發此漏洞。使用垃圾收集器是觸發此漏洞的好方法,但是,它可能會產生不確定的副作用。例如,如果堆合併,過時的指針很可能指向不受攻擊者控制的緩衝區,並導致瀏覽器崩潰。
甚至在測試此漏洞之前,很明顯它只能針對受影響瀏覽器的一個子集,因為它依賴於Flash和其他挿件來繞過DEP和ASLR。我們用這些約束建立了一個理想的測試環境,發現它們的替換科技是不可靠行為的重要來源。將近50%的網站訪問者本應被利用,但這並不是因為替代科技的脆弱性。
結論
在為DEP和ASLR旁路提供了易於使用的介面之後,該工具包的用戶只需製定一個對象替換策略,就可以創建一個有效的利用漏洞。我們對該漏洞中的對象替換程式碼進行的評估表明,作者對該概念的理解很差,囙此該漏洞是不可靠的。如果作者對堆操作有更好的理解,或者遵循已發佈的對象替換方法,則此漏洞的可靠性會高得多。相反,作者依賴於關於記憶狀態的假設,他們的部分工作似乎是從食譜示例代碼中複製出來的。
直到這一點,可以認為複製的示例代碼的許多示例都是錯誤標誌的結果。我們的分析表明,在最重要的漏洞部分,用戶顯示的技能水准與其餘漏洞保持一致。如果攻擊者假裝不稱職,那麼這段關鍵程式碼就不太可能以一種膚淺的管道受損。相反,這次攻擊活動損失了幾乎一半的網站訪問者,它本可以利用。許多安全行業人士認為,APT集團在野外使用前會先“武器化”利用漏洞。然而,繼續使用Elderwood工具包進行戰略性網站妥協表明,此攻擊者組不需要可靠的工程實踐或高度可靠的攻擊程式碼就可以實現其目標。