diff --git a/CHANGELOG.md b/CHANGELOG.md index a50e65b37..295f25371 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,10 @@ Changelog](https://keepachangelog.com/en/1.0.0/). the config successfully now.) #1490 - Mimikatz collector no longer fails if Azure credential collector is disabled. #1512 #1493 - Unhandled error when "modify shell startup files PBA" is unable to find regular users. #1507 +- ATT&CK report bug that showed different techniques' results under a technique if the PBA behind + them was the same. #1514 +- ATT&CK report bug that said that the technique "`.bash_profile` and `.bashrc`" was not attempted + when it actually was attempted but failed. #1511 ### Security diff --git a/monkey/infection_monkey/telemetry/post_breach_telem.py b/monkey/infection_monkey/telemetry/post_breach_telem.py index aceb8d294..4c6607b9c 100644 --- a/monkey/infection_monkey/telemetry/post_breach_telem.py +++ b/monkey/infection_monkey/telemetry/post_breach_telem.py @@ -2,6 +2,7 @@ import socket from common.common_consts.telem_categories import TelemCategoryEnum from infection_monkey.telemetry.base_telem import BaseTelem +from infection_monkey.utils.environment import is_windows_os class PostBreachTelem(BaseTelem): @@ -25,6 +26,7 @@ class PostBreachTelem(BaseTelem): "name": self.pba.name, "hostname": self.hostname, "ip": self.ip, + "os": PostBreachTelem._get_os(), } @staticmethod @@ -36,3 +38,7 @@ class PostBreachTelem(BaseTelem): hostname = "Unknown" ip = "Unknown" return hostname, ip + + @staticmethod + def _get_os(): + return "Windows" if is_windows_os() else "Linux" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1146.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1146.py index 98a725dcd..b85d4c728 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1146.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1146.py @@ -12,24 +12,3 @@ class T1146(PostBreachTechnique): "restored it back)." ) pba_names = [POST_BREACH_CLEAR_CMD_HISTORY] - - @staticmethod - def get_pba_query(*args): - return [ - { - "$match": { - "telem_category": "post_breach", - "data.name": POST_BREACH_CLEAR_CMD_HISTORY, - } - }, - { - "$project": { - "_id": 0, - "machine": { - "hostname": {"$arrayElemAt": ["$data.hostname", 0]}, - "ips": [{"$arrayElemAt": ["$data.ip", 0]}], - }, - "result": "$data.result", - } - }, - ] diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py index f9c5c5020..3244dbea3 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -9,30 +9,3 @@ class T1156(PostBreachTechnique): scanned_msg = "Monkey tried modifying bash startup files but failed." used_msg = "Monkey successfully modified bash startup files." pba_names = [POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION] - - @staticmethod - def get_pba_query(*args): - return [ - { - "$match": { - "telem_category": "post_breach", - "data.name": POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - } - }, - { - "$project": { - "_id": 0, - "machine": { - "hostname": {"$arrayElemAt": ["$data.hostname", 0]}, - "ips": [{"$arrayElemAt": ["$data.ip", 0]}], - }, - "result": "$data.result", - } - }, - {"$unwind": "$result"}, - { - "$match": { - "$or": [{"result": {"$regex": r"\.bash"}}, {"result": {"$regex": r"\.profile"}}] - } - }, - ] diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py index edeb083b3..ddeaf9788 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -9,26 +9,3 @@ class T1504(PostBreachTechnique): scanned_msg = "Monkey tried modifying PowerShell startup files but failed." used_msg = "Monkey successfully modified PowerShell startup files." pba_names = [POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION] - - @staticmethod - def get_pba_query(*args): - return [ - { - "$match": { - "telem_category": "post_breach", - "data.name": POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - } - }, - { - "$project": { - "_id": 0, - "machine": { - "hostname": {"$arrayElemAt": ["$data.hostname", 0]}, - "ips": [{"$arrayElemAt": ["$data.ip", 0]}], - }, - "result": "$data.result", - } - }, - {"$unwind": "$result"}, - {"$match": {"result": {"$regex": r"profile\.ps1"}}}, - ] diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/pba_technique.py b/monkey/monkey_island/cc/services/attack/technique_reports/pba_technique.py index 07e64566e..3cc3d4085 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/pba_technique.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/pba_technique.py @@ -18,7 +18,7 @@ class PostBreachTechnique(AttackTechnique, metaclass=abc.ABCMeta): ... @classmethod - def get_pba_query(cls, post_breach_action_names): + def get_pba_query(cls, post_breach_action_names, relevant_systems): """ :param post_breach_action_names: Names of post-breach actions with which the technique is associated @@ -29,14 +29,20 @@ class PostBreachTechnique(AttackTechnique, metaclass=abc.ABCMeta): return [ { "$match": { - "telem_category": "post_breach", - "$or": [{"data.name": pba_name} for pba_name in post_breach_action_names], + "$and": [ + {"telem_category": "post_breach"}, + {"$or": [{"data.name": pba_name} for pba_name in post_breach_action_names]}, + {"$or": [{"data.os": os} for os in relevant_systems]}, + ] } }, { "$project": { "_id": 0, - "machine": {"hostname": "$data.hostname", "ips": ["$data.ip"]}, + "machine": { + "hostname": {"$arrayElemAt": ["$data.hostname", 0]}, + "ips": [{"$arrayElemAt": ["$data.ip", 0]}], + }, "result": "$data.result", } }, @@ -50,13 +56,18 @@ class PostBreachTechnique(AttackTechnique, metaclass=abc.ABCMeta): @cls.is_status_disabled def get_technique_status_and_data(): - info = list(mongo.db.telemetry.aggregate(cls.get_pba_query(cls.pba_names))) + info = list( + mongo.db.telemetry.aggregate(cls.get_pba_query(cls.pba_names, cls.relevant_systems)) + ) status = ScanStatus.UNSCANNED.value if info: successful_PBAs = mongo.db.telemetry.count( { - "$or": [{"data.name": pba_name} for pba_name in cls.pba_names], - "data.result.1": True, + "$and": [ + {"$or": [{"data.name": pba_name} for pba_name in cls.pba_names]}, + {"$or": [{"data.os": os} for os in cls.relevant_systems]}, + {"data.result.1": True}, + ] } ) status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value diff --git a/monkey/tests/unit_tests/infection_monkey/telemetry/test_post_breach_telem.py b/monkey/tests/unit_tests/infection_monkey/telemetry/test_post_breach_telem.py index d6ce48825..e880b3fc9 100644 --- a/monkey/tests/unit_tests/infection_monkey/telemetry/test_post_breach_telem.py +++ b/monkey/tests/unit_tests/infection_monkey/telemetry/test_post_breach_telem.py @@ -6,6 +6,7 @@ from infection_monkey.telemetry.post_breach_telem import PostBreachTelem HOSTNAME = "hostname" IP = "0.0.0.0" +OS = "operating system" PBA_COMMAND = "run some pba" PBA_NAME = "some pba" RESULT = False @@ -21,6 +22,7 @@ class StubSomePBA: def post_breach_telem_test_instance(monkeypatch): PBA = StubSomePBA() monkeypatch.setattr(PostBreachTelem, "_get_hostname_and_ip", lambda: (HOSTNAME, IP)) + monkeypatch.setattr(PostBreachTelem, "_get_os", lambda: OS) return PostBreachTelem(PBA, RESULT) @@ -32,6 +34,7 @@ def test_post_breach_telem_send(post_breach_telem_test_instance, spy_send_teleme "name": PBA_NAME, "hostname": HOSTNAME, "ip": IP, + "os": OS, } expected_data = json.dumps(expected_data, cls=post_breach_telem_test_instance.json_encoder) assert spy_send_telemetry.data == expected_data