近期發現的三個Windows 0day漏洞分析及臨時修復方案
在近期,我們發現了3個0day漏洞,本文將主要分析這些0day漏洞,探討攻擊者利用這些漏洞可以實現的功能,並在最後給出修復建議。
一、angrypolarbearbug漏洞
該漏洞於上個月釋出,由作者SandboxEscaper將其命名為“angrypolarberbug”,該漏洞允許本地無特權程序在系統上使用Windows錯誤報告XML檔案中的內容,覆蓋任何指定的檔案。由於攻擊者幾乎無法控制該XML檔案中的內容,因此SandboxEscaper提供的演示是破壞關鍵系統檔案pci.sys從而導致本地拒絕服務,這樣會阻止系統的啟動。可以想象,如果我們能夠發現覆蓋某些檔案會導致可以在更高許可權(例如:SYSTEM或Administrator)下執行攻擊者特定的程式碼,那麼這一漏洞的危害程度將會更高。但是目前據我們所知,還沒有發現此類漏洞利用方式。
該漏洞的關鍵在於,對於經過身份驗證的使用者來說(包括本地攻擊者),Windows錯誤報告服務建立臨時XML檔案的C:\ProgramData\Microsoft\Windows\WER\Temp\資料夾具有包括讀取、寫入和刪除訪問許可權的可繼承許可權。這意味著,當某人在沒有指定許可權的情況下建立新檔案時,系統上的任何程序(包括低許可權的惡意程序)都可以用另一個檔案替換該檔案。這就是SandboxEscaper的PoC所進行的操作:等待XML檔案出現,然後用指向特定目標檔案(例如:pci.sys)的硬連結快速替換它。當Windows錯誤報告服務隨後重新開啟這一XML檔案並進行寫入時,它實際上開啟的是連結到的檔案,並對其進行寫入。
我們給出的修復方案稍有變化。當Windows錯誤報告服務建立XML檔案時,它現在會被指定與以前完全相同的許可權,但授權使用者對該檔案並沒有刪除許可權。這樣一來,可以使得錯誤報告繼續正常工作,同時防止利用該漏洞刪除XML檔案(以及在其位置建立硬連結)。
我們已經將這個微補丁更新到Windows 10的1803版本中。請注意,由於錯誤報告的工作方式不同,這一漏洞似乎不會影響到Windows 7系統。
大家可以在下面的視訊中看到微補丁的執行情況:
微補丁的原始碼如下:
;Micropatch for wer.dll version 10.17134.471 ; ;How it works: ; a vulnerable call CreateFileW responsible for creating a temporary report XML file ; which inherits loose C:\ProgramData\Microsoft\Windows\WER\Temp\ permissions is replaced by ; a call to ConvertStringSecurityDescriptorToSecurityDescriptor which creates a new security ; descriptor from ACE string that gets supplied to a new CreateFileW call. ; The new security descriptor has no DELETE permissions for AuthenticatedUsers group ; on report XML so a regular user can no longer change it to a hard link. MODULE_PATH "..\AffectedModules\wer.dll_10.17134.471_64bit\wer.dll" PATCH_ID 344 PATCH_FORMAT_VER 2 VULN_ID 4657 PLATFORM win64 patchlet_start PATCHLET_ID 1 PATCHLET_TYPE 2 PIT kernel32.dll!CreateFileW,advapi32.dll!ConvertStringSecurityDescriptorToSecurityDescriptorA,kernel32.dll!LocalFree PATCHLET_OFFSET 0x00059bd7 JUMPOVERBYTES 11 N_ORIGINALBYTES 2 code_start mov qword [rsp+10h], r8 ; dwShareMode mov qword [rsp+8h], rdi ; storing a global variable mov qword [rsp], rcx; lpFileName call arg0_StringSecurityDescriptor ; args for ConvertStringSecurityDescriptorToSecurityDescriptor ; we changed (A;;0x13019f;;;AU) to (A;;GRSD;;;AU) - meaning ; AuthenticatedUsers can Read and Delete only db "D:(A;;FA;;;BA)(A;;GRGW;;;AU)(A;;0x13019f;;;SU)(A;;0x13019f;;;LS)(A;;0x13019f;;;NS)(A;;0x13019f;;;WR)(A;;0x13019f;;;AC)(A;;0x13019f;;;S-1-15-2-2)",0 arg0_StringSecurityDescriptor: pop rcx ; rcx=arg0_StringSecurityDescriptor mov rdx, 01h ; arg1: StringSDRevision=SDDL_REVISION_1 ;arg2: this arg is part of SECURITY_ATTRIBUTES struct so we have to create this first ; sa requires 18h of space sub rsp, 20h; but we're allocating 8 more than required nLength to keep stack alignment lea r8, [rsp+8h] ;arg2: SecurityDescriptor=&sa.lpSecurityDescriptor ;init sa: mov dword [rsp],18h;sa.nLength = sizeof(SECURITY_ATTRIBUTES); mov dword [rsp+10h],1h ;sa.bInheritHandle=FALSE xor r9d,r9d ; SecurityDescriptorSize=NULL sub rsp, 20h ; allocate homespace call PIT_ConvertStringSecurityDescriptorToSecurityDescriptorA ;copy CreateFileW args 5,6 and 7 to a new stack frame mov rax, [rsp+60h] ; dwCreationDisposition mov qword [rsp],rax mov rax, [rsp+68h] ; dwFlagsAndAttributes mov qword [rsp+8h],rax mov rax, [rsp+70h] ; hTemplateFile mov qword [rsp+10h],rax ;obtain CreateFileW args 1,2,3,4 mov rcx, [rsp+40h] ; lpFileName mov edx, 0C0000000h ; dwDesiredAccess mov r8, [rsp+50h] ; dwShareMode lea r9,[rsp+20h] ;lpSecurityAttributes sub rsp, 20h ; alloc homespace call PIT_CreateFileW mov [rsp+28h],rax ; store result ;free the security descriptor: mov rcx,[rsp+48h] ; sa.lpSecurityDescriptor call PIT_LocalFree ;LocalFree(sa.lpSecurityDescriptor) mov rax,[rsp+28h] ;restore result mov rdi,[rsp+68h] ;restore the global variable add rsp, 60h;restore stack code_end patchlet_end
二、Readfile漏洞
在上個月,SandboxEscaper也釋出了“Readfile ” 0day漏洞。該漏洞允許在Windows計算機上執行的非特權程序獲取任意檔案的內容,即使此類檔案的許可權已經設定了不允許對其進行讀訪問。在PoC中,演示了從使用者桌面讀取另一個使用者desktop.ini檔案的內容,但作者提出還可以嘗試讀取Office歷史檔案等內容(具有已知路徑的其他索引檔案或歷史檔案),這樣可以進一步實現漏洞的利用。
該漏洞位於Windows Installer,更確切的說是其中的廣告功能,可以使用MsiAdvertiseProduct函式觸發。在這裡,我們不打算深入說明漏洞的細節。但需要說明的是,在產品安裝過程中(使用MSI安裝包),以SYSTEM身份執行的Windows Installer將獲取相應MSI檔案,並對其進行解析,然後在C:\Windows\Installer資料夾中建立臨時MSI檔案,並複製原始MSI檔案的內容。(實際上,會進行更多操作,但這些操作與漏洞無關,因此在這裡省略。)SandboxEscaper注意到原始MSI檔案被開啟兩次,並且可以在第一次開啟時指向常規MSI檔案的符號連結,但第二次開啟時指向其他檔案。這樣就會導致後一個檔案的內容被複制到臨時MSI檔案中。由於臨時MSI檔案的許可權允許Everyone讀取和訪問,因此攻擊者可以欺騙Windows Installer服務將任意檔案的內容複製到臨時的MSI檔案中,然後讀取該檔案,以獲取特定檔案中的內容。
要對這個漏洞進行修復,需要我們熟悉Windows Installer的內部工作原理。事實證明,將源MSI檔案複製到臨時MSI檔案的函式已經支援對臨時檔案設定兩個不同的許可權集:(1)繼承許可權;(2)源MSI檔案的許可權。它在進行產品的推薦時,使用了繼承的許可權(允許攻擊者讀取檔案),因此我們需要採取一些小技巧,來強制它使用源MSI檔案的許可權。經過修復後,產品廣告功能仍然正常工作,但由於臨時MSI檔案許可權與正在複製的檔案許可權相同,因此攻擊者就無法實現越權讀取檔案。
我們已經將這個微補丁更新到64位的Windows 10 1803版本和最新的Windows 7中。
大家可以在下面的視訊中看到微補丁的執行情況:
微補丁的原始碼如下。其中包含四個小程式,每個小程式都有一條指令。
MODULE_PATH "..\AffectedModules\msi.dll_5.0.17134.228_64bit.dll\msi.dll" ; Windows 10 version 1803 PATCH_ID 345 PATCH_FORMAT_VER 2 VULN_ID 4658 PLATFORM win64 patchlet_start PATCHLET_ID 1 PATCHLET_TYPE 2 PATCHLET_OFFSET 0x002edb76 ; Injecting after eax is set to FlagsAndAttributes ; in CMsiFileCopy::OpenDestination code_start or r12d, 0x8000 ; we set the 15th bit of FlagsAndAttributes, ; which will cause the execution to flow towards using ; source file's ACL code_end patchlet_end patchlet_start PATCHLET_ID 2 PATCHLET_TYPE 2 PATCHLET_OFFSET 0x002edbe9 ; Overwriting code that checks value #12 in ; MSI record, and setting eax to 1 JUMPOVERBYTES 20 code_start mov eax, 1 ; we set eax to 1 to simulate IsNull returning false code_end patchlet_end patchlet_start PATCHLET_ID 3 PATCHLET_TYPE 2 PATCHLET_OFFSET 0x002edd0e ; Overwriting code that checks value #12 in ; MSI record, and setting eax to 1 JUMPOVERBYTES 22 code_start mov eax, 1 ; we set eax to 1 to simulate IsNull returning false code_end patchlet_end patchlet_start PATCHLET_ID 4 PATCHLET_TYPE 2 PATCHLET_OFFSET 0x002edd61 ; Overwriting code that checks value #12 in ; MSI record, and setting eax to 1 JUMPOVERBYTES 6 code_start mov eax, 1 ; we set eax to 1 to simulate IsNull returning false code_end patchlet_end
三、Windows Contacts任意程式碼執行漏洞
該0day漏洞是由ZDI研究員John Page在向微軟報告漏洞的90天后釋出的。該漏洞最初被認為與VCF檔案(預設與Windows Contacts應用程式關聯)有關,但隨後發現CONTACT檔案(預設也與Windows Contacts關聯)也可以進行漏洞利用。
該問題在於,幾乎所有通過網站URL或電子郵件中提供的VCF或CONTACT檔案,其中的字串最終都將被用作ShellExecute呼叫的引數。儘管ShellExecute是用於在使用者預設瀏覽器中開啟URL的便捷功能,但在此操作之前,它還會嘗試在本地計算機上“啟動”提供的字串。具體而言,在提供“www.microsoft.com”的情況下,ShellExecute將首先嚐試查詢並啟動一個名為www.microsoft.com的本地可執行檔案,只有在失敗的情況下,才會在瀏覽器中開啟這一網頁。這樣的行為,在此前已經造成了許多漏洞的出現,將來也毫無疑問會帶來更多的問題。要利用這一漏洞,攻擊者必須誘導使用者開啟惡意的VCF或CONTACT檔案,然後單擊顯示的網站或電子郵件連結,這樣會導致啟動攻擊者的可執行檔案,該檔案也必須存在於使用者的計算機或網路共享上。
我們分析了在點選網站或電子郵件連結時發生的事件,會導致在wab32.dll中使用SafeExecute函式。該函式會對URL進行解析,從而允許mshelp:// URLs形式URL的執行,然後將呼叫ShellExecute。我們在呼叫之前,簡單地添加了一些邏輯,以確保如果URL不以“mailto:”、“http://”或“https://”開頭,那麼將會使用“https://”字首來防止任何可能的本地可執行檔案啟動。我們最初考慮的方法是在讀取檔案的程式碼中新增清理程式碼,但後來發現顯示連結的程式碼很容易存在HTML注入的問題,這會使得清理過程變得異常複雜,並且可能會被繞過。
我們已經將這個微補丁更新到64位的Windows 10 1803版本和最新的Windows 7中。
大家可以在下面的視訊中看到微補丁的執行情況。該視訊同時還很好的演示瞭如何將微補丁應用到正在執行的程序中。我們在Windows Contacts顯示惡意聯絡人卡片時啟動微補丁,並且點選連結,最終的執行結果會與原來有所不同。
微補丁的原始碼如下:
;Micropatch for wab32.dll version 6.1.7601.17699 ; ;How it works: ; in SafeExecute an unsanitized pszUrl - a user-controlled parameter is passed to ShellExecute. ; This patch adds a series of checks for valid pszUrl prefixes and eventually, ; if no valid prefix is found, adds a http:// prefix to pszUrl. MODULE_PATH "..\AffectedModules\wab32.dll_6.1.7601.17699\wab32.dll" PATCH_ID 347 PATCH_FORMAT_VER 2 VULN_ID 4656 PLATFORM win64 patchlet_start PATCHLET_ID 1 PATCHLET_TYPE 2 PATCHLET_OFFSET 0x00087f7a PIT SHLWAPI.dll!StrCmpNICW,msvcrt.dll!memmove JUMPOVERBYTES 0 N_ORIGINALBYTES 1 code_start ;store registers: push rsi push rcx push rdx push r8 push r8; extra space for prefix variable push rax; store pszUrl ;check lpFile for valid prefixes: call mailto db __utf16__('mailto:'),0 mailto: pop rcx; pszStr1 = "mailto:" mov rdx, rax; pszStr2 = pszUrl mov r8, 07h; nChar sub rsp, 20h; homespace call PIT_StrCmpNICW test rax,rax jz skip; if found, exit patch call https db __utf16__('https://'),0 https: pop rcx; pszStr1 = "https://" mov rdx, [rsp+20h]; pszStr2 = pszUrl mov r8, 08h; nChar call PIT_StrCmpNICW test rax,rax jz skip; if found, exit patch call http db __utf16__('http://'),0 http: pop rcx; pszStr1 = "http://" mov [rsp+28h], rcx; store prefix mov rdx, [rsp+20h]; pszStr2 = pszUrl mov r8, 07h; nChar call PIT_StrCmpNICW test rax,rax jz skip; if found, exit patch mov r8, 1024h; num mov rdx, [rsp+20h]; Src = pszUrl lea rcx,[rdx+0eh]; Dst call PIT_memmove; moving pszUrl of max 1024h in size to *pszUrl+0eh mov rcx, [rsp+20h]; Dst = pszUrl mov rdx, [rsp+28h]; Src = "http://" mov r8, 0eh; num call PIT_memmove; copying http:// to *pszUrl skip: ;revert stack: add rsp, 20h; revert homespace pop rax pop r8; blank pop pop r8 pop rdx pop rcx pop rsi code_end patchlet_end
四、總結
上述內容就是我們近期發現的3個0day漏洞,以及相應的臨時修復方式。我們不清楚微軟是否會對這些問題進行修復,也不清楚會在什麼時間解決這些問題。如果使用者已經安裝並註冊了我們的代理,那麼這些微補丁將在計算機上安裝,並應用於所有受影響的程序。否則,大家可以註冊一個免費的0patch帳戶,並安裝0patch Agent以應用這些微補丁。如果此後微軟修復了這些問題,則相關的微補丁將會立即停止執行並恢復到原有狀態,因此使用者無需擔心微補丁會影響Windows Update正常更新。
需要注意的是,我們還沒有將這些微補丁移植到所有Windows版本上。如果大家有修復特定版本Windows的需求,請聯絡[email protected]。