【技術分享】一種特殊的dll劫持
去年我分享了我發現的CVE-2020-3535:Cisco Webex Teams windows客戶端dll劫持漏洞。當時我文章中說:
考慮另外一種exe和加載的dll不在同一個路徑的情況,如果C:\abc\def\poc.exe想要加載C:\abc\lib\test.dll,可不可以寫成LoadLibraryW(L”..\lib\test.dll”)呢?這也是會導致漏洞的,同樣windows會把”..\lib\test.dll”直接當成”C:\lib\test.dll”。我在另外某個知名廠商的產品中發現了這樣的代碼,我已經報告給了廠商,還在等廠商給我答復。我可能會在90天的期限或者廠商發布安全公告之后補充更多細節。
實際上我發現了兩個產品中都有這樣的代碼,分別是IBM(R) Db2(R)和VMware ThinApp。具體細節我發到full disclosure里面了:
VMware ThinApp DLL hijacking vulnerability
IBM(R) Db2(R) Windows client DLL Hijacking Vulnerability(0day)
我們看看LoadLibrary的文檔:

微軟說你們可不能直接給LoadLibrary一個相對路徑啊,你們應該先用GetFullPathName獲取dll的絕對路徑,再把絕對路徑作為參數調用LoadLibrary。那么當我們給LoadLibrary提供一個相對路徑的時候到底發生了什么呢?以VMware ThinApp中的LoadLibraryExW(L"\\DummyTLS\\dummyTLS.dll", 0, 0)為例我們來簡單分析一下Windows的ntdll.dll是怎么處理dll路徑的。這里的流程是:KernelBase!LoadLibraryExW->ntdll!LdrpLoadDll->ntdll!LdrpPreprocessDllName,我們來看LdrpPreprocessDllName。

代碼的意思是調用RtlDetermineDosPathNameType_Ustr判斷路徑的類型,這里返回了4也就是RtlPathTypeRooted,后面調用LdrpGetFullPath就得到C:\DummyTLS\dummyTLS.dll這樣的一個路徑了。所以這里處理的邏輯就是只要你是一個相對路徑,Windows就認為你是一個相對于磁盤根目錄(一般也就是C盤)的路徑。可以參考ReactOS的代碼。
非常糟糕的是Windows中非管理員用戶是可以在C盤根目錄下創建文件夾并向其中寫入文件的,所以就導致了這種本地提權的場景。
小 結
1.確實不能理解Windows系統里面為什么有這么奇怪的設計,可能很多Windows開發也不知道。
2.還是像我之前文章里面說的,如果dll加載失敗的時候開發者認真調試檢查就能避免這樣的漏洞(也正因為如此這種dll劫持的場景一般不會發生)。
3.Windows中非管理員用戶是可以在C盤根目錄下創建文件夾并向其中寫入文件的,這給了很多這樣本地提權場景利用的機會。
4.使用絕對路徑往往能更安全一點,后面有機會我也可能繼續分享一些我發現的相對路徑導致的各種各樣的本地提權或者RCE的場景。