TeamT5 研發工程師 Zeze 於 2024 HITCON、2024 ROOTCON 發表演講「穿梭於秘密通道:揭密那些深藏在 VPN 的漏洞」。本篇部落格詳細說明演講內容。
Introduction
named pipe 作為一個簡單好用的 IPC 機制被許多軟體使用,這個研究將從 named pipe 運作機制講解,並且實作自動化分析工具來克服在分析一個目標時可能會遇到的難點,以及深入研究 Windscribe、CyberGhost、OpenVPN 三款 VPN 軟體,挖掘與 named pipe 相關的漏洞。
Named Pipe
named pipe 大約在 Windows NT 3.1 這個 1993 年發行的版本中出現,至今至少二、三十年。named pipe 是一種系統中 process 之間的溝通方式,也就是 IPC (Inter-Process Communication)。named pipe 其實是一個 file object,主要由 windows 系統中一個稱作 NPFS (Named Pipe FileSystem) 的元件管理。
目標 VPN
Windscribe
官方網站介紹:Windscribe is a desktop application and browser extension that work together to block ads and trackers, restore access to blocked content and help you safeguard your privacy online.
windscribe 是一個開源的 VPN (Windscribe/Desktop-App),用 C/C++ 實作,最一開始會選擇研究 VPN 的 named pipe 漏洞也是從 windscribe 開始的。
CyberGhost
官方網站介紹:CyberGhost is the best VPN service in 2024. With 11712 servers, it offers top privacy for all devices, Windows, iOS, Mac, Android, or Linux.
CyberGhost 相對曝光度高一些,它是一款閉源的 VPN,用 C# 實作。
OpenVPN
官方網站介紹:OpenVPN is a network security company serving the secure remote access needs of small businesses to the enterprise. Our on-prem and cloud-based products offer the essentials of zero trust network access and are built on the leading OpenVPN tunneling protocol.
OpenVPN 應該無人不知,它是一個開源的 VPN (OpenVPN Inc),用 C 實作。
Background
Named Pipe Communication
named pipe 基本的運作方式非常簡單,一般會分為 named pipe client 與 named pipe server 兩個角色,通常 named pipe client 和 named pipe server 是不同的 process,這樣可以達到 IPC (Inter Process Communication) 的效果。
- named pipe server 的 process 用 CreateNamedPipe 建立 named pipe,named pipe 的名稱也在這個 API 的參數中指定。
- 使用 ConnectNamedPipe 等待 named pipe client 連上來。
- named pipe client 的 process 連上 named pipe server 使用 CreateFile,檔名就是 named pipe 的名稱。
- 跟一般操作檔案一樣,用 WriteFile 寫資料給 named pipe 的另一端。
- 另一端用 ReadFile 讀 data,反過來也是一樣。
- 最後用 CloseHandle 關閉 named pipe handle。
Impersonation
一個在 named pipe 中特別的機制,叫做 impersonation,運作方式如下:
- named pipe client 連接 named pipe。
- named pipe server 就可以 impersonate named pipe client。
- named pipe server 可以用 named pipe client 的 process 的 security context 做任何事,比如說建立 process。
因為這個機制是可以透過 SMB 在不同機器上遠端連線的,所以也常被攻擊者用來橫向移動。
Impersonation Level
但是要使用 impersonation 有幾個條件,在 named pipe client 用 CreateFile 連上 named pipe server 時,其中的參數 dwFlagsAndAttributes 需要有 SECURITY_IMPERSONATION 以上的權限。
HANDLE CreateFileA(
[in] LPCSTR lpFileName,
[in] DWORD dwDesiredAccess,
[in] DWORD dwShareMode,
[in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
[in] DWORD dwCreationDisposition,
[in] DWORD dwFlagsAndAttributes,
[in, optional] HANDLE hTemplateFile
);
跟 SECURITY_IMPERSONATION 這個設定相對的是這四個 SECURITY_IMPERSONATION_LEVEL。
- SecurityAnonymous:named pipe server 無法識別 named pipe client,也不能 impersonate。
- SecurityIdentification:named pipe server 可以識別 named pipe client,但不能 impersonate。
- SecurityImpersonation:named pipe server 可以識別 named pipe client 也可以 impersonate,但僅限於同個系統。
- SecurityDelegation:named pipe server 可以識別 named pipe client 也可以 impersonate,而且可以 remote impersonate。
SECURITY_IMPERSONATION_LEVEL | Identification | Impersonate |
---|---|---|
SecurityAnonymous | ❌ | ❌ |
SecurityIdentification | ⭕️ | ❌ |
SecurityImpersonation | ⭕️ | ⭕️(only local) |
SecurityDelegation | ⭕️ | ⭕️(local and remote) |
SeImpersonatePrivilege
除了 named pipe client 有限制之外,named pipe server 在使用 ImpersonateNamedPipeClient 時,還需要有 SeImpersonatePrivilege。
這些是目前預設環境下擁有 SeImpersonatePrivilege 的 group,也就是說擁有這個權限的 process 或一些擁有這個權限的使用者被入侵時,攻擊者就可以取得這個權限。
- Administrators
- Local Service
- Network Service
- IIS AppPool Account
- Microsoft SQL Server Account
- Service
Previous Research
Windscribe
最一開始會挑 VPN 來研究是因為看到 Windscribe 的 CVE。CVE-2018-11334 是任何使用者權限的攻擊者都可以透過 windscribe service 的 named pipe 達到提權或 DoS;CVE-2018-11479 也是透過 windscribe service 的 named pipe,command injection 然後達到提權。
- CVE-2018-11334: Windscribe 1.81 creates a named pipe with a NULL DACL that allows Everyone users to gain privileges or cause a denial of service via \.\pipe\WindscribeService.
- CVE-2018-11479: The VPN component in Windscribe 1.81 uses the OpenVPN client for connections. Also, it creates a WindScribeService.exe system process that establishes a \.\pipe\WindscribeService named pipe endpoint that allows the Windscribe VPN process to connect and execute an OpenVPN process or other processes (like taskkill, etc.). There is no validation of the program name before constructing the lpCommandLine argument for a CreateProcess call. An attacker can run any malicious process with SYSTEM privileges through this named pipe.
CyberGhost
CyberGhost 相關的 CVE 是 CVE-2023-30237。參考 Bullied by Bugcrowd over Kape CyberGhost disclosure 得知,這個漏洞是利用 CyberGhost service 的 named pipe 造成 command injection 達到提權。
- CVE-2023-30237: CyberGhostVPN Windows Client before v8.3.10.10015 was discovered to contain a DLL injection vulnerability via the component Dashboard.exe.
OpenVPN
OpenVPN 相關的漏洞是今年 blackhat US 的一個講題 OVPNX: 4 Zero-Days Leading to RCE, LPE and KCE (via BYOVD) Affecting Millions of OpenVPN Endpoints Across the Globe,這是微軟的研究員投稿的,不過做這個研究時還沒有發表。有兩個漏洞,都是透過 OpenVPN 開啟的 named pipe。CVE-2024-27459 可以造成 buffer overflow 達到 crash;CVE-2024-24974 則是可以遠端開啟 OpenVPN process。
- CVE-2024-27459: When reading message from the pipe, we first peek the pipe to get the size of the message waiting to be read and then read the message. A compromised OpenVPN process could send an excessively large message, which would result in a stack-allocated message buffer overflow.
- CVE-2024-24974: If an attacker manages to get credentials for a user which is the member of "OpenVPN Administrators" group on a victim machine, an attacker might be able to communicate with the privileged interactive service on a victim machine and start openvpn processes remotely.
Method
分析遇到的難題
在研究的過程中遇到了幾個難題:
- 假設一個軟體 code base 很大,要怎麼找到程式的哪一塊程式碼讀寫了 named pipe buffer?如果單純用 debugger 在 ReadFile、WriteFile 等等 API 下斷點,因為跟檔案操作太相似,會分辨不出是在讀寫 named pipe 還是一般的檔案。
- 假設一個軟體的 named pipe server 有用 GetNamedPipeClientProcessId 檢查 named pipe client 是不是合法的 image,攻擊者怎麼繞過?
- 最後是怎麼自動化的測試一個軟體是否可能有 impersonation 的漏洞?
NamedPipeMaster
為了解決上述問題,實作了一個工具,名為 NamedPipeMaster,它包含以下功能:
- 直接跟目標 process 的 named pipe 互動
- 透過 dll injection 注入到目標 process 中監控 named pipe 的操作
- 用 minifilter driver 監控整個系統的 named pipe 行為
主動跟目標 Process 互動
- 主動當 named pipe client 連上其他 named pipe server
- 被動的當 named pipe server 等待其他 named pipe client 的連接
- 透過注入 dll 到另一個 process,然後從另一個 process 當作 named pipe client 去連其他 named pipe server
注入 DLL 到目標 Process
在目標 process 中 hook 一些跟 named pipe 相關的 function:
- hook NtCreateNamedPipeFile 監控 named pipe 的建立
- hook NtCreateFile 監控連接 named pipe 的行為
- hook NtFsControlFile 監控 named pipe 被連接
- hook NtReadFile 監控從 named pipe 讀資料的操作
- hook NtWriteFile 監控對 named pipe 寫資料的操作
另外也可以在這些 hook function 中把 call stack 印出來,也能用 GetFileType 來確認一個 file handle 是不是 named pipe handle,而且還可以測試目標 named pipe handle 能否被 impersonate。
Minifilter Driver
它能做到的事跟 dll injection 很像,不同的是因為它是 kernel driver,所以整個系統的 named pipe 操作都可以監控,而不限於被注入 dll 的 process。在 minifilter driver 中,可以對 IRP 設置 callback 進行監控,從中取得需要的資訊。
- 在 IRP_MJ_CREATE_NAMED_PIPE 的 callback 中監控 named pipe 的建立
- 在 IRP_MJ_CREATE 的 callback 中監控連接 named pipe 的行為
- 在 IRP_MJ_FILE_SYSTEM_CONTROL 的 callback 中監控 named pipe 被連接
- 在 IRP_MJ_READ 的 callback 中監控從 named pipe 讀資料的操作
- 在 IRP_MJ_WRITE 的 callback 中監控對 named pipe 寫資料的操作
Vulnerabilities
Windscribe Vuln
named pipe 類型的漏洞很常見的形式是有個高權限的 service 當作 named pipe server,這裡是 WindscribeService.exe;還有一個低權限的 process 當作 named pipe client,這裡是 Windscribe.exe。兩個 process 之間用 named pipe 溝通,named pipe 名稱為 WindscribeService。
用 accesschk 工具確認這個 named pipe 的存取權限會發現任何使用者,包含 guests 都能讀寫這個 named pipe,意思是擁有任何權限攻擊者都可以透過 named pipe 跟 WindscribeService.exe 溝通。
\\.\Pipe\WindscribeService
RW BUILTIN\Guests
RW NT AUTHORITY\Authenticated Users
RW BUILTIN\Administrators
Windscribe 的 named pipe server 在 named pipe client 連上來時會用 GetNamedPipeClientProcessId 取得攻擊者的 process id,然後對回 image path 找到攻擊者的執行檔,驗證執行檔的簽章是不是 Windscribe 的簽章。
要繞過針對執行檔的簽章檢查,只要自己開啟一個 Windscribe.exe,然後注入 dll,讓這個 dll 與 WindscribeService 建立 named pipe 連線就好。
Vuln1
身為 named pipe server 的 WindscribeService.exe 會接收來自 named pipe client 的指令,根據指令內容做不同的事情。因為 WindscribeService.exe 是高權限的 process,所以收到指令後做的任何操作也都跑在高權限。其中一個指令叫做 COMMAND_START_WIREGUARD,參數給 exeName 和 configFile。named pipe client 要把兩個參數用
boost::archive::text_oarchive
包起來,傳給 named pipe server。有漏洞的程式碼如下。第一區塊就是把執行檔的名稱加個 exe 而已,第二區塊把 Windscribe 的路徑接上使用者輸入的 exeName,再接上 configFile,變成一個指令,最後用 installService 執行這個指令。
繞過方式:
這是個 directory traversal 漏洞,把 exeName 的執行檔名前面加上
..\..\..\
就可以繞過程式給定的路徑,然後攻擊者就可以成功透過這個功能安裝任意的高權限 service。exeName_ = exeName + L".exe";
// ......
stream << L"\"" << Utils::getExePath() << L"\\" << exeName_ << "\" \"" << configFile << L"\"";
serviceCmdLine = stream.str();
// ......
svcCtrl.installService(serviceName_.c_str(), serviceCmdLine.c_str(),
L"Windscribe Wireguard Tunnel", L"Manages the Windscribe WireGuard tunnel connection",
SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, L"Nsi\0TcpIp\0", true);
Vuln2
第二個漏洞是另一個指令 CMD_TASK_KILL,輸入一個 exeName 的參數。這個漏洞就比較單純一些,程式就是會用 taskkill 關閉指定的 exeName 的 process,利用這個漏洞攻擊者可以用高權限關閉任意 process。
std::wstring killCmd = Utils::getSystemDir() + L"\\taskkill.exe /f /t /im " + cmdTaskKill.szExecutableName;
CyberGhost Vuln
跟 Windscribe 類似,CyberGhost 也是有個高權限的 service 當 named pipe server,和一個低權限的 process 當 named pipe client。
named pipe 名稱為
<hostname>CyberGhost8Service
,用 accesschk 查看,會發現任何使用者都可以對這個 named pipe 讀寫。\\.\Pipe\<hostname>CyberGhost8Service
RW NT AUTHORITY\Authenticated Users
RW BUILTIN\Administrators
跟 windscribe 類似,CyberGhost 也有做 image check,確認 named pipe client 的 image path 是不是在白名單中。所以攻擊者也同樣可以自己開啟 Dashboard.exe 的 process 然後透過注入 dll 跟 named pipe server 溝通。
Vuln1
CyberGhost 的溝通方式也是讓 named pipe client 傳送指令,named pipe server 接收到指令後做相對應的操作。其中一個指令叫 SetPeLauncherState,參數給一個 ExecutableName,然後用 JsonSerializer 包起來送給 named pipe server。
程式中可以看到它準備寫入 registry
Image File Execution Options
。在這個 registry 中加入 subkey,名稱是一個執行檔名稱,然後在建好的 subkey 中設定名為 debugger
的 value,這樣一來當下次執行這個執行檔名稱的 process 時,系統就會改成執行 debugger
的 data 所指定的執行檔。這邊的漏洞在於攻擊者可以控制 subkey 要填入的執行檔名稱,雖然控制不了 debugger 的值,但是也可以做到讓系統沒辦法執行特定的程式。
using (RegistryKey registryKey2 = registryKey.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options", RegistryKeyPermissionCheck.ReadWriteSubTree));
// ......
RegistryKey registryKey3 = registryKey2.CreateSubKey(peImageName, RegistryKeyPermissionCheck.ReadWriteSubTree);
// ......
registryKey3.SetValue("debugger", debuggerExecuteable);
// ......
Vuln2
第二個漏洞就單純很多,是一個叫做 LockInternetConnection 的指令,不用給任何參數。看名稱能猜到它可以讓系統斷網,所以攻擊者可以用低權限的使用者阻止整個系統連上網路,這算是一個 broken access control。
OpenVPN Vuln
最後是 OpenVPN,整個 OpenVPN 執行起來有很多 process,但這邊就列出兩個跟漏洞相關的 process。ovpnhelper_service.exe 是 named pipe server,OpenVPNConnect.exe 是 named pipe client,named pipe 名稱為
ovpnhelper_service
。named pipe client 在用 CreateFile 連上 named pipe server 時有設定 SECURITY_IMPERSONATION,所以 named pipe server 有 SeImpersonatePrivilege 就可以 impersonate,用 named pipe client 的權限做其他事。
但是攻擊者可以在這個情況下可以假冒自己是 named pipe server,建立跟 ovpnhelper_service.exe 相同的 named pipe 名稱,騙 openvpn 的 named pipe client 連上來。攻擊者只要擁有 SeImpersonatePrivilege,就可以用 openvpn 的 named pipe client 的權限做任何事。如果這個 named pipe client 在 Administrators group 中的話,攻擊者能藉此達成提權。
Fix
Windscribe Vuln1 Fix
原本 Windscribe 的漏洞是因為攻擊者可以控制 exeName 繞過程式指定的路徑達到提權。
現在它不讓使用者指定參數,而是直接寫死原本的兩個參數。因為原本功能就是要執行 wireguard,所以把原本 exeName 固定為 WireGuardService.exe,configFile 固定為 WindscribeWireguard.conf。
Windscribe Vuln2 Fix
原本 windscribe 的
AA_CMD_TASK_KILL
指令可以指定任意 exeName 造成攻擊者關閉任意 process,現在把 exeName 固定成 windscribeopenvpn.exe。OpenVPN Vuln Fix
OpenVPN 的漏洞原本是攻擊者可以用低權限的 process 建立同名的 named pipe,騙 OpenVPN 的 named pipe client 連上來,然後再 impersonate 它。
所以首先要防禦的地方是在 OpenVPN 的 service 建立 named pipe 時,設定這個 named pipe 的 ACL (Access Control List),限制只有高權限的使用者才能建立同名的 named pipe。
不過這樣還有個問題是假如 OpenVPN 的 service crash 了,或者攻擊者比 OpenVPN 的 service 更早建立這個名稱的 named pipe 怎麼辦?
所以要有另一個檢查機制,就是確認用 QueryServiceStatus 取得的 OpenVPN 的 service 的 pid 和用 GetNamedPipeServerProcessId 取得的 pid 是否相同,都一樣的話才讓 named pipe server 來 impersonate。
Report
Report Windscribe
- 2024/02/12 把提權漏洞回報給 ZDI
- 2024/04/19 把任意 kill process 漏洞回報給 Windscribe
- 2024/04/20 Windscribe Review
- 2024/04/30 ZDI Review
- 2024/05/15 在 v2.10.10-alpha 修正
- 2024/06/20 CVE-2024-6141 發布
Report CyberGhost
2024/04/19 回報當天被標註為 duplicate
Report OpenVPN
- 2024/04/28 把漏洞回報給 OpenVPN
- 2024/04/28 ~ 2024/05/09 跟 OpenVPN 的成員討論如何修補漏洞
- 2024/05/15 指定漏洞編號 CVE-2024-4877
- 2024/05/23 漏洞修補
- 2024/06/20 新版本與 CVE-2024-4877 發布
Conclusion
在這個研究中,介紹了 named pipe 的運作和 impersonation 的機制,並且透過注入 dll 來 hook API 和 minifilter driver 更有效率的分析 named pipe。從三個 VPN 的 named pipe 的漏洞理解 named pipe 的攻擊面以及如何更安全的實作 named pipe。