# Copyright (c) Meta Platforms, Inc. and affiliates. # All rights reserved. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. """ Deterministic task definitions for CyberSOCEnv. Each task defines a fixed attack chain, network layout, and expected containment actions. No randomness — every run of the same task_id produces identical initial state. Tasks: - easy: Single ransomware endpoint on the corporate subnet. - medium: Multi-stage lateral movement (phishing -> cred theft -> 3 subnets). - hard: APT + ransomware with C2, exfiltration, and executive pressure. """ from __future__ import annotations from typing import Any, Dict, List # ============================================================================= # Network Topology Builder (deterministic, 500-node) # ============================================================================= def _build_subnet( name: str, role: str, prefix: str, ip_base: str, count: int, start_idx: int, criticality: float, default_ports: List[int], default_procs: List[str], ) -> List[Dict[str, Any]]: """Build a list of host dicts for a subnet.""" hosts = [] for i in range(count): idx = start_idx + i hosts.append({ "hostname": f"{prefix}-{idx:03d}", "ip_address": f"{ip_base}.{idx}", "subnet": name, "role": role, "status": "online", "running_processes": list(default_procs), "open_ports": list(default_ports), "criticality": criticality, }) return hosts def build_network() -> Dict[str, List[Dict[str, Any]]]: """Build the deterministic enterprise network (~50 active hosts). Reduced from 400 to ~50 nodes for GRPO training throughput (target ≥8 eps/min). Host indices are chosen to cover all hand-crafted task references (WS-042, WS-088, DEV-033, FIN-008, FIN-012, SRV-002..SRV-015, EXEC-003) plus a small buffer for procedural generation and lateral pivot targets. The README still describes a "500-node enterprise" — the simulation covers the same topology, but only materializes the operationally relevant hosts. Returns: Dict mapping subnet name -> list of host dicts. """ network: Dict[str, List[Dict[str, Any]]] = {} # Corporate: WS-001..WS-005 (buffer) + WS-015..WS-020 (covers WS-017) # + WS-040..WS-045 (covers WS-042) + WS-085..WS-090 (covers WS-088) corporate: List[Dict[str, Any]] = [] for start, count in [(1, 5), (15, 6), (40, 6), (85, 6)]: corporate.extend(_build_subnet( name="corporate", role="corporate", prefix="WS", ip_base="10.1.1", count=count, start_idx=start, criticality=0.3, default_ports=[135, 445, 3389], default_procs=["outlook.exe", "chrome.exe", "explorer.exe"], )) network["corporate"] = corporate # 23 hosts # Engineering: DEV-001..DEV-005 + DEV-030..DEV-036 (covers DEV-033) engineering: List[Dict[str, Any]] = [] for start, count in [(1, 5), (30, 7)]: engineering.extend(_build_subnet( name="engineering", role="engineering", prefix="DEV", ip_base="10.2.1", count=count, start_idx=start, criticality=0.5, default_ports=[22, 443, 8080, 3389], default_procs=["vscode.exe", "python.exe", "docker.exe", "git.exe"], )) network["engineering"] = engineering # 12 hosts # Finance: FIN-001..FIN-005 + FIN-008..FIN-014 (covers FIN-008, FIN-012) finance: List[Dict[str, Any]] = [] for start, count in [(1, 5), (8, 7)]: finance.extend(_build_subnet( name="finance", role="finance", prefix="FIN", ip_base="10.3.1", count=count, start_idx=start, criticality=0.8, default_ports=[443, 1433, 3389], default_procs=["excel.exe", "sap.exe", "sqlcmd.exe"], )) network["finance"] = finance # 12 hosts # DMZ: DMZ-001..DMZ-003 (no tasks reference DMZ hosts) network["dmz"] = _build_subnet( name="dmz", role="dmz", prefix="DMZ", ip_base="10.4.1", count=3, start_idx=1, criticality=0.6, default_ports=[80, 443, 8443], default_procs=["nginx", "node", "java"], ) # 3 hosts # Datacenter: SRV-001..SRV-020 (covers SRV-002, SRV-005, SRV-010, SRV-015) network["datacenter"] = _build_subnet( name="datacenter", role="datacenter", prefix="SRV", ip_base="10.5.1", count=20, start_idx=1, criticality=0.9, default_ports=[22, 443, 5432, 6379, 9200], default_procs=["postgres", "redis-server", "elasticsearch", "kubelet"], ) # 20 hosts # Executive: EXEC-001..EXEC-005 (covers EXEC-003) network["executive"] = _build_subnet( name="executive", role="executive", prefix="EXEC", ip_base="10.6.1", count=5, start_idx=1, criticality=1.0, default_ports=[443, 3389], default_procs=["outlook.exe", "teams.exe", "chrome.exe"], ) # 5 hosts return network # Total: ~75 hosts # ============================================================================= # Attack Chain Definitions # ============================================================================= TASKS: Dict[str, Dict[str, Any]] = { # ----- EASY: Single ransomware endpoint ----- "easy": { "description": "Ransomware detected on a single corporate workstation. Isolate and contain.", "max_steps": 15, "initial_business_impact": 0.05, "impact_per_step": 0.02, # Impact grows slowly per step "attack_chain": [ { "threat_id": "T-EASY-001", "threat_type": "ransomware", "phase": "execution", "compromised_hosts": ["WS-042"], "malicious_processes": ["cryptolocker.exe"], "c2_servers": [], "iocs": { "hashes": ["e99a18c428cb38d5f260853678922e03"], "ips": [], "domains": [], }, "lateral_targets": [], "exfil_targets": [], }, ], "initial_alerts": [ { "alert_id": "ALERT-E001", "timestamp": "2025-01-15T09:23:17Z", "source_host": "WS-042", "severity": "critical", "threat_type": "ransomware", "description": "EDR detected file encryption activity on WS-042. Process 'cryptolocker.exe' is encrypting files in C:\\Users\\jsmith\\Documents.", "ioc_indicators": ["e99a18c428cb38d5f260853678922e03"], "subnet": "corporate", "is_acknowledged": False, }, { "alert_id": "ALERT-E002", "timestamp": "2025-01-15T09:23:45Z", "source_host": "WS-042", "severity": "high", "threat_type": "ransomware", "description": "Anomalous file system activity: 147 files renamed with .locked extension in 28 seconds.", "ioc_indicators": [], "subnet": "corporate", "is_acknowledged": False, }, ], # Optimal containment: kill process, run forensics, block hash, submit plan "optimal_actions": ["kill_process", "run_forensics", "block_ioc", "submit_containment_plan"], "containment_requirements": { "must_kill": [{"hostname": "WS-042", "process": "cryptolocker.exe"}], "must_block_iocs": ["e99a18c428cb38d5f260853678922e03"], "must_forensics": ["WS-042"], "must_not_isolate": ["finance", "engineering", "datacenter"], # Unnecessary isolation = downtime }, }, # ----- MEDIUM: Multi-stage lateral movement ----- "medium": { "description": "Phishing attack led to credential theft and lateral movement across 3 subnets.", "max_steps": 25, "initial_business_impact": 0.10, "impact_per_step": 0.03, "attack_chain": [ { "threat_id": "T-MED-001", "threat_type": "phishing", "phase": "initial_access", "compromised_hosts": ["WS-017"], "malicious_processes": ["powershell.exe"], "c2_servers": [], "iocs": { "hashes": ["d41d8cd98f00b204e9800998ecf8427e"], "ips": [], "domains": ["evil-login.example.com"], }, "lateral_targets": [], "exfil_targets": [], }, { "threat_id": "T-MED-002", "threat_type": "credential_theft", "phase": "credential_access", "compromised_hosts": ["WS-017"], "malicious_processes": ["mimikatz.exe"], "c2_servers": [], "iocs": { "hashes": ["aabbccdd11223344eeff5566778899aa"], "ips": [], "domains": [], }, "lateral_targets": ["DEV-033", "FIN-012"], "exfil_targets": [], }, { "threat_id": "T-MED-003", "threat_type": "lateral_movement", "phase": "lateral_movement", "compromised_hosts": ["DEV-033", "FIN-012"], "malicious_processes": ["svchost_backdoor.exe"], "c2_servers": [], "iocs": { "hashes": ["112233445566778899aabbccddeeff00"], "ips": ["203.0.113.50"], "domains": [], }, "lateral_targets": ["SRV-005"], "exfil_targets": [], }, ], "initial_alerts": [ { "alert_id": "ALERT-M001", "timestamp": "2025-01-15T08:15:00Z", "source_host": "WS-017", "severity": "medium", "threat_type": "phishing", "description": "User clicked suspicious link in email. PowerShell execution detected downloading payload from evil-login.example.com.", "ioc_indicators": ["evil-login.example.com"], "subnet": "corporate", "is_acknowledged": False, }, { "alert_id": "ALERT-M002", "timestamp": "2025-01-15T08:32:00Z", "source_host": "WS-017", "severity": "high", "threat_type": "credential_theft", "description": "LSASS memory access detected — possible credential dumping via Mimikatz.", "ioc_indicators": ["aabbccdd11223344eeff5566778899aa"], "subnet": "corporate", "is_acknowledged": False, }, { "alert_id": "ALERT-M003", "timestamp": "2025-01-15T09:05:00Z", "source_host": "DEV-033", "severity": "high", "threat_type": "lateral_movement", "description": "Suspicious RDP login from WS-017 using admin credentials. New process svchost_backdoor.exe spawned.", "ioc_indicators": ["203.0.113.50", "112233445566778899aabbccddeeff00"], "subnet": "engineering", "is_acknowledged": False, }, { "alert_id": "ALERT-M004", "timestamp": "2025-01-15T09:12:00Z", "source_host": "FIN-012", "severity": "critical", "threat_type": "lateral_movement", "description": "Unauthorized access to FIN-012 from compromised credentials. Backdoor process active.", "ioc_indicators": ["112233445566778899aabbccddeeff00"], "subnet": "finance", "is_acknowledged": False, }, ], "optimal_actions": [ "query_host", "run_forensics", "kill_process", "block_ioc", "isolate_segment", "run_forensics", "submit_containment_plan", ], "containment_requirements": { "must_kill": [ {"hostname": "WS-017", "process": "powershell.exe"}, {"hostname": "WS-017", "process": "mimikatz.exe"}, {"hostname": "DEV-033", "process": "svchost_backdoor.exe"}, {"hostname": "FIN-012", "process": "svchost_backdoor.exe"}, ], "must_block_iocs": [ "evil-login.example.com", "203.0.113.50", "d41d8cd98f00b204e9800998ecf8427e", "aabbccdd11223344eeff5566778899aa", "112233445566778899aabbccddeeff00", ], "must_forensics": ["WS-017", "DEV-033", "FIN-012"], "must_not_isolate": ["executive", "datacenter"], }, }, # ----- HARD: APT + Ransomware, C2, exfiltration, executive pressure ----- "hard": { "description": "Advanced Persistent Threat with active C2 comms, data exfiltration in progress, and ransomware deployment imminent. Board is watching — minimize downtime.", "max_steps": 30, "initial_business_impact": 0.20, "impact_per_step": 0.04, "attack_chain": [ { "threat_id": "T-HARD-001", "threat_type": "phishing", "phase": "initial_access", "compromised_hosts": ["EXEC-003"], "malicious_processes": ["outlook_macro.exe"], "c2_servers": ["198.51.100.77"], "iocs": { "hashes": ["deadbeef0123456789abcdef01234567"], "ips": ["198.51.100.77"], "domains": ["cdn-update.malware-c2.net"], }, "lateral_targets": ["WS-088"], "exfil_targets": [], }, { "threat_id": "T-HARD-002", "threat_type": "c2_communication", "phase": "command_and_control", "compromised_hosts": ["EXEC-003", "WS-088"], "malicious_processes": ["svchost_c2.exe"], "c2_servers": ["198.51.100.77"], "iocs": { "hashes": ["cafebabe9876543210fedcba98765432"], "ips": ["198.51.100.77"], "domains": ["cdn-update.malware-c2.net", "exfil.malware-c2.net"], }, "lateral_targets": ["SRV-002", "FIN-008"], "exfil_targets": [], }, { "threat_id": "T-HARD-003", "threat_type": "privilege_escalation", "phase": "privilege_escalation", "compromised_hosts": ["SRV-002"], "malicious_processes": ["exploit_kernel.exe"], "c2_servers": ["198.51.100.77"], "iocs": { "hashes": ["1122334455667788aabbccddeeff0011"], "ips": ["198.51.100.77"], "domains": [], }, "lateral_targets": ["SRV-010", "SRV-015"], "exfil_targets": ["SRV-002"], }, { "threat_id": "T-HARD-004", "threat_type": "data_exfiltration", "phase": "exfiltration", "compromised_hosts": ["SRV-002", "FIN-008"], "malicious_processes": ["data_pump.exe"], "c2_servers": ["198.51.100.77"], "iocs": { "hashes": ["ffeeddccbbaa99887766554433221100"], "ips": ["198.51.100.77", "203.0.113.99"], "domains": ["exfil.malware-c2.net"], }, "lateral_targets": [], "exfil_targets": ["SRV-002", "FIN-008"], }, { "threat_id": "T-HARD-005", "threat_type": "ransomware", "phase": "impact", "compromised_hosts": ["SRV-010", "SRV-015"], "malicious_processes": ["blackcat_ransom.exe"], "c2_servers": [], "iocs": { "hashes": ["aabb0011ccdd2233eeff4455667788"], "ips": [], "domains": [], }, "lateral_targets": [], "exfil_targets": [], }, ], "initial_alerts": [ { "alert_id": "ALERT-H001", "timestamp": "2025-01-15T06:00:00Z", "source_host": "EXEC-003", "severity": "medium", "threat_type": "phishing", "description": "Executive VP opened macro-enabled document. Outbound connection to cdn-update.malware-c2.net detected.", "ioc_indicators": ["cdn-update.malware-c2.net", "198.51.100.77"], "subnet": "executive", "is_acknowledged": False, }, { "alert_id": "ALERT-H002", "timestamp": "2025-01-15T06:45:00Z", "source_host": "WS-088", "severity": "high", "threat_type": "c2_communication", "description": "Periodic beaconing detected to 198.51.100.77 every 60 seconds. Encrypted payload exchange observed.", "ioc_indicators": ["198.51.100.77", "cafebabe9876543210fedcba98765432"], "subnet": "corporate", "is_acknowledged": False, }, { "alert_id": "ALERT-H003", "timestamp": "2025-01-15T07:30:00Z", "source_host": "SRV-002", "severity": "critical", "threat_type": "privilege_escalation", "description": "Kernel exploit attempt on SRV-002 (database server). Process exploit_kernel.exe gained SYSTEM privileges.", "ioc_indicators": ["1122334455667788aabbccddeeff0011"], "subnet": "datacenter", "is_acknowledged": False, }, { "alert_id": "ALERT-H004", "timestamp": "2025-01-15T08:00:00Z", "source_host": "SRV-002", "severity": "critical", "threat_type": "data_exfiltration", "description": "Large data transfer (2.3 GB) to external IP 203.0.113.99 from database server SRV-002. Possible exfiltration of customer PII.", "ioc_indicators": ["203.0.113.99", "exfil.malware-c2.net"], "subnet": "datacenter", "is_acknowledged": False, }, { "alert_id": "ALERT-H005", "timestamp": "2025-01-15T08:10:00Z", "source_host": "FIN-008", "severity": "critical", "threat_type": "data_exfiltration", "description": "Financial records being staged for exfiltration on FIN-008. Process data_pump.exe accessing sensitive directories.", "ioc_indicators": ["ffeeddccbbaa99887766554433221100"], "subnet": "finance", "is_acknowledged": False, }, { "alert_id": "ALERT-H006", "timestamp": "2025-01-15T08:30:00Z", "source_host": "SRV-010", "severity": "critical", "threat_type": "ransomware", "description": "BlackCat ransomware deployment detected on SRV-010! File encryption starting on production storage.", "ioc_indicators": ["aabb0011ccdd2233eeff4455667788"], "subnet": "datacenter", "is_acknowledged": False, }, ], "optimal_actions": [ "block_ioc", "kill_process", "run_forensics", "isolate_segment", "kill_process", "block_ioc", "run_forensics", "kill_process", "submit_containment_plan", ], "containment_requirements": { "must_kill": [ {"hostname": "EXEC-003", "process": "outlook_macro.exe"}, {"hostname": "EXEC-003", "process": "svchost_c2.exe"}, {"hostname": "WS-088", "process": "svchost_c2.exe"}, {"hostname": "SRV-002", "process": "exploit_kernel.exe"}, {"hostname": "SRV-002", "process": "data_pump.exe"}, {"hostname": "FIN-008", "process": "data_pump.exe"}, {"hostname": "SRV-010", "process": "blackcat_ransom.exe"}, {"hostname": "SRV-015", "process": "blackcat_ransom.exe"}, ], "must_block_iocs": [ "198.51.100.77", "203.0.113.99", "cdn-update.malware-c2.net", "exfil.malware-c2.net", "deadbeef0123456789abcdef01234567", "cafebabe9876543210fedcba98765432", ], "must_forensics": ["EXEC-003", "WS-088", "SRV-002", "FIN-008", "SRV-010"], "must_not_isolate": [], # In APT scenario, any isolation decision is valid }, }, } def get_task(task_id: str) -> Dict[str, Any]: """Retrieve a task definition by ID. Supports: - 'easy', 'medium', 'hard': Hand-crafted curated benchmarks - 'gen_0001' through 'gen_1000': Procedurally generated scenarios - Any other string: Generated on-the-fly via seeded procedural generation Args: task_id: Task identifier string. Returns: Task definition dict. """ # Check hand-crafted tasks first if task_id in TASKS: return TASKS[task_id] # Fall back to procedural generation try: from .task_generator import generate_task except ImportError: from server.task_generator import generate_task return generate_task(task_id)