Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

Windows Privilege Escalation — Communication with Processes

One of the best places to look for privilege escalation is the processes running on the system. Even if a process isn’t running as an administrator, it may lead to additional privileges. The most common example is discovering a web server like IIS or XAMPP running on the box, placing an aspx/php shell on it, and gaining a shell as the user running the web server. Generally this isn’t an administrator, but it will often have the SeImpersonatePrivilege token, allowing for Rogue/Juicy/Lonely Potato to provide SYSTEM permissions.

Access Tokens

Access tokens describe the security context (security attributes/rules) of a process or thread, including the user account’s identity and privileges. When a user authenticates, their password is verified against a security database, and if authentication succeeds they’re assigned an access token. Every time a user interacts with a process, a copy of this token is presented to determine their privilege level.

Enumerating Network Services

The most common way processes are interacted with is through a network socket (DNS, HTTP, SMB, etc.). netstat displays active TCP/UDP connections, giving a clearer picture of what’s listening on which port(s), both locally and externally accessible. A vulnerable service that’s only accessible to localhost (when logged on to the host) can still be exploited for privesc.

Display Active Network Connections

C:\htb> netstat -ano

Focus on entries listening on loopback addresses (127.0.0.1 and ::1) rather than the host IP or broadcast (0.0.0.0, ::/0). Localhost-bound sockets are often left insecure under the assumption “they aren’t accessible to the network.” A classic example: port 14147, used by FileZilla’s administrative interface. Connecting to it may allow extracting FTP passwords or creating an FTP share at c:\ as the FileZilla Server user (potentially Administrator).

More Examples

  • Splunk Universal Forwarder — installed on endpoints to send logs into Splunk. Its default configuration had no authentication, allowing anyone to deploy applications (leading to code execution), and ran as SYSTEM rather than a low-privilege user. See Splunk Universal Forwarder Hijacking and SplunkWhisperer2.
  • Erlang Port (25672) — Erlang is built around distributed computing; nodes join a cluster using a shared secret called a cookie. Many Erlang-based apps (RabbitMQ, SolarWinds, CouchDB) use a weak default cookie (e.g., RabbitMQ’s rabbit) or store the cookie in a poorly protected config file. See Mubix’s Erlang-arce blog post.

Named Pipes

Processes also communicate through Named Pipes — files stored in memory that are cleared out after being read. Cobalt Strike uses named pipes for every command (excluding BOFs):

  1. Beacon starts a named pipe, e.g. \\.\pipe\msagent_12.
  2. Beacon starts a new process and injects a command into it, directing output to \\.\pipe\msagent_12.
  3. The server displays what was written into the pipe.

This design means a flagged/crashed command doesn’t affect the beacon process itself. Operators often rename pipes to masquerade as legitimate software (e.g., mojo instead of msagent, mimicking Chrome). A named pipe prefixed mojo on a host without Chrome installed is a strong IOC — in one case, it turned out to be the company’s internal red team (an external consultant finding the red team before the blue team did speaks volumes).

More on Named Pipes

Pipes enable communication between two applications/processes via shared memory. There are two types:

  • Named pipes — e.g., \\.\PipeName\ExampleNamedPipeServer.
  • Anonymous pipes.

Windows uses a client-server model: the process that creates the pipe is the server, and the process communicating with it is the client. Communication can be:

  • Half-duplex — one-way; the client can only write to the server.
  • Duplex — two-way; the client writes and the server responds over the same pipe.

A named pipe may have multiple simultaneous instances — each client connection creates a new instance sharing the same pipe name but with its own independent data buffer.

Listing Named Pipes with PipeList

C:\htb> pipelist.exe /accepteula

Listing Named Pipes with PowerShell

PS C:\htb> gci \\.\pipe\

Reviewing Named Pipe Permissions with AccessChk

After enumerating named pipes, use AccessChk to review the Discretionary Access List (DACL) for a specific pipe — showing who has modify/write/read/execute permissions on it. Review all named pipe DACLs at once with .\accesschk.exe /accepteula \pipe\.

C:\htb> accesschk.exe /accepteula \\.\Pipe\lsass -v

For LSASS, only BUILTIN\Administrators should have FILE_ALL_ACCESS — everyone/anonymous logon are limited to read/write of specific attributes, not full control.

Named Pipes Attack Example — WindscribeService

Search for all named pipes with write access granted broadly:

C:\htb> accesschk.exe -w \pipe\* -v

The WindscribeService Named Pipe Privilege Escalation is a good real-world example — WindscribeService’s pipe granted Everyone (all authenticated users) FILE_ALL_ACCESS:

C:\htb> accesschk.exe -accepteula -w \pipe\WindscribeService -v
\\.\Pipe\WindscribeService
  Medium Mandatory Level (Default) [No-Write-Up]
  RW Everyone
        FILE_ALL_ACCESS

With FILE_ALL_ACCESS granted to Everyone, any authenticated user can interact with the privileged service via its pipe — this lax permission can be leveraged to escalate privileges to SYSTEM.

Key Takeaways

  • Processes are a prime privesc target even without admin rights — a web server shell (IIS/XAMPP) often carries SeImpersonatePrivilege, enabling Potato-family exploits to SYSTEM.
  • netstat -ano surfaces services; prioritize ports bound to loopback only (127.0.0.1/::1) over the host IP/broadcast — they’re frequently left unauthenticated (e.g., FileZilla admin on 14147).
  • Third-party agents (Splunk Universal Forwarder, Erlang-based apps like RabbitMQ/SolarWinds/CouchDB via port 25672) are common unauthenticated-SYSTEM-service privesc vectors.
  • Named pipes (\\.\pipe\...) are another cross-process IPC channel; enumerate with pipelist.exe or PowerShell gci \\.\pipe\, then audit DACLs with accesschk.exe.
  • accesschk.exe -w \pipe\* -v finds pipes with broad write access — Everyone/FILE_ALL_ACCESS on a privileged service’s pipe (e.g., WindscribeService) can be abused for SYSTEM-level privesc.