InvestigationDetailedSummaryParse
Parses attacks from context, and shows them according to the MITRE technique they use.
python · Malware Investigation and Response
Source
from collections import defaultdict from dataclasses import dataclass from typing import NamedTuple from CommonServerPython import * FoundTechnique = NamedTuple("FoundTechnique", (("mitre_id", str), ("name", str), ("tactics", list[str]))) Technique = NamedTuple("Technique", (("code", str), ("name", str))) Tactic = NamedTuple("Tactic", (("code", str), ("name", str), ("default_techniques", Optional[tuple[Technique]]))) Table = NamedTuple("Table", (("title", str), ("content", list[dict[str, str]]))) CONTEXT_PREFIX = "InvestigationDetailedSummary" @dataclass class TacticFinding: tactic: Tactic found_techniques: tuple[Technique] | tuple = () missing_techniques: tuple[Technique] | tuple = () def command_result(self): result = {technique.name: True for technique in self.found_techniques} | { technique.name: False for technique in self.missing_techniques } return CommandResults(outputs=result, outputs_prefix=f"{CONTEXT_PREFIX}.{self.tactic.name}") TACTICS = ( Tactic("TA0002", "Execution", default_techniques=(Technique("T1059", "Command and Scripting Interpreter"),)), Tactic("TA0004", "Privilege Escalation", default_techniques=(Technique("T1547", "Boot or Logon Autostart Execution"),)), Tactic("TA0008", "Lateral Movement", default_techniques=(Technique("T1021", "Remote Services"),)), Tactic("TA0005", "Defense Evasion", default_techniques=(Technique("T1070", "Indicator Removal on Host"),)), Tactic("TA0003", "Persistence", default_techniques=(Technique("T1547", "Boot or Logon Autostart Execution"),)), ) class ContextParser: def __init__(self, context: dict): self.tactic_to_found_technique = defaultdict(list) self.technique_id_to_found_technique = defaultdict(list) techniques = ContextParser._parse_techniques(context) for technique in techniques: self.technique_id_to_found_technique[technique.mitre_id].append(technique) for tactic in technique.tactics: self.tactic_to_found_technique[tactic].append(technique) @staticmethod def _parse_techniques(context: dict) -> tuple[FoundTechnique]: # type:ignore[arg-type] attack_pattern_context = context.get("AttackPattern", ()) if isinstance(attack_pattern_context, dict): # can be dict or list of dicts. attack_pattern_context = (attack_pattern_context,) result = [] for attack_dict in attack_pattern_context: if "value" not in (k.lower() for k in attack_dict): # outdated MITREv2 pack, <= v1.1.0 raise DemistoException("please make sure the MITRE ATT&CK v2 pack is up-to-date (v1.1.1 or newer)") result.append( FoundTechnique( mitre_id=attack_dict.get("MITREID", ""), name=attack_dict.get("Value", "") or attack_dict.get("value", ""), tactics=attack_dict.get("KillChainPhases", []), ) ) return tuple(result) # type:ignore[return-value] def find(self) -> tuple[TacticFinding]: result = [] for tactic in TACTICS: found = tuple(self.tactic_to_found_technique.get(tactic.name, ())) missing = tuple(filter(lambda t: t.code not in self.technique_id_to_found_technique, tactic.default_techniques or ())) result.append(TacticFinding(tactic, found, missing)) # type:ignore[arg-type] searched_tactic_names = {tactic.name for tactic in TACTICS} for tactic in set(self.tactic_to_found_technique.keys()).difference(searched_tactic_names): result.append( TacticFinding( tactic=Tactic(name=tactic, code="", default_techniques=None), found_techniques=tuple(self.tactic_to_found_technique[tactic]), ) # type:ignore[arg-type] ) return tuple(result) # type:ignore[return-value] def parse_command(context: dict) -> list[CommandResults]: parser = ContextParser(context) return [finding.command_result() for finding in parser.find()] def main(): try: context = demisto.callingContext.get("context", {}).get("ExecutionContext", {}) result = parse_command(context) return_results(result) except Exception as ex: demisto.error(traceback.format_exc()) # print the traceback return_error(f"Failed to execute InvestigationDetailedSummaryParse. Error: {ex!s}") if __name__ in ("__main__", "__builtin__", "builtins"): main()
README
This script parses attacks from context and shows them according to the MITRE technique they use.
The MITRE ATT&CK v2 pack (v1.1.0 or newer) is required for this automation to run properly.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Tags | basescript |
| Cortex XSOAR Version | 6.2.0 |
Inputs
There are no inputs for this script.
Outputs
| Path | Description | Type |
|---|---|---|
| InvestigationDetailedSummary.Execution.Command and Scripting Interpreter | Whether the Command and Scripting Interpreter technique was detected. | bool |
| InvestigationDetailedSummary.Privilege Escalation.Boot or Logon Autostart Execution | Whether the Boot or Logon Autostart Execution technique was detected. | bool |
| InvestigationDetailedSummary.Lateral Movement.Command and Scripting Interpreter | Whether the Indicator Removal on Host technique was detected. | bool |
| InvestigationDetailedSummary.Defense Evasion.Remote Services | Whether the Remote Services technique was detected. | bool |
| InvestigationDetailedSummary.Persistence.Boot or Logon Autostart Execution | Whether the Boot or Logon Autostart Execution technique was detected. | bool |