Skip to content

Commit d29eb9f

Browse files
committed
fix
1 parent fb7fa68 commit d29eb9f

File tree

5 files changed

+47
-24
lines changed

5 files changed

+47
-24
lines changed

uncoder-core/app/translator/core/models/query_container.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,13 @@ def __init__(
6969
self.raw_mitre_attack = raw_mitre_attack or []
7070
self.status = status or "stable"
7171
self.false_positives = false_positives or []
72-
self.source_mapping_ids = source_mapping_ids or [DEFAULT_MAPPING_NAME]
72+
self.source_mapping_ids = sorted(source_mapping_ids) if source_mapping_ids else [DEFAULT_MAPPING_NAME]
7373
self.parsed_logsources = parsed_logsources or {}
7474
self.timeframe = timeframe
7575

7676
@property
77-
def author_str(self) -> Optional[str]:
78-
if self.author:
79-
return ", ".join(self.author)
77+
def author_str(self) -> str:
78+
return ", ".join(self.author)
8079

8180

8281
@dataclass

uncoder-core/app/translator/platforms/elasticsearch/parsers/detection_rule.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,10 @@ def parse_raw_query(self, text: str, language: str) -> RawQueryContainer:
3333
rule = self.load_rule(text=text)
3434
parsed_description = parse_rule_description_str(rule.get("description", ""))
3535

36-
mitre_attack = None
37-
if rule_mitre_attack_data := rule.get("threat"):
38-
mitre_attack = self.mitre_config.get_mitre_info(
39-
tactics=[
40-
threat_data["tactic"]["name"].replace(" ", "_").lower() for threat_data in rule_mitre_attack_data
41-
],
42-
techniques=[threat_data["technique"][0]["id"].lower() for threat_data in rule_mitre_attack_data],
43-
)
36+
mitre_attack = self.mitre_config.get_mitre_info(
37+
tactics=[threat_data["tactic"]["name"].replace(" ", "_").lower() for threat_data in rule.get("threat", [])],
38+
techniques=[threat_data["technique"][0]["id"].lower() for threat_data in rule.get("threat", [])],
39+
)
4440

4541
return RawQueryContainer(
4642
query=rule["query"],

uncoder-core/app/translator/platforms/elasticsearch/renders/xpack_watcher.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
from typing import Optional
2323

2424
from app.translator.core.mapping import SourceMapping
25+
from app.translator.core.mitre import MitreConfig
2526
from app.translator.core.models.platform_details import PlatformDetails
26-
from app.translator.core.models.query_container import MetaInfoContainer
27+
from app.translator.core.models.query_container import MetaInfoContainer, MitreInfoContainer
2728
from app.translator.managers import render_manager
2829
from app.translator.platforms.base.lucene.mapping import LuceneMappings
2930
from app.translator.platforms.elasticsearch.const import XPACK_WATCHER_RULE, xpack_watcher_details
@@ -47,6 +48,24 @@ class XPackWatcherRuleRender(ElasticSearchQueryRender):
4748
mappings: LuceneMappings = xpack_watcher_mappings
4849
or_token = "OR"
4950
field_value_render = XpackWatcherRuleFieldValue(or_token=or_token)
51+
mitre: MitreConfig = MitreConfig()
52+
53+
def __create_mitre_threat(self, mitre_attack: MitreInfoContainer) -> dict:
54+
result = {"tactics": [], "techniques": []}
55+
56+
for tactic in mitre_attack.tactics:
57+
result["tactics"].append({"external_id": tactic.external_id, "url": tactic.url, "tactic": tactic.name})
58+
for technique in mitre_attack.techniques:
59+
result["techniques"].append(
60+
{
61+
"technique_id": technique.technique_id,
62+
"technique": technique.name,
63+
"url": technique.url,
64+
"tactic": technique.tactic,
65+
}
66+
)
67+
68+
return result if result["tactics"] or result["techniques"] else {}
5069

5170
def finalize_query(
5271
self,
@@ -76,7 +95,7 @@ def finalize_query(
7695
license_=meta_info.license,
7796
mitre_attack=mitre_attack,
7897
),
79-
"tags": meta_info.tags,
98+
"tags": self.__create_mitre_threat(mitre_attack=meta_info.mitre_attack),
8099
}
81100
)
82101
rule["input"]["search"]["request"]["body"]["query"]["bool"]["must"][0]["query_string"]["query"] = query

uncoder-core/app/translator/platforms/splunk/parsers/splunk_alert.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import re
2020

21+
from app.translator.core.custom_types.meta_info import SeverityType
2122
from app.translator.core.models.platform_details import PlatformDetails
2223
from app.translator.core.models.query_container import MetaInfoContainer, RawQueryContainer
2324
from app.translator.managers import parser_manager
@@ -36,9 +37,15 @@ def parse_raw_query(self, text: str, language: str) -> RawQueryContainer:
3637
rule_name: str = ""
3738
severity: str = ""
3839
raw_mitre_attack: list[str] = []
39-
if severity_match := re.search(r"action\.risk\.param\._risk_score\s*=\s*(\d+)", text):
40-
level_map = {"0": "informational", "25": "low", "50": "medium", "75": "high", "100": "critical"}
40+
if severity_match := re.search(r"alert\.severity\s*=\s*(\d+)", text):
41+
level_map = {
42+
"1": SeverityType.low,
43+
"2": SeverityType.medium,
44+
"3": SeverityType.high,
45+
"4": SeverityType.critical,
46+
}
4147
severity = level_map.get(str(severity_match.group(1)), "low")
48+
4249
if mitre_attack_match := re.search(r'"mitre_attack":\s*\[(.*?)\]', text):
4350
raw_mitre_attack = [attack.strip().strip('"').lower() for attack in mitre_attack_match.group(1).split(",")]
4451

uncoder-core/app/translator/platforms/splunk/renders/splunk_alert.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from app.translator.core.custom_types.meta_info import SeverityType
2323
from app.translator.core.mapping import SourceMapping
2424
from app.translator.core.models.platform_details import PlatformDetails
25-
from app.translator.core.models.query_container import MetaInfoContainer
25+
from app.translator.core.models.query_container import MetaInfoContainer, MitreInfoContainer
2626
from app.translator.managers import render_manager
2727
from app.translator.platforms.splunk.const import DEFAULT_SPLUNK_ALERT, splunk_alert_details
2828
from app.translator.platforms.splunk.mapping import SplunkMappings, splunk_alert_mappings
@@ -46,13 +46,15 @@ class SplunkAlertRender(SplunkQueryRender):
4646
field_value_render = SplunkAlertFieldValueRender(or_token=or_token)
4747

4848
@staticmethod
49-
def __create_mitre_threat(meta_info: MetaInfoContainer) -> dict:
50-
techniques = {"mitre_attack": []}
49+
def __create_mitre_threat(mitre_attack: MitreInfoContainer) -> dict:
50+
mitre_attack_render = {"mitre_attack": []}
5151

52-
for technique in meta_info.mitre_attack.techniques:
53-
techniques["mitre_attack"].append(technique.technique_id)
54-
techniques["mitre_attack"].sort()
55-
return techniques
52+
for technique in mitre_attack.techniques:
53+
mitre_attack_render["mitre_attack"].append(technique.technique_id)
54+
for tactic in mitre_attack.tactics:
55+
mitre_attack_render["mitre_attack"].append(tactic.name)
56+
mitre_attack_render["mitre_attack"].sort()
57+
return mitre_attack_render
5658

5759
def finalize_query(
5860
self,
@@ -77,7 +79,7 @@ def finalize_query(
7779
rule_id=meta_info.id,
7880
)
7981
rule = rule.replace("<description_place_holder>", rule_description)
80-
mitre_techniques = self.__create_mitre_threat(meta_info=meta_info)
82+
mitre_techniques = self.__create_mitre_threat(mitre_attack=meta_info.mitre_attack)
8183
if mitre_techniques:
8284
mitre_str = f"action.correlationsearch.annotations = {mitre_techniques})"
8385
rule = rule.replace("<annotations_place_holder>", mitre_str)

0 commit comments

Comments
 (0)