Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add support for structured levels of alerts, detections and logging #431

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
138 changes: 138 additions & 0 deletions mvt/common/alerting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Mobile Verification Toolkit (MVT)
# Copyright (c) 2021-2023 The MVT Authors.
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
from enum import Enum


class AlertLevel(Enum):
"""
informational: Rule is intended for enrichment of events, e.g. by tagging them. No case or alerting should be triggered by such rules because it is expected that a huge amount of events will match these rules.
low: Notable event but rarely an incident. Low rated events can be relevant in high numbers or combination with others. Immediate reaction shouldn’t be necessary, but a regular review is recommended.
medium: Relevant event that should be reviewed manually on a more frequent basis.
high: Relevant event that should trigger an internal alert and requires a prompt review.
critical: Highly relevant event that indicates an incident. Critical events should be reviewed immediately.
Comment on lines +10 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to tweak some of the language here around interpreting the levels for our specific case

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes definitely. I think we should include some similar descriptions in our documentation.

"""

INFORMATIONAL = 0
LOW = 10
MEDIUM = 20
HIGH = 30
CRITICAL = 40


class AlertStore(object):
"""
Track all of the alerts and detections generated during an analysis.

Results can be logged as log messages or in JSON format for processing by other tools.
"""

def __init__(self) -> None:
self.alerts = []

def add_alert(
self, level, message=None, event_time=None, event=None, ioc=None, detected=True
):
"""
Add an alert to the alert store.
"""
self.alerts.append(
Alert(
level=level,
message=message,
event_time=event_time,
event=event,
ioc=ioc,
detected=detected,
)
)

def informational(
self, message=None, event_time=None, event=None, ioc=None, detected=False
):
self.add_alert(
AlertLevel.INFORMATIONAL,
message=message,
event_time=event_time,
event=event,
ioc=ioc,
detected=detected,
)

def low(self, message=None, event_time=None, event=None, ioc=None, detected=False):
self.add_alert(
AlertLevel.LOW,
message=message,
event_time=event_time,
event=event,
ioc=ioc,
detected=detected,
)

def medium(
self, message=None, event_time=None, event=None, ioc=None, detected=False
):
self.add_alert(
AlertLevel.MEDIUM,
message=message,
event_time=event_time,
event=event,
ioc=ioc,
detected=detected,
)

def high(self, message=None, event_time=None, event=None, ioc=None, detected=False):
self.add_alert(
AlertLevel.HIGH,
message=message,
event_time=event_time,
event=event,
ioc=ioc,
detected=detected,
)

def critical(
self, message=None, event_time=None, event=None, ioc=None, detected=False
):
self.add_alert(
AlertLevel.CRITICAL,
message=message,
event_time=event_time,
event=event,
ioc=ioc,
detected=detected,
)


class Alert(object):
"""
An alert generated by an MVT module.
"""
Comment on lines +108 to +111
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making this a dataclass might be a good idea


def __init__(self, level, message, event_time, event, ioc, detected):
self.level = level
self.message = message
self.event_time = event_time
self.event = event
self.ioc = ioc
self.detected = detected

def __repr__(self):
return f"<Alert level={self.level} message={self.message} event_time={self.event_time} event={self.event}>"

def __str__(self):
return f"{self.level} {self.message} {self.event_time} {self.event}"

def to_log(self):
return f"{self.level} {self.message} {self.event_time} {self.event}"

def to_json(self):
return {
"level": self.level,
"message": self.message,
"event_time": self.event_time,
"event": self.event,
"ioc": self.ioc,
"detected": self.detected,
}
7 changes: 4 additions & 3 deletions mvt/ios/modules/mixed/sms.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ def check_indicators(self) -> None:
for message in self.results:
alert = "ALERT: State-sponsored attackers may be targeting your iPhone"
if message.get("text", "").startswith(alert):
self.log.warning(
"Apple warning about state-sponsored attack received on the %s",
message["isodate"],
self.alerts.medium(
f"Apple warning about state-sponsored attack received on the {message['isodate']}",
event_time=message["isodate"],
event=message,
)

if not self.indicators:
Expand Down
Loading