Skip to content

Commit 14e0efc

Browse files
authored
Merge pull request #3 from jmorascalyr/identity-attack-cross-platform
Identity attack cross platform
2 parents bfcb28b + b929010 commit 14e0efc

9 files changed

Lines changed: 2533 additions & 507 deletions

File tree

Backend/AGENTS.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,56 @@
4848
- In Docker, data persists under `api/data/` (mounted to `/app/data`).
4949
- Production: keep `DISABLE_AUTH=false`, use strong keys, configure CORS appropriately.
5050

51+
## Scenario Generation Playbook (Agent Instructions)
52+
Use this workflow whenever creating a new attack scenario under `Backend/scenarios/`.
53+
54+
1) Implement the scenario script
55+
- Create `Backend/scenarios/<scenario_id>.py` in `snake_case` (example: `identity_theft_ransomware_scenario.py`).
56+
- Include profiles (`VICTIM_PROFILE`, `ATTACKER_PROFILE`) and phase/step generators.
57+
- Return a top-level scenario object with:
58+
- `scenario_name`, `description`, `generated_at`, `total_events`, `events`
59+
- Each event formatted as: `{"timestamp", "source", "phase", "event"}`
60+
- Save JSON output to `Backend/scenarios/configs/<scenario_id>.json` in `__main__`.
61+
62+
2) Reuse existing generators first
63+
- Prefer functions from `event_generators/` over custom raw payloads.
64+
- Common modules used by scenarios:
65+
- Endpoint: `event_generators/endpoint_security/sentinelone_endpoint.py`
66+
- Identity: `event_generators/identity_access/okta_authentication.py`
67+
- Network: `event_generators/network_security/paloalto_firewall.py`
68+
- Windows logs: `event_generators/endpoint_security/microsoft_windows_eventlog.py`
69+
- Add new generator logic only if required fields cannot be represented with existing overrides.
70+
71+
3) Correlation-ready scenarios
72+
- If scenario supports SIEM time anchoring, add `CORRELATION_CONFIG` in the scenario module.
73+
- Include:
74+
- `scenario_id`, `name`, `description`, `default_query`
75+
- `time_anchors` and `phase_mapping`
76+
- `fallback_behavior` (typically `offset_from_now`)
77+
78+
4) Register in backend APIs
79+
- Add scenario metadata to:
80+
- `api/app/services/scenario_service.py` (`self.scenario_templates`)
81+
- `api/app/routers/scenarios.py` (`/templates` payload)
82+
- If correlation-enabled, also register import/append logic in:
83+
- `api/app/routers/scenarios.py` under `/correlation`
84+
85+
5) Register in frontend scenario dropdown
86+
- Add scenario entry to `Frontend/log_generator_ui.py` route `GET /scenarios`.
87+
- Ensure `id` exactly matches the scenario filename/module id.
88+
- If the UI should auto-send generated JSON to HEC, include the scenario id in the auto-replay allowlist in `Frontend/log_generator_ui.py`.
89+
90+
6) Verify execution and HEC replay
91+
- Validate import/compile:
92+
- `python3 -c "from <scenario_module> import <entry_fn>; print('Import OK')"`
93+
- Generate scenario:
94+
- `python3 Backend/scenarios/<scenario_id>.py`
95+
- Confirm JSON exists at `Backend/scenarios/configs/<scenario_id>.json`.
96+
- Run replay manually if needed:
97+
- `python3 Backend/scenarios/scenario_hec_sender.py --scenario Backend/scenarios/configs/<scenario_id>.json --auto --preserve-timestamps`
98+
99+
7) Expected operator log signals
100+
- During generation: phase banners + `Total Events` + `Scenario saved to ...`.
101+
- During replay: sender analysis + progress + transmission summary.
102+
- If generation completes but replay does not start, check frontend auto-replay allowlist for missing scenario id.
103+

Backend/api/app/routers/scenarios.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class CorrelationRunRequest(BaseModel):
4242
workers: int = 10
4343
overwrite_parser: bool = False
4444
suppress_alerts: bool = False
45-
strip_helios_prefix: bool = False
45+
include_helios_prefix: bool = False
4646

4747
# Initialize scenario service
4848
scenario_service = ScenarioService()
@@ -146,6 +146,15 @@ async def get_scenario_templates(
146146
"generators": ["proofpoint", "microsoft_365_collaboration", "sentinelone_endpoint", "paloalto_firewall"],
147147
"severity": "high",
148148
"mitre_tactics": ["T1566.002", "T1204.002", "T1059.001", "T1053.005", "T1071.001"]
149+
},
150+
{
151+
"id": "identity_theft_ransomware",
152+
"name": "Cross-Platform Identity Theft & Ransomware",
153+
"description": "Advanced identity-led attack: esentutl.exe LOLBin credential theft, stolen OAuth refresh-token abuse through Okta, C2 via ScreenConnect/ngrok/AnyDesk, AD recon (SharpHound, ADRecon), LSASS dump + Okta privilege escalation, and ALPHV/BlackCat ransomware execution with VSS deletion.",
154+
"duration_minutes": 55,
155+
"generators": ["sentinelone_endpoint", "okta_authentication", "paloalto_firewall", "microsoft_windows_eventlog"],
156+
"severity": "critical",
157+
"mitre_tactics": ["T1539", "T1550.001", "T1078", "T1071.001", "T1059.001", "T1003.001", "T1486", "T1490"]
149158
}
150159
]
151160

@@ -193,7 +202,20 @@ async def list_correlation_scenarios(
193202
except ImportError as e:
194203
logger.warning(f"Failed to import apollo_ransomware_scenario: {e}")
195204

196-
# Add more correlation scenarios here as they are created
205+
# Identity Theft & Ransomware Scenario
206+
try:
207+
from identity_theft_ransomware_scenario import CORRELATION_CONFIG as SS_CORRELATION_CONFIG
208+
correlation_scenarios.append({
209+
"id": SS_CORRELATION_CONFIG["scenario_id"],
210+
"name": SS_CORRELATION_CONFIG["name"],
211+
"description": SS_CORRELATION_CONFIG["description"],
212+
"default_query": SS_CORRELATION_CONFIG["default_query"],
213+
"time_anchors": SS_CORRELATION_CONFIG["time_anchors"],
214+
"phase_mapping": SS_CORRELATION_CONFIG["phase_mapping"],
215+
"fallback_behavior": SS_CORRELATION_CONFIG.get("fallback_behavior", "offset_from_now")
216+
})
217+
except ImportError as e:
218+
logger.warning(f"Failed to import identity_theft_ransomware_scenario: {e}")
197219

198220
return BaseResponse(
199221
success=True,
@@ -324,7 +346,7 @@ async def run_correlation_scenario(
324346
tag_trace=request.tag_trace,
325347
overwrite_parser=request.overwrite_parser,
326348
suppress_alerts=request.suppress_alerts,
327-
strip_helios_prefix=request.strip_helios_prefix,
349+
include_helios_prefix=request.include_helios_prefix,
328350
background_tasks=background_tasks
329351
)
330352

Backend/api/app/services/scenario_service.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,19 @@ def __init__(self):
170170
{"name": "Command & Control", "generators": ["sentinelone_endpoint", "paloalto_firewall"], "duration": 1},
171171
{"name": "Detection & Response", "generators": ["proofpoint", "sentinelone_endpoint"], "duration": 1}
172172
]
173+
},
174+
"identity_theft_ransomware": {
175+
"id": "identity_theft_ransomware",
176+
"name": "Cross-Platform Identity Theft & Ransomware",
177+
"description": "Advanced identity-led attack: esentutl.exe LOLBin credential theft, stolen OAuth refresh-token abuse through Okta, C2 via ScreenConnect/ngrok/AnyDesk, AD recon (SharpHound, ADRecon), LSASS dump + Okta privilege escalation, and ALPHV/BlackCat ransomware execution with VSS deletion.",
178+
"phases": [
179+
{"name": "Initial Access / Credential Theft", "generators": ["sentinelone_endpoint", "microsoft_windows_eventlog", "okta_authentication"], "duration": 10},
180+
{"name": "Command & Control", "generators": ["sentinelone_endpoint", "paloalto_firewall"], "duration": 5},
181+
{"name": "Endpoint Discovery & Staging", "generators": ["sentinelone_endpoint"], "duration": 10},
182+
{"name": "Credential & Privilege Abuse", "generators": ["sentinelone_endpoint", "microsoft_windows_eventlog", "okta_authentication"], "duration": 10},
183+
{"name": "Ransomware Preparation", "generators": ["sentinelone_endpoint"], "duration": 10},
184+
{"name": "Ransomware Execution / Impact", "generators": ["sentinelone_endpoint", "microsoft_windows_eventlog"], "duration": 10}
185+
]
173186
}
174187
}
175188
self._load_json_scenarios()
@@ -249,6 +262,12 @@ async def list_scenarios(
249262

250263
# Add metadata
251264
for scenario in scenarios:
265+
data_sources = sorted({
266+
generator
267+
for phase in scenario.get("phases", [])
268+
for generator in phase.get("generators", [])
269+
})
270+
scenario["data_sources"] = data_sources
252271
scenario["phase_count"] = len(scenario.get("phases", []))
253272
scenario["estimated_duration_minutes"] = sum(
254273
phase.get("duration", 0) for phase in scenario.get("phases", [])
@@ -302,7 +321,7 @@ async def start_correlation_scenario(
302321
dry_run: bool = False,
303322
overwrite_parser: bool = False,
304323
suppress_alerts: bool = False,
305-
strip_helios_prefix: bool = False,
324+
include_helios_prefix: bool = False,
306325
background_tasks=None
307326
) -> str:
308327
"""Start correlation scenario execution with SIEM context and trace ID support"""
@@ -321,7 +340,7 @@ async def start_correlation_scenario(
321340
"tag_trace": tag_trace,
322341
"overwrite_parser": overwrite_parser,
323342
"suppress_alerts": suppress_alerts,
324-
"strip_helios_prefix": strip_helios_prefix,
343+
"include_helios_prefix": include_helios_prefix,
325344
"progress": 0
326345
}
327346

@@ -335,7 +354,7 @@ async def start_correlation_scenario(
335354
tag_phase,
336355
tag_trace,
337356
suppress_alerts,
338-
strip_helios_prefix
357+
include_helios_prefix
339358
)
340359

341360
return execution_id
@@ -349,7 +368,7 @@ async def _execute_correlation_scenario(
349368
tag_phase: bool = True,
350369
tag_trace: bool = True,
351370
suppress_alerts: bool = False,
352-
strip_helios_prefix: bool = False
371+
include_helios_prefix: bool = False
353372
):
354373
"""Execute correlation scenario with SIEM context and trace ID support"""
355374
import sys
@@ -371,13 +390,19 @@ async def _execute_correlation_scenario(
371390
os.environ['S1_TRACE_ID'] = trace_id
372391
os.environ['S1_TAG_PHASE'] = '1' if tag_phase else '0'
373392
os.environ['S1_TAG_TRACE'] = '1' if tag_trace else '0'
393+
os.environ['SCENARIO_INCLUDE_HELIOS_PREFIX'] = 'true' if include_helios_prefix else 'false'
374394

375395
# Import and run the scenario
376-
module = __import__(scenario_id)
377-
scenario_result = module.generate_apollo_ransomware_scenario(
396+
scenario_module_map = {
397+
'apollo_ransomware_scenario': ('apollo_ransomware_scenario', 'generate_apollo_ransomware_scenario'),
398+
'identity_theft_ransomware': ('identity_theft_ransomware_scenario', 'generate_identity_theft_ransomware_scenario'),
399+
}
400+
module_name, function_name = scenario_module_map.get(scenario_id, (scenario_id, f'generate_{scenario_id}'))
401+
module = __import__(module_name)
402+
scenario_func = getattr(module, function_name)
403+
scenario_result = scenario_func(
378404
siem_context=siem_context,
379-
suppress_alerts=suppress_alerts,
380-
strip_helios_prefix=strip_helios_prefix,
405+
include_helios_prefix=include_helios_prefix,
381406
)
382407

383408
# Update execution status
@@ -400,6 +425,8 @@ async def _execute_correlation_scenario(
400425
os.environ.pop('S1_TRACE_ID', None)
401426
os.environ.pop('S1_TAG_PHASE', None)
402427
os.environ.pop('S1_TAG_TRACE', None)
428+
os.environ.pop('SCENARIO_INCLUDE_HELIOS_PREFIX', None)
429+
403430

404431
async def _execute_scenario(self, execution_id: str, scenario: Dict[str, Any]):
405432
"""Execute scenario in background"""

0 commit comments

Comments
 (0)