From 68aec8e336b51f8ffeb6dcde0ce0e2f424ef1b46 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 20 Aug 2019 18:15:25 +0300 Subject: [PATCH] Exported UsageTechnique class to separate file, improved documentation. Refactored scripting attack telemetry sending in pba --- monkey/infection_monkey/post_breach/pba.py | 13 ++++- .../attack/technique_reports/T1035.py | 3 +- .../attack/technique_reports/T1064.py | 2 +- .../attack/technique_reports/T1106.py | 2 +- .../attack/technique_reports/T1129.py | 3 +- .../attack/technique_reports/__init__.py | 46 +--------------- .../technique_reports/usage_technique.py | 53 +++++++++++++++++++ 7 files changed, 70 insertions(+), 52 deletions(-) create mode 100644 monkey/monkey_island/cc/services/attack/technique_reports/usage_technique.py diff --git a/monkey/infection_monkey/post_breach/pba.py b/monkey/infection_monkey/post_breach/pba.py index 123214db9..e3eb533ae 100644 --- a/monkey/infection_monkey/post_breach/pba.py +++ b/monkey/infection_monkey/post_breach/pba.py @@ -47,10 +47,21 @@ class PBA(object): """ exec_funct = self._execute_default result = exec_funct() - if result[1] and isinstance(self.command, list) and len(self.command) > 1: + if self.scripts_were_used(result): T1064Telem(ScanStatus.USED, "Scripts used to execute %s post breach action." % self.name).send() PostBreachTelem(self, result).send() + def scripts_were_used(self, pba_execution_result): + """ + Determines if scripts were used to execute PBA + :param pba_execution_result: result of execution function. e.g. self._execute_default + :return: True if scripts were used, False otherwise + """ + pba_execution_succeeded = pba_execution_result[1] + if pba_execution_succeeded and isinstance(self.command, list) and len(self.command) > 1: + return True + return False + def _execute_default(self): """ Default post breach command execution routine diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py index fcc230be5..2750c953c 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py @@ -1,5 +1,4 @@ -from monkey_island.cc.database import mongo -from monkey_island.cc.services.attack.technique_reports import UsageTechnique +from monkey_island.cc.services.attack.technique_reports.usage_technique import UsageTechnique __author__ = "VakarisZ" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1064.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1064.py index ef9ce1b80..9137f99e4 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1064.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1064.py @@ -1,4 +1,4 @@ -from monkey_island.cc.services.attack.technique_reports import UsageTechnique +from monkey_island.cc.services.attack.technique_reports.usage_technique import UsageTechnique __author__ = "VakarisZ" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1106.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1106.py index b50b19883..d07a66038 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1106.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1106.py @@ -1,4 +1,4 @@ -from monkey_island.cc.services.attack.technique_reports import UsageTechnique +from monkey_island.cc.services.attack.technique_reports.usage_technique import UsageTechnique __author__ = "VakarisZ" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py index f1a4d1b83..5f87faabb 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py @@ -1,5 +1,4 @@ -from monkey_island.cc.database import mongo -from monkey_island.cc.services.attack.technique_reports import UsageTechnique +from monkey_island.cc.services.attack.technique_reports.usage_technique import UsageTechnique __author__ = "VakarisZ" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py index ec5ee7781..e164e8830 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py @@ -2,7 +2,7 @@ import abc import logging from monkey_island.cc.database import mongo -from common.utils.attack_utils import ScanStatus, UsageEnum +from common.utils.attack_utils import ScanStatus from monkey_island.cc.services.attack.attack_config import AttackConfig from common.utils.code_utils import abstractstatic @@ -115,47 +115,3 @@ class AttackTechnique(object): data = cls.get_message_and_status(status) data.update({'title': cls.technique_title()}) return data - - -class UsageTechnique(AttackTechnique): - __metaclass__ = abc.ABCMeta - - @staticmethod - def parse_usages(usage): - """ - Parses data from database and translates usage enums into strings - :param usage: Usage telemetry that contains fields: {'usage': 'SMB', 'status': 1} - :return: usage string - """ - try: - usage['usage'] = UsageEnum[usage['usage']].value[usage['status']] - except KeyError: - logger.error("Error translating usage enum. into string. " - "Check if usage enum field exists and covers all telem. statuses.") - return usage - - @classmethod - def get_usage_data(cls): - data = list(mongo.db.telemetry.aggregate(cls.get_usage_query())) - return list(map(cls.parse_usages, data)) - - @classmethod - def get_usage_query(cls): - """ - :return: Query that parses attack telems for simple report component - (gets machines and attack technique usage). - """ - return [{'$match': {'telem_category': 'attack', - 'data.technique': cls.tech_id}}, - {'$lookup': {'from': 'monkey', - 'localField': 'monkey_guid', - 'foreignField': 'guid', - 'as': 'monkey'}}, - {'$project': {'monkey': {'$arrayElemAt': ['$monkey', 0]}, - 'status': '$data.status', - 'usage': '$data.usage'}}, - {'$addFields': {'_id': 0, - 'machine': {'hostname': '$monkey.hostname', 'ips': '$monkey.ip_addresses'}, - 'monkey': 0}}, - {'$group': {'_id': {'machine': '$machine', 'status': '$status', 'usage': '$usage'}}}, - {"$replaceRoot": {"newRoot": "$_id"}}] diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/usage_technique.py b/monkey/monkey_island/cc/services/attack/technique_reports/usage_technique.py new file mode 100644 index 000000000..69f178e1c --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/technique_reports/usage_technique.py @@ -0,0 +1,53 @@ +import abc + +from monkey_island.cc.database import mongo +from monkey_island.cc.services.attack.technique_reports import AttackTechnique, logger +from common.utils.attack_utils import UsageEnum + + +class UsageTechnique(AttackTechnique): + __metaclass__ = abc.ABCMeta + + @staticmethod + def parse_usages(usage): + """ + Parses data from database and translates usage enums into strings + :param usage: Usage telemetry that contains fields: {'usage': 'SMB', 'status': 1} + :return: usage string + """ + try: + usage['usage'] = UsageEnum[usage['usage']].value[usage['status']] + except KeyError: + logger.error("Error translating usage enum. into string. " + "Check if usage enum field exists and covers all telem. statuses.") + return usage + + @classmethod + def get_usage_data(cls): + """ + Gets data of usage attack telemetries + :return: parsed list of usages from attack telemetries of usage type + """ + data = list(mongo.db.telemetry.aggregate(cls.get_usage_query())) + return list(map(cls.parse_usages, data)) + + @classmethod + def get_usage_query(cls): + """ + :return: Query that parses attack telemetries for a simple report component + (gets machines and attack technique usage). + """ + return [{'$match': {'telem_category': 'attack', + 'data.technique': cls.tech_id}}, + {'$lookup': {'from': 'monkey', + 'localField': 'monkey_guid', + 'foreignField': 'guid', + 'as': 'monkey'}}, + {'$project': {'monkey': {'$arrayElemAt': ['$monkey', 0]}, + 'status': '$data.status', + 'usage': '$data.usage'}}, + {'$addFields': {'_id': 0, + 'machine': {'hostname': '$monkey.hostname', 'ips': '$monkey.ip_addresses'}, + 'monkey': 0}}, + {'$group': {'_id': {'machine': '$machine', 'status': '$status', 'usage': '$usage'}}}, + {"$replaceRoot": {"newRoot": "$_id"}}]