Hunting & Detecting SMB Named Pipe Pivoting (Lateral Movement)
With SMB traffic being ubiquitous in enterprise networks, adversaries and Offensive Security Tools can abuse pivoting over SMB named pipes to achieve lateral movement and for pivoting C2 traffic. Named Pipes are primarily used for local processes to communicate with each other, but can also facilitate communication between two processes on separate hosts, over Microsoft SMB Protocol.
For the above reasons, pretty much all popular C2 frameworks like Cobalt Strike, Brute Ratel, Sliver, Metasploit etc implement this technique.
In this primer, we’ll see how a combination of various data sources (endpoint & network) and system utilities can aid in detection, hunting and analysis of SMB lateral movement that leverages remotely accessible named pipes.
The techniques described here should largely be framework agnostic, as the underlying mechanics of SMB Named Pipe communication and their resulting behavior would be similar across the multitude of C2 frameworks being used in the wild.
Why Pivoting?
Once you compromise an internal host, you can then use the session obtained on that host to use that as a pivot, and relay traffic to the final target machine that you want to access. In addition to aiding lateral movement this technique:
- Allows for stealth in cases where egress to internet infrastructure is not expected from a target host (Domain Controller connecting to Internet over 445 is strange, but expected when it’s towards internal workstations or servers)
- Help with pivoting C2 traffic on highly restricted subnet that cannot route traffic directly to the internet.
- A pivot host can support multiple pivot sessions and listeners and thereby reduce the number of individual egress connections to attacker infrastructure — This can be useful as defenders tend to prioritize scrutiny of egress traffic, rather than what’s happening on their internal network traffic.
Below is a visual representation of how pivoting works.
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
It’s very similar to client/server architecture as notions such as a named pipe server
and a named pipe client
exist. The client and server terminology can be confusing here, but a client and server in a pipe connection can reside on the same host (like the example above) or on remote hosts. The client is just the process initiating the connection to the server process, which created the 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
).
Speaking of remote named pipes, they feature in the popular Sysinternals PsExec utility. This named pipe — \psexesvc
is what allows for convenient input/output redirection back to the system that launched PsExec.
C:\Users\ankith\Desktop>net file
ID Path User name # Locks
-------------------------------------------------------------------------------
166 \PSEXESVC ankith 0
Named Pipes can also be abused for privilege escalation to SYSTEM, via a technique called “Named Pipe Token Impersonation”. Refer to my previous blog post that goes over this technique:
Pivoting via Named Pipes
We’ll now make use of Bishop Fox’s Sliver C2 framework to demonstrate this technique and hopefully to generate relevant attack telemetry for detection and hunt prototyping. Here’s a basic getting started guide to Sliver — Getting Started, if you haven’t dabbled with it yet.
Below is a high level overview of the steps involved:
- A named pipe implant is generated on the attack machine (A) (or elsewhere) to be transferred and executed on the intended target machine (C):
> generate --named-pipe 192.168.1.4/pipe/foobar
2. A named pipe listener (foobar) is started on the pivot machine (B) for the implant (C) to connect back via an SMB session:
> pivots named-pipe --bind foobar
pivots
ID Protocol Bind Address Number Of Pivots
==== ============ ================= ==================
1 Named Pipe \\.\pipe\foobar 0
3. Once the implant is executed on the target (C) (WMI or PsExec can be used for this purpose), the attack machine (A) will receive a session via the pivot host (B):
> sessions
ID Transport Remote Address Hostname Username Operating System Health
========== =========== ================================== ================= ====================== ================== =========
908768f2 pivot 192.168.1.4:1552->MODERN_BRIEF-> DESKTOP-1SQV2LH ankit windows/amd64 [ALIVE]
If you’d like to just test remote pipe connection establishment without having to setup Pivoting, then the following Powershell script invoke-pipeshell can also be used. This generates similar events like what Sliver and other C2 frameworks would generate.
Hunting and Detection
We’ll primarily use Sysmon logs to conduct our Hunts and Detection prototyping. We’ll also leverage certain system utilities and Sysinternal tools to conclusively ascertain if remotely accessible named pipes were involved (net file and PsFile).
We’ll be using “Pipe Creation” and “Pipe Connected” Sysmon events, which may not always be enabled. The below XML config snippet allows for all Pipe related events to be recorded.
<!--SYSMON EVENT ID 17 & 18 : PIPE CREATED / PIPE CONNECTED [PipeEvent]-->
<!--EVENT 17: "Pipe Created"-->
<!--EVENT 18: "Pipe Connected"-->
<!--DATA: UtcTime, ProcessGuid, ProcessId, PipeName, Image-->
<RuleGroup name="" groupRelation="or">
<PipeEvent onmatch="exclude">
</PipeEvent>
</RuleGroup>
- Hunting Anomalous Named Pipe Creation Events
Sysmon captures named “Pipe creation” events under Event ID 17.
We can begin by looking for outliers in the pipe creation events by using basic stack counting. The malicious ones should be infrequent and would stand out, like we see in the screenshot below.
The below query checks for outliers by Process Name, by sorting their occurrences in ascending order. Another variation of this is to check for outliers by sorting distinct count of hosts — Although an event might occur once on a host, 1000s of other systems in a large environment might exhibit the same behavior, providing us a baseline to conclude such events as legitimate.
`sysmon` EventCode=17 EventType=CreatePipe ComputerName=Ankith-PC
| eval Event_Type=mvindex(EventType, 1)
| search NOT PipeName IN ("<Anonymous Pipe>")
| stats count values(PipeName) as PipeName, values(Event_Type) as Event_Type
by Image, ComputerName
| table ComputerName, Event_Type, Image, PipeName, count
| sort count
Pipe Created:
RuleName: -
EventType: CreatePipe
UtcTime: 2023-04-13 10:50:24.293
ProcessGuid: {ac6a4e42-de2b-6437-e1f9-000000006700}
ProcessId: 9720
PipeName: \suspicious_pipe
Image: C:\Users\ankith\Desktop\MODERN_BRIEF.exe
User: ANKITH-PC\ankith
Other criteria that can be used to further refine the data:
- Most legitimate pipe creation events are generated by known processes that are most likely to be digitally signed — Filter/Look for anomalous processes creating pipes that are not signed (like our unsigned Sliver implant).
Since we’re dealing with remotely accessible named pipes, a disadvantage of just relying on endpoint pipe creation events is that it’s not possible to ascertain if the pipes are communicating remotely. As we’ll see in later points, we’d need network traffic and other system utilities to confirm this fact. An advantage however is that this criteria also detects a common variation of named pipe token impersonation abuse.
Another point to keep in mind when using this hunt technique is — The process name is entirely dependent on the mechanism used to create named pipes. In our case we see the .exe file (Sliver Implant) as the Process Name, but this could very well be Powershell (via Powershell Script that can setup named pipe communications)(see below) or even a legitimate signed Windows binary if the adversary managed to perform prior Process Injection (see OpSec considerations section at the last).
Pipe Created:
RuleName: -
EventType: CreatePipe
UtcTime: 2023-04-13 15:41:26.822
ProcessGuid: {ac6a4e42-2278-6438-11b1-010000006700}
ProcessId: 6048
PipeName: \ankith-pipe
Image: C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe
User: ANKITH-PC\ankith
2. Detection via Grouping Net Conn and Pipe Connected Events
Sysmon can capture named “Pipe Connection” events (Event ID 18). The Network Connection events capture TCP/UDP connections (Event ID 3) — Our Application Layer SMB traffic would show up here under Pivot host’s port 445. In this detection we’ll attempt to group these two events.
Let’s first review the Pipe Connection events generated when the target (pipe client) connects to the named pipe on the pivot listener (pipe server). Such events seem to distinctively have SYSTEM as the Process Name, as shown below (it seems like when a pipe is being remotely accessed the Image field is set to SYSTEM). This is good, as we can use this as one of the criteria for our grouping.
Pipe Connected:
RuleName: -
EventType: ConnectPipe
UtcTime: 2023-04-17 17:04:58.563
ProcessGuid: {ac6a4e42-6f36-643d-eb03-000000000000}
ProcessId: 4
PipeName: \foobar
Image: System
User: NT AUTHORITY\SYSTEM
Below is the corresponding Network Connection event (for some reason my Src and Dest IPs field names were switched even though this event generated on the Src IP machine)
TaskCategory=Network connection detected (rule: NetworkConnect)
OpCode=Info
Message=Network connection detected:
RuleName: -
UtcTime: 2023-04-17 17:04:58.563
ProcessGuid: {AC6A4E42-F0DB-6436-EB03-000000000000}
ProcessId: 4
Image: System
User: NT AUTHORITY\SYSTEM
Protocol: tcp
Initiated: false
SourceIsIpv6: false
SourceIp: 192.168.1.2
SourceHostname: DESKTOP-1SQV2LH
SourcePort: 54910
SourcePortName: -
DestinationIsIpv6: false
DestinationIp: 192.168.1.10
DestinationHostname: Ankith-PC
DestinationPort: 445
DestinationPortName: microsoft-ds
Now we’ll group Pipe Connection with SMB Network Connection events. This allows us to zero in on named pipes that could be communicating remotely. The idea is, a pipe connection event and SMB network connection event will occur in conjunction with each other (say within a time span of 1 minute).
I’ll be using Splunk’s bucket command to group events by a time span of 1 minute:
`sysmon`
| bucket _time span=1m
| search ComputerName=Ankith-PC Image=SYSTEM EventCode=3 OR EventCode=18
(DestinationPort=445 AND DestinationIp=*) OR PipeName=*
| stats count values(PipeName) as PipeName, values(DestinationIp) as Dest_IP,
values(SourceIp) as Src_IP values(DestinationPort) as Dest_Port by _time
| search Src_IP=*, PipeName=*
| table Src_IP, Dest_IP, Dest_Port, PipeName
As seen above, this provides additional details like the Remote Target IP that initiated the SMB connection. This should be rare depending on your organization and may allow us to create high fidelity detections, as a result.
3. PCAP and Network Monitoring
SMB allows blocks of data to be written to or read from a remote resource. In the case of a named pipe, the data transmitted is read from and written to memory.
The following diagram demonstrates the steps taken by SMB to execute transactions over a named pipe using both individual reads and writes.
A Network Traffic Analyzer like Zeek can provide visibility into SMB traffic, similar to what we see in the above packet capture. The below snippet shows available fields that can be used for monitoring and investigations. Since named pipes are treated like files, they’ll show up in the name field (contains Filename values, but in this case - Named Pipes).
If remote named pipe communication is rare in your organization, this could act as trigger to investigate the origin of such anomalous pipes. Since Named Pipes don’t have file extensions, a regex could be created to filter normal file names.
These events can help further the investigation and analysis for our case, as it can help:
- Ascertain if remotely accessible named pipes were involved.
- Conclusively provide details of the compromised target host which connected to a malicious pipe.
4. Live System Analysis — net file command
The first two hunting and detection methods can aid in detecting creation/connection of anomalous named pipes but don’t provide conclusive evidence on whether remotely accessible named pipes were involved. This and the next point goes over how an analyst can ascertain if this was indeed the case, using live system analysis.
The net file command shows you a list of the files that other computers have opened on the system.
Since named pipes work a lot like files, this command can be used to enumerate named pipes on our pivot host (B).
C:\WINDOWS\system32>net file
ID Path User name # Locks
-------------------------------------------------------------
3 \foobar ankith 0
The command completed successfully.
We see our named pipe foobar in the output. Such open named pipes interacting with remote host are a rare occurrence, especially on end user type workstations and should be a trigger for further investigation.
5. Live System Analysis — PsFile Sysinternals Tool
PsFile is a Sysinternals command-line utility that shows a list of files on a system that are opened remotely. It is very similar to the net file command we used above.
C:\Users\ankith\Desktop\PSTools >psfile.exe
PsFile v1.04 - Lists files and directories opened remotely
Copyright (C) 2001-2023 Mark Russinovich
Sysinternals
Files opened remotely on ANKITH-PC:
[0] \foobar
User: ankith
Locks: 0
Access: Read Write
We see the foobar named pipe. We also see Access value as Read Write. This is because the pipe has Duplex access mode — The pipe is bi-directional; both server (pivot host) and client (target host) processes can read from and write to the pipe.
Opsec Considerations
Default Named Pipes
A lot of detections tend to utilize default pipe names as the detection criteria. For example, the below SPL pseudo-code alerts on Cobalt Strike’s default pipe names:
`sysmon` EventID=17 OR EventID=18 PipeName IN
(\\msagent_*, \\DserNamePipe*, \\srvsvc_*, \\postex_*, \\status_*,
\\MSSE-*, \\spoolss_*, \\win_svc*, \\ntsvcs*, \\winsock*, \\UIA_PIPE*)
An OpSec aware entity can easily bypass this, as most C2 frameworks provide the ability to set custom named pipe values.
Process Injection
An OpSec aware adversary can bypass process anomaly based named pipe detections, by first injecting into a legitimate process before creating the named pipe. For example, here’s a Pipe Creation event (demo_pipe) originating from a legitmate Windows binary — spoolsv.exe (Print Spooler Service). This process was injected with the implant payload, before pipe creation happened.
Pipe Created:
RuleName: -
EventType: CreatePipe
UtcTime: 2023-04-12 12:13:15.582
ProcessGuid: {ac6a4e42-42a7-6435-3b00-000000006500}
ProcessId: 2440
PipeName: \demo_pipe
Image: C:\WINDOWS\System32\spoolsv.exe
User: NT AUTHORITY\SYSTEM
References
Implementation of SMB Named Pipe pivoting by various Offensive tools
- Sliver — https://github.com/BishopFox/sliver/wiki/Pivots
- Cobalt Strike — https://www.cobaltstrike.com/blog/named-pipe-pivoting/
- Brute Ratel — https://bruteratel.com/tabs/badger/commands/pivot_smb/
- Metasploit — https://docs.metasploit.com/docs/using-metasploit/intermediate/pivoting-in-metasploit.html
- PoshC2 — https://github.com/nettitude/PoshC2/blob/master/resources/modules/Invoke-Pbind.ps1
MITRE TTPs