<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/papers/5037

            0x00 前言


            這是James Forshaw發表在Project Zero上的文章,主要講了CVE-2015-0002的原理,原文鏈接http://googleprojectzero.blogspot.com/2015/02/a-tokens-tale_9.html。

            我非常喜歡漏洞研究的過程,有時發現漏洞挖掘的難度與利用的難度之間有顯著差異。在Project Zero博客中包含了很多對看似瑣碎的漏洞的復雜利用過程。你可能會問,為什么我們會努力證明漏洞是可利用的,我們確實不需要這樣做嗎?希望在這篇博客的最后,你能更好的理解為什么我們總是花費很大努力通過開發一個poc來證明一個安全問題。

            我們PoC的主要目標是供應商,但開發Poc也有其它的好處。使用供應商系統的客戶可以通過PoC來測試它們的系統是否存在這一漏洞,并確保已經打上了所有的補丁。即使供應商不愿意或無法修補漏洞,安全廠商也可以利用它來開發緩解措施和漏洞簽名。而不提供PoC,只有逆向補丁的人才可能了解它,他們可能沒有考慮你的最佳利益。

            ?我不希望這個博客涉及該漏洞(CVE-2015-0002)的太多技術細節。相反,我將重點放在對相對簡單的漏洞的可利用性和PoC開發過程上。該PoC足夠供應商對所描述的漏洞進行一個合理的評估,以減輕工作量。我也會解釋我在PoC開發中采取的各種快捷方式的理由,以及為什么如此。

            0x01 報告漏洞


            在封閉或專有系統上進行漏洞研究的最大問題在于修復漏洞的實際報告流程。特別是在復雜的或非顯而易見的漏洞的情況下。如果系統是開源的,可以開發一個補丁并提交,這代表了一個修復的機會。對于閉源系統,就不得不通過報告的流程。為了更好的理解,讓我們想想典型的大型供應商在接受外部的安全漏洞報告時可能需要做的事。

            enter image description here

            這是漏洞響應處理的一個非常簡單的視圖,但是足以解釋處理原則。對于一個在內部開發他們的大部分軟件的公司,我不能夠影響修補周期,但我可以影響分流周期。越容易對供應商產生影響,分流周期就越短,也就能夠更快的發布補丁。除了已經在使用此漏洞的人,每個人都獲得了好處。不要忘了,即使之前我不知道這個漏洞并不意味著它不被人了解。

            ?在一個理想的漏洞研究的世界(即在其中我只需要做最少量的非科研工作),如果我發現一個bug,我需要做的只是寫了一些關于它的筆記,將其發送給供應商,他們會了解系統,立即采取行動開發補丁,任務就完成了。當然,這樣是行不通的,讓供應商認識到這是一個安全問題是重要的第一步。這可能是從分流周期轉到補丁周期的主要障礙,特別是他們通常是公司內部獨立的實體。為了得到最好的可能,我可能會做兩件事情:

            0x02 寫報告


            盡管在許多情況下并不夠,但寫報告對供應商修復安全問題是非常關鍵的。你可以想象,如果我寫的東西類似“錯誤在ahcache.sys中,請修復它,lol”,這并不能真正幫助廠商。至少,我需要提供一些背景,例如漏洞影響(不影響)哪些系統,漏洞有什么影響(盡我所知)和問題存在于系統的什么地方。

            只有報告為什么并不夠呢?想想大型現代化的軟件產品是如何開發的。它可能是團隊成員分模塊獨立開發完成的。根據漏洞代碼存在的時間,原開發者可能已經轉到其他項目,或者全部離開了公司。即使是身邊可交流的人寫的相對較新的代碼,也并不意味著他們記得代碼是如何工作的。任何人在開發任何規模的軟件,都會碰到一個月、一周甚至一天以前他們寫的代碼,但是不知道它是如何工作的。有一種真實的可能性,花費時間一條一條指令分析軟件的安全研究人員可能比世界上任何人都更了解軟件。

            你也可以在科學意義上考慮一下報告,也就是脆弱性假說。有些漏洞是可以證明,例如緩沖區溢出,通常可以通過數學方式證明,例如想把10件物品放入只能容納5件的空間里將不可能實現。但在很多情況下,沒有什么比開發可利用的證明更好。如果正確完成,可以讓報告者和供應商通過實驗來驗證,這就是概念證明的價值。正確開發概念證明使廠商可以觀察到實驗的效果,將假設變為沒有人可以反駁的理論。

            0x03 通過實驗證明可利用性


            假說假定漏洞具有真實的安全影響,我們將使用PoC來客觀地證明它。為了做到這一點,我們不止需要向供應商提供證明該漏洞真實性的機理,也需要可以清楚觀察到為什么這構成一個安全問題。

            需要什么樣的現象取決于漏洞的類型。對于內存破壞漏洞,可能只需要證明應用程序在響應某些輸入時崩潰就足夠了。但是并非總是如此,一些內存破壞并不提供攻擊者任何有用的控制。因此需要證明可以控制當前執行流,諸如通常理想的是控制EIP寄存器。

            對于邏輯漏洞,可能更細致入微,比如可以寫一個文件到本不能夠寫的位置或者以提升的權限運行了計算器程序。沒有一個適合所有情況的方法,但最起碼??要表現出可以客觀上觀察到的一些安全影響。

            要了解的是我沒有將PoC開發為一個可用的漏洞利用程序(從攻擊者的角度來看),只是足夠證明這是一個安全問題,以保證它能夠被修復。遺憾的是將這兩個者區分開并不容易,有時不展示本地權限提升或遠程代碼執行,它的嚴重性就不會受到應有的重視。

            0x04 開發概念證明


            現在來看看我在開發我發現的ahcache漏洞的PoC時遇到的挑戰。我們不要忘記,花在開發PoC上的時間和漏洞被修復的幾率之間要進行權衡。如果我沒有花足夠的時間來開發一個可用的PoC,供應商可能并不會去修復這個漏洞,另一方面,我花的時間越長,這一漏洞的存在就可能對用戶有害。

            0x05 漏洞的技術細節


            對該漏洞有一點了解將有助于我們后面的討論。這里(https://code.google.com/p/google-security-research/issues/detail?id=118)你可以看到這一漏洞以及附加的我發給Microsoft的PoC。漏洞存在于ahcache.sys驅動程序中,這是Windows8.1引入的,但本質上是在這驅動程序實現的Windows本地系統調用NtApphelpCacheControl中。這個系統調用是用來處理糾正在較新版本的Windows上的應用程序行為的應用程序兼容信息本地緩存的。你可以在這里(https://technet.microsoft.com/en-us/windows/jj863248)閱讀更多有關應用程序兼容性的信息。

            這個系統調用的一些操作是需要權限的,使驅動對當前調用的應用程序進行檢查,以確保他們擁有管理員權限。這些是在函數AhcVerifyAdminContext中完成的,它看起來像下面的代碼:

            #!c++
            BOOLEAN AhcVerifyAdminContext()
            {
            ???BOOLEAN CopyOnOpen;?    ???BOOLEAN EffectiveOnly;?    ???SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;?    ?    ???PACCESS_TOKEN token = PsReferenceImpersonationToken(
            ???????????NtCurrentThread(),?    ???????????&CopyOnOpen,?    ???????????&EffectiveOnly,?    ???????????&ImpersonationLevel);?    
            ???if (token == NULL) {
            ???????token = PsReferencePrimaryToken(NtCurrentProcess());
            ???}?     
            ???PSID user = GetTokenUser(token);
            ?    
            ???if(RtlEqualSid(user, LocalSystemSid) || SeTokenIsAdmin(token)) {
            ???????return TRUE;
            ???}
            ?    
            ???return FALSE;
            }
            

            此代碼查詢當前線程是否模擬其他用戶。 Windows允許一個線程在系統上模擬其他用戶,這樣安全操作就可以正確評估。如果線程正在模擬,將返回一個指向訪問令牌的指針。如果從PsReferenceImpersonationToken返回NULL,代碼則查詢當前進程的訪問令牌。最后,代碼檢查訪問令牌的用戶是不是本地系統用戶或令牌是不是Administrators組的成員。如果函數返回TRUE,則特權操作被允許繼續進行。

            這一切似乎很正確,問題在哪呢?雖然全模擬是僅限于具有令牌模擬特權的用戶才能進行的一種特權操作,普通用戶沒有權限模擬其他用戶執行非安全相關的功能。內核在模擬啟用時,通過分配一個安全級別給令牌來區分特權和非特權模擬。要理解這個漏洞,只需要關心兩個級別,SecurityImpersonation意味著模擬是特權的和SecurityIdentification是非特權的。

            如果令牌被分配為SecurityIdentification,僅能進行查詢令牌信息的操作,例如查詢令牌的用戶。如果你試圖打開受保護的資源,如文件,內核將拒絕訪問。這是潛在的漏洞,如果你看一下代碼,PsReferenceImpersonationToken返回分配給令牌的安全級別的副本,但是代碼并未驗證它是否是SecurityImpersonation。這意味著能夠獲取本地系統訪問令牌的普通用戶可以在SecurityIdentification上進行模擬,仍然可以通過檢查,允許對用戶進行查詢。

            0x06 證明基本的漏洞利用


            要利用該漏洞,需要捕捉本地系統的訪問令牌,模擬它,然后通過適當的參數調用系統調用。這一定要通過普通用戶的權限實現,否則就不是一個安全漏洞。該系統調用未公開,所以如果我們想走捷徑,可能我們只需要表明我們能夠捕捉令牌,只能做到這樣?

            其實并非如此,這個PoC將證明被文檔化的可能的事情確實是可能的。即普通用戶可以捕捉令牌并模擬它,作為模擬系統的設計,這不會導致安全問題。我已經知道COM支持模擬,有很多復雜的系統特權服務(例如BITS),我們可以作為普通用戶與其進行交互,為了進行模擬,可以讓它與我們的應用程序進行通信。這不能證明我們可以到達內核包含漏洞的AhcVerifyAdminContext方法,更別說成功地繞過檢查。

            ?所以,開始了漫長過程的逆向工程,以確定系統調用是如何工作的,你需要傳遞什么參數來使它做一些有用的事。這里也使用了一些來自其他研究人員的成果(如http://www.alex-ionescu.com/?p=39),但肯定沒有現成可用的東西。該系統調用支持許多不同的操作,不是所有的操作所都需要復雜的參數。例如,AppHelpNotifyStart和AppHelpNotifyStop操作可以很容易進行調用,他們依賴于AhcVerifyAdminContext函數。現在可以構造PoC,通過觀察系統調用的返回代碼來驗證對檢查的繞過。

            #!c++
            BOOL IsSecurityVulnerability() {
             ImpersonateLocalSystem();
            ?    
             NTSTATUS status = NtApphelpCacheControl(AppHelpNotifyStop, NULL);
            ?    
            return status != STATUS_ACCESS_DENIED;
            }
            

            這足以證明漏洞可被利用嗎?歷史已經告訴我不能,例如這個問題(https://code.google.com/p/google-security-research/issues/detail?id=127)包含幾乎完全一樣的操作,即可以通過模擬繞過管理員檢查。在這種情況下,除信息披露以外,我并沒有足夠的證據證明它是否會導致其他問題。所以它并沒有被修復,即使它確實是一個安全問題。為了證明可利用性,我們需要花更多的時間在PoC上。

            0x07 改進的概念證明


            為了改進第一個PoC,我需要更好地了解系統調用在做什么。應用程序兼容性緩存用于存儲應用程序兼容性數據庫中的查詢數據。這個數據庫包含的規則會告訴應用程序兼容性系統什么可執行文件需要應用“shims”來實現自定義的行為,如依賴操作系統的版本號來規避不正確的檢查。在進程創建的時候進行查詢,如果找到合適的匹配項,它會被應用到新的進程。新的進程將從數據庫中查詢它需要應用的shim數據。

            enter image description here

            由于每次創建一個新的進程時都要進行這樣的處理,每次查詢數據庫文件會帶來顯著的性能開銷。緩存有助于降低這種影響,數據庫查詢可以被添加到高速緩存中。如果可執行文件稍后被創建,緩存查詢可迅速消除耗時的數據庫查詢,同時應用或者不應用一系列的shims。

            enter image description here

            因此,我們應該能夠緩存現有的查詢并將其應用到任意的可執行文件。所以我花了一些時間獲取系統調用的參數的格式,以便添加自己的查詢緩存。對于32位Windows 8.1,結構看上去像下面這樣:

            #!c++
            struct ApphelpCacheControlData {
            ???????BYTE ??????????unk0[0x98];
            ???????DWORD ?????????query_flags; 
            ???????DWORD ?????????cache_flags;
            ???????HANDLE ????????file_handle;
            ???????HANDLE ????????process_handle;
            ???????UNICODE_STRING file_name;
            ???????UNICODE_STRING package_name;
            ???????DWORD ?????????buf_len;
            ???????LPVOID ????????buffer;
            ???????BYTE ??????????unkC0[0x2C]; 
            ???????UNICODE_STRING module_name;
            ???????BYTE ??????????unkF4[0x14];
            };
            

            你可以在結構中看到有非常多未知的部分。如果你想將它應用到Windows 7(其結構稍微不同)或64位(其結構大小不同),這會導致問題,但對于我們的目的來說并不重要。我們并不需要寫出能在所有版本的Windows上可用的利用代碼,我們需要做的只是向供應商證明這是一個安全問題。我們只要告知供應商PoC的限制(他們將注意到限制),這是可以做到的。供應商應該能夠確定該PoC是否可以跨操作系統的版本使用,畢竟這是他們的產品。

            ?所以,現在可以添加任意的緩存條目,我們真正添加的是什么呢?我只能給現有查詢結果添加條目。你可以修改數據庫來做類似運行時代碼補丁的工作(應用程序兼容性系統也可用于修補程序),但這需要管理員權限。所以,我需要一個現有的shim以便重新利用。

            ?我構建了SDB Explorer工具(https://github.com/evil-e/sdb-explorer)的副本,這樣我可以轉儲現有數據庫查詢中的任何有用的shim。我發現對于32位程序有一個shim會導致進程啟動可執行的regsvr32.exe,并傳遞原始命令行。此工具將加載在命令行上傳遞的一個DLL,執行特定的導出方法,如果我們能夠控制特權進程的命令行,我們可以把它重定向來提升權限。

            enter image description here

            這又限制了PoC只對32位進程有效,但是這很好。最后一步是選擇什么樣的進程來進行重定向。我花了很多時間研究啟動一個進程的時候并能夠控制它的命令行參數的方法。我已經知道一種方式,即UAC自動提升。自動提升作為一個特性被添加到Windows 7,減少典型用戶看到UAC對話框的數量。操作系統定義了允許自動提升的固定的應用程序列表,當UAC為默認設置,且用戶為管理員時,請求提升這些應用程序不會顯示對話框。我可以濫用這一點,為現有的自動提升的應用程序添加緩存條目(在這種情況下,我選擇了ComputerDefaults.exe),并要求應用程序運行提升。被提升的應用重定向到regsvr32,并傳遞我們完全控制的命令行,regsvr32載入我的DLL,而我們現在得到的代碼以提升的權限執行。

            另外,PoC沒有提供任何其他東西,不可能通過其他各種機制(如該Metasploit的模塊https://github.com/rapid7/metasploit-framework/tree/master/external/source/exploits/bypassuac)來實現,但不總是這樣。通過提供一個可觀察的結果充分展示了這一問題(以管理員身份運行任意代碼),這樣微軟就能夠重現并解決它。

            0x08 有趣的最后一點


            由于很容易混淆它是否只能繞過UAC,我決定花一點時間來開發新的PoC,它可以獲得本地系統權限而不依賴UAC。有時候,我喜歡寫漏洞利用,只是為了證明這是可以做到的。要將原來的PoC轉換為獲得本地系統權限的PoC,我需要一個不同的應用來重定向。我認為最有可能的目標是注冊的計劃任務(scheduled task),你有時可以將任意參數傳遞給任務處理進程。因此,實現這一任務,有三條限制,一個普通用戶必須能夠啟動它,它必須啟動一個本地系統權限的進程,進程必須具有由用戶指定的任意的命令行。經過一番搜索我找到了理想的目標,Windows應用商店維護任務(Windows Store Maintenance Task)。正如我們看到的,它作為本地系統用戶來運行。

            enter image description here

            通過使用如icacls的工具查看任務文件的DACL,我們可以確定普通用戶可以啟動它。注意下面的截圖中的項,NT AUTHORITY \Authenticated Users具有讀取和執行(RX)權限。

            enter image description here

            最后,通過檢查XML任務文件,我們可以檢查普通用戶是否可以來傳遞任意參數給任務。在WSTask中,它使用自定義的COM處理程序(https://msdn.microsoft.com/en-us/library/windows/desktop/aa381370(v=vs.85).aspx),但允許用戶指定兩個命令行參數。這將導致可執行文件c:\windows\system32\taskhost.exe作為本地系統用戶執行,并且具有任意命令行參數。

            enter image description here

            這只需要修改PoC以添加taskhost.exe緩存條目,將我們DLL的路徑作為參數來啟動任務。這還是有一定的局限性,特別是它只能在32位Windows8.1上工作(在64位平臺上沒有32位taskhost.exe可供重定向)。不過我敢肯定,通過一些努力,它也能夠在64位上工作。由于該漏洞已經被修復,所以我提供了新的PoC,它附加在原來的問題之后(https://code.google.com/p/google-security-research/issues/detail?id=118#c159)。

            0x09 結論


            我希望我已經證明,為了確保漏洞被修復,漏洞研究人員會去做的一些努力。它最終是花費在PoC開發的時間和漏洞被修復之間的一個折衷,尤其是當該漏洞是復雜的或不明顯的時候。

            ?在這種情況下,我覺得我做出了正確的權衡。盡管從我發送給Microsoft的PoC來看,表面上只是繞過了UAC,結合報告,他們就能夠確定真正的嚴重性并開發補丁。當然,如果他們想推回,并聲稱這不是可利用的,我會開發一個更強大的PoC。通過對嚴重程度的進一步論證,我也開發了一個可用的漏洞利用,可以通過普通用戶帳號獲得本地系統權限。

            ?披露PoC對用戶或安全公司開發公開漏洞的緩解技術是有價值的。如果沒有PoC,驗證安全問題已被修補或緩解是相當困難的。它還有助于告知研究人員和開發人員,在開發一些安全敏感的應用程序時,什么類型的問題需要注意。漏洞挖掘不是Project Zero幫助軟件提高安全性的唯一方法,教育也同樣重要。

            Project Zero的使命是解決軟件漏洞,開發概念驗證幫助軟件廠商或者開源項目采取明智行動修復漏洞也是我們職責的重要組成部分。

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线