基于虛擬化的安全(VBS,Virtualization-based security)
??????? 很多人都認為內核是可信賴的,因為其自身擁有的高權限以及其與用戶模式下的應用隔離。然而,每個月都有無數的第三方驅動發布,微軟通過遙測發現每個月有超過百萬個不同的驅動哈希值。這些驅動每一個都可能有很多漏洞,更不要說惡意的內核模式代碼。這種現實情況下,想要內核是一個小規模的受保護的組件并且用戶模式應用也不會被攻擊是不現實的。這種狀況導致無法完全信任內核,并使得可以的內核模式程序(利用有問題的內核模式組件)可以危害到高度私密的用戶數據的用戶模式關鍵應用程序。
正如第二章,系統架構中討論的,Windows10和Server 2016包含了一個VBS架構,它啟用了一個額外的正交信任等級: 虛擬信任級別(VTL,virtual trust level )。本節,你講了解到Credential Guard和Device Gurad如何利用VTLs來保護用戶數據和為數字代碼簽名提供一個可信硬件層。
正常用戶模式和內核代碼運行在VTL 0并且根本不知道的VTL 1的存在。這意味著任何VTL 1中的事物對于VTL 0代碼都是隱藏和無法訪問的。即使惡意軟件能夠入侵普通內核,它仍然無法獲取任何存儲在VTL1里面的數據,甚至包括運行在VTL1中的用戶模式代碼(稱為隔離用戶模式)。圖7-2描述了本章節我們將講到的VBS的主要組件。
Device Guard主要由Hypervisor-Based Code Integrity (HVCI) and Kernel-Mode Code Integrity (KMCI)來實現。
Credential Guard主要是通過LSA (Lsass.exe) 和隔離LSA (LsaIso.exe)實現的。
當然,和所有可信組件一樣,VTL1也假設它的所有依賴都是可信的。因此,VTL1需要Secure Boot工作正常,超級監督者(hypervisor)沒有被盜用。
Credential Guard
要想了解Credential Guard提供的安全和保護范圍,我們需要先了解用來提供獲取用戶數據和資源或者登陸網絡環境的幾種組件:
Password:這是用戶用來與計算機認證所使用的最主要的憑據。
NT one-way function(NT OWF):在成功登陸之后,使用NTLM協議來為用戶在遺留組件中為用戶提供認證的Hash值。這個Hash是MD4的,因此在現有的計算能力下和容易被破解。
Ticket-granting ticket(TGT):與NT OWF相同,不過使用了更現代一些的遠程認證機制:Kerberos。登錄成功后,TGT和相應的秘鑰將會被提供給本地計算機。一旦這兩部分被攻擊者截獲,用戶的憑證將立刻被攻陷,雖然用戶的密碼并無法被破解和重用。
如果沒有啟用Credential Guard,這些組件中用戶認證的信息將會在LSASS的內存中保存。
如何啟用Credential Guard:
gpedit.msc -> Computer Configuration -> Administrative Templates -> System ->?Device Guard ->?Turn on Virtualization Based Security ->?Enabled
保護密碼
密碼會被本地對稱秘鑰加密,用來為多種協議(例如Digest、RDP)提供SSO(single sign-on)。由于這些協議都使用明文認證,因此密碼必須保存在內存中,這樣通過代碼注入,調試器或者破解技術就可以解密這些密碼。Credential Guard無法改變這些固有的不安全協議。因此,唯一的解決方案就是這些關閉協議的SSO功能。這將會降低兼容性并迫使用戶重新認證。
顯然,更可取的解決方式是完全不使用密碼。Windows Hello 允許通過生物憑證,例如人臉或者指紋來替代輸入密碼。如果用戶根本沒有密碼,也就不會被盜了。另外比較熟悉的是智能卡和PIN碼。由于PIN碼可能在輸入時被竊取,智能卡是用來保證輸入不被攔截的一種途徑。這是雙重認證的一種。
保護NTOWF/TGT 密鑰
即使有了受保護的交互式憑證,域控制器的密鑰分配中心(KDC,key distribution center)還會返回TGT和它的密鑰。然后用戶就可以使用NTOWF來獲取資源,并用TGT向KDC獲取Service Ticket。Service Ticket可以用來獲取遠程資源,例如共享文件。
因此,只要攻擊者獲取到儲存在LSASS中的NTOWF或者是TGT和密鑰,他們就可以繞過智能卡,PIN或者面部和指紋識別來獲取到用戶的資源。保護LSASS不被攻擊者獲取是一個選擇。我們可以通過PPL(Protected Process Light)架構來實現。
我們可以通過設置HKLM\System\CurrentControlSet\Consol\Lsa的RunAsPPL鍵值為1來運行LSASS的PPL保護。不幸的是,盡管這樣能夠保護NTOWF和TGT 密鑰不被用戶模式攻擊者攻擊,但是他無法保護內核模式攻擊者,或者用戶模式攻擊者利用數以百萬級的驅動漏洞來進行攻擊。Credential Guard通過運行在VTL1中的LSAISO.exe進程來解決這個問題。這個進程會將用戶的秘鑰保存在它的內存里。
安全通信(Secure communication)
正如第二章中描述的,VTL1的被攻擊面很小,因為它并不是一個完整的“NT”內核,它也并沒有任何驅動或者連接任何獲取IO的硬件。這也意味著,LSAISO無法直接與KDC通信。因此,上圖所描述的步驟還是需要有LSASS來實現。這就引入了兩個問題:LSASS與LSAISO之間如何接受和發送這些secrets,以及我們如果防止攻擊者做同樣的事情?
第一個問題,我們可以通過ALPC(Advanced Local Procedure Call)來實現。ALPC可以使隔離用戶模式環境支持ALPC協議的RPC運行時庫(Rpcrt4.dll)。這將允許一個VTL0和VTL1應用通過本地RPC來通信。通過Process Explorer我們可以看到LsaIso.exe進程有一個名為LSA_ISO_RPC_SERVER 的ALPC端口。這就是用來與LSASS通信的。
要想回答第二個問題,我們需要先了解一下密碼協議和質詢/響應(challenge/response)模型。如果以已經對SSL/TLS技術以及他們如何在互聯網通信中避免中間人攻擊(MitM, Man in the Middle)有了基本的了解,你可以把KDC和LSAISO協議想象成類似的情況。盡管LSASS在中間充當了代理的角色,它只能看到KDC和LSAISO之間發送的加密過的信息,無法知道信息的內容。因為LSAISO建立了一個只存在于VTL1中的本地“session key”,然后通過安全協議發送使用只有KDC才有的密鑰加密過的“session key”。KDC將使用這個“session key”加密TGT和密鑰并將其返回。
這一模型也同樣可以被用來保護基于質詢/響應模型的NTLM認證。比如,當用戶使用明文憑證登錄時,LSA將憑證發送給LSAISO,LSAISO將使用“session key”加密并返回給LSASS。當一次NTLM質詢/響應發起時,Lsass將NTLM質詢和之前加密的憑證發送給LSAISO。這時只有LSAISO有可以解密的密鑰,于是它將憑證解密并基于NTLM質詢生成響應。
然而,需要知道的是,這個模型里有四個可能存在的攻擊:
1.如果機器已經被劫持,明文密碼可能在輸入或者發送到LASISO階段就被截獲。使用WindowsHello可以緩解這個問題。
2.正如之前提到的,NTLM沒有反重播(anti-replay)屬性。因此如果NTML響應被截獲,它將可以被用來回復同樣的質詢。另外,如果攻擊者在登陸之后攻陷了LSASS,它將可以截獲加密的憑據并強制LSAISO來為任意NTLM質詢來生成新的NTLM響應。不過這種攻擊只能生效與reboot之前,因為一旦重啟,LSAISO將會生成一個新的“session key”。
3.如果機器已經被劫持,在使用Kerberos登錄時,NTOWF可能像標準的Hash傳遞攻擊(pass-the-hash attack)那樣被截獲并重用。
4.物理登陸的用戶可以關閉Credential Guard。這種情況下,舊的登錄模型將會被啟用(也稱之為降維攻擊,downgrade attack),于是舊的攻擊模式將可以被實施。
UEFI lock
由于攻擊者很容易就能關閉Credential Guard(只不過是一個注冊表選項),Secure Boot和UEFI可以用來防止攻擊者來關閉Credential Guard。我們可以通過啟用Credential Guard的UEFILock。這種模式下,一個EFI運行時變量將會被寫入固件的內存并需要重啟生效。重啟時,WindowsBootLoader會寫入這個變量來記錄Credential Guard是啟用的。同時,一個BCD(Boot Configuration Database)選項會被記錄。
當內核啟動后,他會自動重寫BCD選項/UEFI 運行時變量里存在的Credential Guard注冊表鍵值。如果BCD選項被攻擊者刪除,BitLocker(如果啟用)和基于TPM的遠程驗證(如果啟用)會檢測到改動,然后會要求啟動前輸入管理員的恢復密匙,并通過UEFI運行時變量來恢復BCD選項。因此,攻擊者將無法在UEFI Lock模式下禁用Credential Guard。
認證策略和加強的Kerberos(Authentication policies and armored Kerberos)
“只要登錄就是安全的”模式相對于哪些沒有基于Credential Guard模式確實是一個很大的進步。然而,有些公司或組織可能想要更強的安全承諾:哪些被挾持的機器也不能被用來偽裝或者重發用戶的憑證,或者即使憑證被截獲,他們也不能被用在某些特定的系統里。利用Server 2016的一個稱為認證策略和加強的Kerberos(Authentication Pilicies and armored Kerberos)的功能,Credential Guard可以實現這種提升的安全模式。
在這種模式下,VTL1安全內核將通過TPM收集一個特殊的Machine ID 密鑰。這個密鑰將在機器加入域的操作時被用來生成一個machine TGT 密鑰,這個TGT密鑰會被發送到KDC。一旦配置成功,當用戶使用他們的憑證登錄時,他們的憑證將會結合機器的憑證形成一個來源證明(proof-of-origin)密鑰。KDC將會返回用來源證明密鑰加密過的NTOWF和用戶TGT 密鑰。這種模式下,提供了兩種安全保障:
1.用戶從一個已知的機器認證:如果用戶或者攻擊者有原始憑證并嘗試在其他機器上使用它們,它們基于TPM的機器憑證將會不同。
2.NTLM響應/用戶Ticket將從LSAISO生成而并不是在Lsass中手動生成:這就保證了Credential Guard在這臺機器上是啟用的,盡管用戶可以通過某些途徑關閉它。
不幸的是,如果機器被劫持,攻擊者獲得了來源證明密鑰加密過的KDC響應。攻擊者可以使用它向LSAISO來獲取“session-key”加密的service tickets。這樣他們就可以獲取遠程文件了。避免這種問題唯一的方法就是重啟,因為重啟會生成一個新的session key。所以,在一個啟用了Credential Guard的系統中,建議每次用戶登出就重啟。
未來的改進
正如在第二章和第三章中討論的,VTL1中的安全內核是目前正在進行的改進。他可以用來添加對特殊類型的PCI和USB硬件支持,這些硬件可以獨占的與超級監督者和VTL1代碼使用SDF(Secure Device Framework)來通信。結合BioIso.exe和FsIso.exe,基于VTL0內核模式的組件無法截獲Windows Hello的認證。一旦發布,Windows Hello 憑證將會在硬件層保障對VTL0不可用。在這種模式下,Lsass將不需要參與Windows Hello認證。LsaIso將會直接從隔離的生物識別和幀服務(Frame Service)獲得憑證。
Device Guard
Credential Guard主要關心用戶的憑據的安全,Device Guard則有一個完全不同的目標:保護用戶的機器免于各種軟件或者硬件的攻擊。Device Guard利用了Windows Code Integrity服務,例如內核模式代碼簽名(KMCS,Kernel-Mode Code Signing),用戶模式代碼完整(UMCI,User-Mode Code Integrity)然后通過HVCI(HyperVisor Coide Integrity)來增強他們。(CI請參考第八章第二節)
另外,由于有Custom Code Integrity和簽名策略,Device Guard是完全可配置的。這些策略可以通過文件的SHA-2 Hash值或者證書簽名者來設置強制允許/排除清單。(AppLocker的策略則是使用文件名或者文件路徑)
這里我們不會詳細描述具體的各種配置CI策略的方法,我們會列出Device Guard的幾個主要保證原則:
1. 如果內核模式代碼簽名被實施,只有簽名的代碼可以被加載,即使內核被攻擊者劫持
2. 如果內核模式代碼簽名被實施,簽名代碼一旦被加載將不可修改
3. 如果內核模式代碼簽名被實施,動態分配代碼(dynamically allocated code)將被禁止
4. 如果內核模式代碼簽名被實施,UEFI運行時代碼將不能被修改,另外Secure Boot也需要驗證UEFI運行時代碼在加載時是簽名的。
5. 如果內核模式代碼簽名被實施,只有內核模式(ring 0)簽名代碼可以執行
6. 如果用戶模式代碼簽名被實施,只有簽名的用戶模式鏡像可以被加載,這就意味著所有可執行進程必須被簽名,無論是exe文件或者是它所調用的dll。
7. 如果用戶模式代碼簽名被實施,內核將禁止用戶模式應用程序使現有可執行代碼頁可寫
8. 如果用戶模式代碼簽名被實施,并且簽名策略要求Hard Code保證,則動態分配代碼將被禁止
9. 如果用戶模式PowerShell約束語言模式被啟用,那么所有使用動態類型,反射或者其他功能允許執行Windows/.NET API的PowerShell腳本也需要被簽名
有一點很重要,為了優化性能,HVCI機制在系統從休眠狀態(S4 sleep state)恢復的時候不會重新認證所有的頁面文件。因此,超級監督者需要信任休眠文件沒有被篡改過。這是通過使用TPM中存儲的本地機器秘鑰來加密這些休眠文件來實現的。不過,不幸的是,如果沒有TPM,這個秘鑰必須存儲在UEFI運行時變量中。這就給攻擊者機會獲得這個密鑰來解密,修改并加密休眠文件。