Detecting Named Pipe Token Impersonation Abuse — Windows PrivEsc

Ankith Bharadwaj
6 min readApr 5, 2023

--

Named Pipe Impersonation is a Windows feature that can be abused for privilege escalation to achieve local SYSTEM. Due to its privileges, the Windows NT AUTHORITY\SYSTEM account is a juicy target for adversaries across all versions of Windows operating systems.

This technique has been integrated into various offensive security tools like Cobalt Strike , Metasploit (getsystem command), PoshC2 etc, and is regularly employed by threat actors in the wild.

Named Pipes

Pipes are a form of inter-process communication (IPC) that allow separate processes to communicate without having been designed explicitly to work together. Below is a simple bash script that references a named pipe called my_pipe, to gzip compress file contents:

#!/bin/bash

mkfifo my_pipe # mkfifo() is a function to explicitly create named pipes
gzip -9 -c < my_pipe > out.gz & # gzip to compress things piped to it
cat my_file.txt > my_pipe # redirect file contents to named pipe

In Windows implementation, every pipe is placed in the root directory of the named pipe filesystem (NPFS), mounted under the special path \\.\pipe\ (that is, a pipe named "foo" would have a full path name of \\.\pipe\foo)

Impersonating Named Pipes to get SYSTEM

Impersonation is the ability of a thread to execute in a security context different from that of the process that owns the thread. A named pipe server thread can call the ImpersonateNamedPipeClient function to assume the access token of the user connected to the client end of the pipe. The client and server terminology can be confusing here, but quite often, a client and server in a pipe connection will reside on the same host. The client is just the process initiating the connection to the server process, which created the pipe.

The idea is to help perform activities based on the client’s privileges, since the server may have full access, but the client typically has more limited rights. As we’ll see below, this feature can be exploited by creating a pipe server with limited or low privileges and then attempting to connect a much more privileged client to that pipe server.

One of the ways tools like Cobalt Strike and Meterpreter abuses the above functionality is by creating a Windows Service to execute as NT Authority\SYSTEM (pipe client) and having it connect to a named pipe that is created by the malicious payload (pipe server).

Let’s see some code snippets of how this technique is implemented programmatically:

1. Create Named Pipe

Meterpreter (pipe server) creates a named pipe using CreateNamedPipe API. The mode is set to “PIPE_ACCESS_DUPLEX” — The pipe is bi-directional; both server and client processes can read from and write to the pipe.

It’s important to note that any process (in our case the Meterpreter payload) can open a new named pipe object, granted that one with the same name does not already exist, although the impersonation process requires the server process to hold the SeImpersonatePrivilege privilege. This is the reason attacker needs to have prior Administrator access.

// create the named pipe for the client service to connect to

hServerPipe = CreateNamedPipe( cpServicePipe, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL );

2. Create and Run Service and Connect to Named Pipe

A new Windows Service is created under local SYSTEM that executes cmd.exe (client). This is made to connect to Meterpreter’s named pipe that will allow us to impersonate the client.

_snprintf_s( cServicePipe, sizeof(cServicePipe), MAX_PATH, "\\\\.\\pipe\\%s", cpServiceName );

_snprintf_s( cServiceArgs, sizeof(cServiceArgs), MAX_PATH, "cmd.exe /c echo %s > %s", cpServiceName, cServicePipe );

if( service_create( cpServiceName, cServiceArgs ) != ERROR_SUCCESS )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_namedpipe. service_create failed" );
service_start( cpServiceName );

3. Impersonating the Client

Here we impersonate the client token by using ImpersonateNamedPipeClient API. The context of the client is SYSTEM, so when you impersonate it you become SYSTEM.

// impersonate the client!

if( !ImpersonateNamedPipeClient( hServerPipe ) )
CONTINUE_ON_ERROR( "[ELEVATE] elevate_namedpipe_thread. ImpersonateNamedPipeClient failed" );


// now we can set the meterpreters thread token to that of our system
// token so all subsequent meterpreter threads will use this token.
core_update_thread_token( remote, hToken );

getsystem Demo

Assuming we have initial access with Administrative shell on the victim, we run the getsystem command. We’ll explicitly choose technique 1, which is what’s described in this post.

Although there are several getsystem techniques ( a 6th one was added in 2022), the first one still remains the most commonly used.

meterpreter > getuid
Server username: ANKITH-PC\ankith

meterpreter > getsystem -h
Usage: getsystem [options]

Attempt to elevate your privilege to that of local system.

OPTIONS:

-h Help Banner.
-t <opt> The technique to use. (Default to '0').
0 : All techniques available
1 : Named Pipe Impersonation (In Memory/Admin)
2 : Named Pipe Impersonation (Dropper/Admin)
3 : Token Duplication (In Memory/Admin)
4 : Named Pipe Impersonation (RPCSS variant)

meterpreter > getsystem -t 1
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Running getuid, shows we are running as SYSTEM.

Detections & Hunting

We’ll use Sysmon logs to identify various criterias on which detections can be crafted:

  1. Process Monitoring

The below characteristic is common on both Cobalt Strike Beacon and Meterpreter, when getsystem (using Named Pipe Impersonation) is attempted.

a) With process monitoring we can create detections with the following process names and cmdline criteria:

  • Parent Process: services.exe
  • Process Name: cmd.exe
  • CommandLine: Contains “echo” and “\pipe\”

This detection is applicable to other C2 frameworks as well, like Empire and PoshC2 (Get-System.ps1) as they are a inspired by the getsystem command:

cmd.exe /C start %COMSPEC% /C `"timeout /t 3 >nul&&
echo TestSVC > \\.\pipe\TestSVC`

b) Another detection can be to alert on cmd.exe being run with SYSTEM privileges:

  • Process Name: cmd.exe
  • User: NT AUTHORITY\SYSTEM
Process Create (Event ID 1)
Process Create:
RuleName: -
UtcTime: 2023-04-04 11:32:18.400
ProcessGuid: {ac6a4e42-0ac2-642c-8801-000000006700}
ProcessId: 64
Image: C:\Windows\System32\cmd.exe
FileVersion: 10.0.17134.1 (WinBuild.160101.0800)
Description: Windows Command Processor
Product: Microsoft® Windows® Operating System
Company: Microsoft Corporation
OriginalFileName: Cmd.Exe
CommandLine: cmd.exe /c echo jqrwnk > \\.\pipe\jqrwnk
CurrentDirectory: C:\WINDOWS\system32\
User: NT AUTHORITY\SYSTEM
LogonGuid: {ac6a4e42-359e-642b-e703-000000000000}
LogonId: 0x3E7
TerminalSessionId: 0
IntegrityLevel: System
Hashes: MD5=4E2ACF4F8A396486AB4268C94A6A245F,SHA256=9A7C58BD98D70631AA1473F7B57B426DB367D72429A5455B433A05EE251F3236,IMPHASH=8542FB14699D84D7E8DA92F66145C7FE
ParentProcessGuid: {ac6a4e42-359e-642b-0b00-000000006700}
ParentProcessId: 624
ParentImage: C:\Windows\System32\services.exe
ParentCommandLine: C:\WINDOWS\system32\services.exe
ParentUser: NT AUTHORITY\SYSTEM

2. Named “Pipe Creation” & “Pipe Connected” Events

Sysmon can capture named “Pipe creation” and “Pipe connected” events (Event ID 17 and Event ID 18).

a) New named pipes being created by anomalous process (in this case the .tmp Meterpreter payload) can be used for alerting. Similarly, previous pipe creations can be profiled during a hunt exercise.

Pipe Created (Event ID 17)
Pipe Created:
RuleName: -
EventType: CreatePipe
UtcTime: 2023-04-04 13:17:24.604
ProcessGuid: {ac6a4e42-2319-642c-3803-000000006700}
ProcessId: 9092
PipeName: \vxmvoe
Image: C:\WINDOWS\Installer\MSI13BD.tmp
User: ANKITH-PC\ankith

b) cmd.exe running as SYSTEM, and connecting to named pipes, could be another related detection:

  • Pipe Name: *
  • Process Name: cmd.exe
  • User: NT AUTHORITY\SYSTEM
Pipe Connected (Event ID 18)
Pipe Connected:
RuleName: -
EventType: ConnectPipe
UtcTime: 2023-04-04 13:17:24.604
ProcessGuid: {ac6a4e42-2364-642c-3903-000000006700}
ProcessId: 7788
PipeName: \vxmvoe
Image: C:\WINDOWS\system32\cmd.exe
User: NT AUTHORITY\SYSTEM

3. Windows Services through Registry

The HKLM\SYSTEM\CurrentControlSet\Services registry tree stores information about each service on the system. The registry “Data” field can be monitored for mentions of “\pipe\” as seen below

  • Image: services.exe
  • Registry Value Name: ImagePath
  • Registry Value Data: Contains “echo” and “\pipe\”
Registry Value Set (Event ID 13)
Registry value set:
RuleName: T1031,T1050
EventType: SetValue
UtcTime: 2023-04-04 13:17:24.604
ProcessGuid: {ac6a4e42-359e-642b-0b00-000000006700}
ProcessId: 624
Image: C:\WINDOWS\system32\services.exe
TargetObject: HKLM\System\CurrentControlSet\Services\vxmvoe\ImagePath
Details: cmd.exe /c echo vxmvoe > \\.\pipe\vxmvoe
User: NT AUTHORITY\SYSTEM

References

--

--