Skip to content

Commit

Permalink
Merge pull request #63 from frack113/filter-mitre-analyze
Browse files Browse the repository at this point in the history
Add level-status filter for mitre analyze
  • Loading branch information
thomaspatzke authored Feb 26, 2025
2 parents ab3c182 + d833665 commit b663382
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2,062 deletions.
18 changes: 12 additions & 6 deletions sigma/analyze/attack.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Callable, Dict, Iterable, List
from sigma.rule import SigmaRule, SigmaLevel, SigmaStatus
from sigma.rule import SigmaRule, SigmaLevel
from sigma.collection import SigmaCollection
from collections import defaultdict
Expand Down Expand Up @@ -46,14 +47,19 @@ def calculate_attack_scores(
rules: SigmaCollection,
score_function: Callable[[Iterable[SigmaRule]], int],
no_subtechniques: bool = False,
min_sigmalevel: SigmaLevel = SigmaLevel.INFORMATIONAL,
min_sigmastatus: SigmaStatus = SigmaStatus.UNSUPPORTED,
) -> Dict[str, int]:
"""Generate MITRE™️ ATT&CK Navigator heatmap according to scoring function."""
attack_rules = defaultdict(list)
for rule in rules:
for tag in rule.tags:
if tag.namespace == "attack":
technique = tag.name.upper()
if no_subtechniques:
technique = technique.split(".")[0]
attack_rules[technique].append(rule)
level = rule.level if rule.level else min_sigmalevel
status = rule.status if rule.status else min_sigmastatus
if level >= min_sigmalevel and status >= min_sigmastatus:
for tag in rule.tags:
if tag.namespace == "attack":
technique = tag.name.upper()
if no_subtechniques:
technique = technique.split(".")[0]
attack_rules[technique].append(rule)
return {attack: score_function(rules) for attack, rules in attack_rules.items()}
25 changes: 24 additions & 1 deletion sigma/cli/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
mitre_attack_version,
)
from sigma.analyze.stats import create_logsourcestats, format_row
from sigma.rule import SigmaLevel, SigmaStatus


@click.group(name="analyze", help="Analyze Sigma rule sets")
Expand All @@ -30,6 +31,18 @@ def analyze_group():
show_default=True,
help="Pattern for file names to be included in recursion into directories.",
)
@click.option(
"--min-level",
"-L",
default="INFORMATIONAL",
help="The minimun level of the rule to be include.",
)
@click.option(
"--min-status",
"-T",
default="UNSUPPORTED",
help="The minimun status of the rule to be include.",
)
@click.option(
"--subtechniques/--no-subtechniques",
"-s/-S",
Expand Down Expand Up @@ -80,6 +93,8 @@ def analyze_group():
)
def analyze_attack(
file_pattern,
min_level,
min_status,
subtechniques,
max_color,
min_color,
Expand All @@ -89,9 +104,17 @@ def analyze_attack(
output,
input,
):
try:
min_sigmalevel = SigmaLevel[min_level.upper()]
except:
min_sigmalevel = SigmaLevel.INFORMATIONAL
try:
min_sigmastatus = SigmaStatus[min_status.upper()]
except:
min_sigmastatus = SigmaStatus.UNSUPPORTED
rules = load_rules(input, file_pattern)
score_function = score_functions[function][0]
scores = calculate_attack_scores(rules, score_function, not subtechniques)
scores = calculate_attack_scores(rules, score_function, not subtechniques,min_sigmalevel=min_sigmalevel,min_sigmastatus=min_sigmastatus,)
layer_techniques = [
{
"techniqueID": technique,
Expand Down
Loading

0 comments on commit b663382

Please sign in to comment.