Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/detectmatelibrary/detectors/new_value_combo_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,17 @@ def detect(
combo_dict = get_combo(configured_variables)

overall_score = 0.0
for event_id, event_tracker in self.persistency.get_events_data().items():
current_event_id = input_["EventID"]
known_events = self.persistency.get_events_data()

if current_event_id in known_events:
event_tracker = known_events[current_event_id]
for combo_key, multi_tracker in event_tracker.get_data().items():
# Get the value tuple for this combo key
value_tuple = combo_dict.get(combo_key)
if value_tuple is None:
continue
if value_tuple not in multi_tracker.unique_set:
alerts[f"EventID {event_id}"] = (
alerts[f"EventID {current_event_id} - {combo_key}"] = (
f"Unknown value combination: {value_tuple}"
)
overall_score += 1.0
Expand Down
12 changes: 8 additions & 4 deletions src/detectmatelibrary/detectors/new_value_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,17 @@ def detect(
configured_variables = get_configured_variables(input_, self.config.events)
overall_score = 0.0

for event_id, event_tracker in self.persistency.get_events_data().items():
for event_id, multi_tracker in event_tracker.get_data().items():
value = configured_variables.get(event_id)
current_event_id = input_["EventID"]
known_events = self.persistency.get_events_data()

if current_event_id in known_events:
event_tracker = known_events[current_event_id]
for var_name, multi_tracker in event_tracker.get_data().items():
value = configured_variables.get(var_name)
if value is None:
continue
if value not in multi_tracker.unique_set:
alerts[f"EventID {event_id}"] = (
alerts[f"EventID {current_event_id} - {var_name}"] = (
f"Unknown value: '{value}'"
)
overall_score += 1.0
Expand Down
18 changes: 17 additions & 1 deletion src/detectmatelibrary/utils/persistency/event_persistency.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,23 @@ def get_event_data(self, event_id: int) -> Any | None:
return data_structure.get_data() if data_structure is not None else None

def get_events_data(self) -> Dict[int, EventDataStructure]:
"""Retrieve the events' data."""
"""Retrieve the events data that is currently stored.
Returns:
A dictionary mapping event IDs to their corresponding EventDataStructure instances.
Example:
{
1: EventTracker(data={
'var_0': SingleTracker(...),
'var_1': SingleTracker(...),
}),
2: EventTracker(data={
'var_0': SingleTracker(...)
}),
...
}
"""
return self.events_data

def get_event_template(self, event_id: int) -> str | None:
Expand Down
45 changes: 45 additions & 0 deletions tests/test_detectors/test_new_value_combo_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
NewValueComboDetector, BufferMode
)
from detectmatelibrary.common._config import generate_detector_config
from detectmatelibrary.parsers.template_matcher import MatcherParser
from detectmatelibrary.helper.from_to import From
import detectmatelibrary.schemas as schemas

from detectmatelibrary.utils.aux import time_test_mode
Expand Down Expand Up @@ -541,3 +543,46 @@ def test_configure_only_selects_stable_event_types(self):
output = schemas.DetectorSchema()
result = detector.detect(file_event, output)
assert result is False


_PARSER_CONFIG = {
"parsers": {
"MatcherParser": {
"method_type": "matcher_parser",
"auto_config": False,
"log_format": "type=<Type> msg=audit\\(<Time>\\): <Content>",
"time_format": None,
"params": {
"remove_spaces": True,
"remove_punctuation": True,
"lowercase": True,
"path_templates": "tests/test_folder/audit_templates.txt",
},
}
}
}


class TestNewValueComboDetectorEndToEndWithRealData:
"""Regression test: full configure/train/detect pipeline on audit.log."""

def test_audit_log_anomalies(self):
parser = MatcherParser(config=_PARSER_CONFIG)
detector = NewValueComboDetector()

logs = list(From.log(parser, in_path="tests/test_folder/audit.log", do_process=True))

for log in logs[:1800]:
detector.configure(log)
detector.set_configuration()

for log in logs[:1800]:
detector.train(log)

detected_ids: set[str] = set()
for log in logs[1800:]:
output = schemas.DetectorSchema()
if detector.detect(log, output_=output):
detected_ids.add(log["logID"])

print(detected_ids)
45 changes: 45 additions & 0 deletions tests/test_detectors/test_new_value_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"""

from detectmatelibrary.detectors.new_value_detector import NewValueDetector, BufferMode
from detectmatelibrary.parsers.template_matcher import MatcherParser
from detectmatelibrary.helper.from_to import From
import detectmatelibrary.schemas as schemas

from detectmatelibrary.utils.aux import time_test_mode
Expand Down Expand Up @@ -188,3 +190,46 @@ def test_detect_known_value_alert(self):

assert result
assert output.score == 1.0


_PARSER_CONFIG = {
"parsers": {
"MatcherParser": {
"method_type": "matcher_parser",
"auto_config": False,
"log_format": "type=<Type> msg=audit\\(<Time>\\): <Content>",
"time_format": None,
"params": {
"remove_spaces": True,
"remove_punctuation": True,
"lowercase": True,
"path_templates": "tests/test_folder/audit_templates.txt",
},
}
}
}


class TestNewValueDetectorEndToEnd:
"""Regression test: full configure/train/detect pipeline on audit.log."""

def test_audit_log_anomalies(self):
parser = MatcherParser(config=_PARSER_CONFIG)
detector = NewValueDetector()

logs = list(From.log(parser, in_path="tests/test_folder/audit.log", do_process=True))

for log in logs[:1800]:
detector.configure(log)
detector.set_configuration()

for log in logs[:1800]:
detector.train(log)

detected_ids: set[str] = set()
for log in logs[1800:]:
output = schemas.DetectorSchema()
if detector.detect(log, output_=output):
detected_ids.add(log["logID"])

assert detected_ids == {'1859', '1860', '1861', '1862', '1864', '1865', '1866', '1867'}