From 5fc6b6eb409fbcf1a3a9583802217020f4d8e5c5 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sat, 27 Jun 2020 01:13:18 +0530 Subject: [PATCH 01/27] Modify logic to call PostBreachTelem.send() only once for modify shell startup files PBA --- .../actions/modify_shell_startup_files.py | 22 ++++++++++++++++++- .../attack/technique_reports/T1156.py | 20 ++++++++++++----- .../attack/technique_reports/T1504.py | 20 ++++++++++++----- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 1ab524e64..57b44f5ed 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -1,8 +1,13 @@ +import subprocess + from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from infection_monkey.post_breach.pba import PBA from infection_monkey.post_breach.shell_startup_files.shell_startup_files_modification import \ get_commands_to_modify_shell_startup_files +from infection_monkey.telemetry.post_breach_telem import PostBreachTelem + +EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" class ModifyShellStartupFiles(PBA): @@ -12,8 +17,12 @@ class ModifyShellStartupFiles(PBA): and profile.ps1 in windows. """ + def __init__(self): + super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) + def run(self): - [pba.run() for pba in self.modify_shell_startup_PBA_list()] + results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] + PostBreachTelem(self, results).send() def modify_shell_startup_PBA_list(self): return ShellStartupPBAGenerator.get_modify_shell_startup_pbas() @@ -43,3 +52,14 @@ class ModifyShellStartupFile(PBA): super(ModifyShellStartupFile, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, linux_cmd=linux_cmds, windows_cmd=windows_cmds) + + def run(self): + if self.command: + try: + output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() + if not output: + output = EXECUTION_WITHOUT_OUTPUT + return output, True + except subprocess.CalledProcessError as e: + # Return error output of the command + return e.output.decode(), False 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 4c8f0d11f..b1ef19251 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -14,8 +14,7 @@ class T1156(AttackTechnique): used_msg = "Monkey modified bash startup files on the system." query = [{'$match': {'telem_category': 'post_breach', - 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - 'data.command': {'$regex': 'bash'}}}, + 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', 'ips': ['$data.ip']}, @@ -25,14 +24,23 @@ class T1156(AttackTechnique): def get_report_data(): data = {'title': T1156.technique_title(), 'info': []} - bash_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) + shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) + + bash_startup_modification_info = [] + for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: + # only want bash startup files + if any(file_name in shell_startup_file_result[0] for file_name in [".bash", ".profile"]): + bash_startup_modification_info.append({ + 'machine': shell_startup_files_modification_info[0]['machine'], + 'result': shell_startup_file_result + }) status = [] - for pba_node in bash_modification_info: - status.append(pba_node['result'][1]) + for bash_startup_file in bash_startup_modification_info: + status.append(bash_startup_file['result'][1]) status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ if status else ScanStatus.UNSCANNED.value data.update(T1156.get_base_data_by_status(status)) - data.update({'info': bash_modification_info}) + data.update({'info': bash_startup_modification_info}) return data 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 a9aeb38b7..57f2bf21f 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -14,8 +14,7 @@ class T1504(AttackTechnique): used_msg = "Monkey modified powershell startup files on the system." query = [{'$match': {'telem_category': 'post_breach', - 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - 'data.command': {'$regex': 'powershell'}}}, + 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', 'ips': ['$data.ip']}, @@ -25,14 +24,23 @@ class T1504(AttackTechnique): def get_report_data(): data = {'title': T1504.technique_title(), 'info': []} - powershell_profile_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) + shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) + + powershell_startup_modification_info = [] + for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: + # only want powershell startup files + if "profile.ps1" in shell_startup_file_result[0]: + powershell_startup_modification_info.append({ + 'machine': shell_startup_files_modification_info[0]['machine'], + 'result': shell_startup_file_result + }) status = [] - for pba_node in powershell_profile_modification_info: - status.append(pba_node['result'][1]) + for powershell_startup_file in powershell_startup_modification_info: + status.append(powershell_startup_file['result'][1]) status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ if status else ScanStatus.UNSCANNED.value data.update(T1504.get_base_data_by_status(status)) - data.update({'info': powershell_profile_modification_info}) + data.update({'info': powershell_startup_modification_info}) return data From 1182a3ad03d151020f3643c659e780f181d11d3a Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 20 Jul 2020 10:15:28 +0530 Subject: [PATCH 02/27] Manipulate PBA data to show multiple results of PBAs as separate entries in the report --- .../report-components/security/PostBreach.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js index cc9ea1c20..f49995b27 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js @@ -23,6 +23,17 @@ const subColumns = [ ]; let renderDetails = function (data) { + data.forEach(pba => { + if (typeof pba['result'][0] === "object") { // if `result` has more than one entry + let results = pba['result']; + let details = data.splice(data.indexOf(pba), 1); // remove that pba from `data` + results.forEach(result => { // add back those results to `data` as individual pba entries + let tempDetails = JSON.parse(JSON.stringify(details)); + tempDetails[0]['result'] = result; + data.push(tempDetails[0]); + }); + } + }); let defaultPageSize = data.length > pageSize ? pageSize : data.length; let showPagination = data.length > pageSize; return Date: Tue, 21 Jul 2020 22:54:48 +0530 Subject: [PATCH 03/27] CR changes - Added nested classes - Extracted repetitive code --- .../actions/modify_shell_startup_files.py | 63 +++++++++---------- .../attack/technique_reports/T1156.py | 19 ++---- .../attack/technique_reports/T1504.py | 19 ++---- .../technique_report_tools.py | 21 +++++++ 4 files changed, 62 insertions(+), 60 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 57b44f5ed..3973724e0 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -18,48 +18,47 @@ class ModifyShellStartupFiles(PBA): """ def __init__(self): - super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) + super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) def run(self): results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] PostBreachTelem(self, results).send() def modify_shell_startup_PBA_list(self): - return ShellStartupPBAGenerator.get_modify_shell_startup_pbas() + return self.ShellStartupPBAGenerator().get_modify_shell_startup_pbas() + class ShellStartupPBAGenerator(): + def get_modify_shell_startup_pbas(self): + (cmds_for_linux, shell_startup_files_for_linux, usernames_for_linux),\ + (cmds_for_windows, shell_startup_files_per_user_for_windows) =\ + get_commands_to_modify_shell_startup_files() -class ShellStartupPBAGenerator(): - def get_modify_shell_startup_pbas(): - (cmds_for_linux, shell_startup_files_for_linux, usernames_for_linux),\ - (cmds_for_windows, shell_startup_files_per_user_for_windows) = get_commands_to_modify_shell_startup_files() + pbas = [] - pbas = [] + for startup_file_per_user in shell_startup_files_per_user_for_windows: + windows_cmds = ' '.join(cmds_for_windows).format(startup_file_per_user) + pbas.append(self.ModifyShellStartupFile(linux_cmds='', windows_cmds=['powershell.exe', windows_cmds])) - for startup_file_per_user in shell_startup_files_per_user_for_windows: - windows_cmds = ' '.join(cmds_for_windows).format(startup_file_per_user) - pbas.append(ModifyShellStartupFile(linux_cmds='', windows_cmds=['powershell.exe', windows_cmds])) + for username in usernames_for_linux: + for shell_startup_file in shell_startup_files_for_linux: + linux_cmds = ' '.join(cmds_for_linux).format(shell_startup_file).format(username) + pbas.append(self.ModifyShellStartupFile(linux_cmds=linux_cmds, windows_cmds='')) - for username in usernames_for_linux: - for shell_startup_file in shell_startup_files_for_linux: - linux_cmds = ' '.join(cmds_for_linux).format(shell_startup_file).format(username) - pbas.append(ModifyShellStartupFile(linux_cmds=linux_cmds, windows_cmds='')) + return pbas - return pbas + class ModifyShellStartupFile(PBA): + def __init__(self, linux_cmds, windows_cmds): + super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, + linux_cmd=linux_cmds, + windows_cmd=windows_cmds) - -class ModifyShellStartupFile(PBA): - def __init__(self, linux_cmds, windows_cmds): - super(ModifyShellStartupFile, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - linux_cmd=linux_cmds, - windows_cmd=windows_cmds) - - def run(self): - if self.command: - try: - output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() - if not output: - output = EXECUTION_WITHOUT_OUTPUT - return output, True - except subprocess.CalledProcessError as e: - # Return error output of the command - return e.output.decode(), False + def run(self): + if self.command: + try: + output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() + if not output: + output = EXECUTION_WITHOUT_OUTPUT + return output, True + except subprocess.CalledProcessError as e: + # Return error output of the command + return e.output.decode(), False 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 b1ef19251..c6ddcba93 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -1,8 +1,9 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION -from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.services.attack.technique_reports.technique_report_tools import \ + extract_shell_startup_files_modification_info, get_shell_startup_files_modification_status __author__ = "shreyamalviya" @@ -26,20 +27,10 @@ class T1156(AttackTechnique): shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) - bash_startup_modification_info = [] - for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: - # only want bash startup files - if any(file_name in shell_startup_file_result[0] for file_name in [".bash", ".profile"]): - bash_startup_modification_info.append({ - 'machine': shell_startup_files_modification_info[0]['machine'], - 'result': shell_startup_file_result - }) + bash_startup_modification_info =\ + extract_shell_startup_files_modification_info(shell_startup_files_modification_info, [".bash", ".profile"]) - status = [] - for bash_startup_file in bash_startup_modification_info: - status.append(bash_startup_file['result'][1]) - status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ - if status else ScanStatus.UNSCANNED.value + status = get_shell_startup_files_modification_status(bash_startup_modification_info) data.update(T1156.get_base_data_by_status(status)) data.update({'info': bash_startup_modification_info}) 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 57f2bf21f..4fd0a475a 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -1,8 +1,9 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION -from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.services.attack.technique_reports.technique_report_tools import \ + extract_shell_startup_files_modification_info, get_shell_startup_files_modification_status __author__ = "shreyamalviya" @@ -26,20 +27,10 @@ class T1504(AttackTechnique): shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) - powershell_startup_modification_info = [] - for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: - # only want powershell startup files - if "profile.ps1" in shell_startup_file_result[0]: - powershell_startup_modification_info.append({ - 'machine': shell_startup_files_modification_info[0]['machine'], - 'result': shell_startup_file_result - }) + powershell_startup_modification_info =\ + extract_shell_startup_files_modification_info(shell_startup_files_modification_info, ["profile.ps1"]) - status = [] - for powershell_startup_file in powershell_startup_modification_info: - status.append(powershell_startup_file['result'][1]) - status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ - if status else ScanStatus.UNSCANNED.value + status = get_shell_startup_files_modification_status(powershell_startup_modification_info) data.update(T1504.get_base_data_by_status(status)) data.update({'info': powershell_startup_modification_info}) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index 80bfb952d..e7e2eb8e0 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -1,4 +1,5 @@ from monkey_island.cc.encryptor import encryptor +from common.utils.attack_utils import ScanStatus def parse_creds(attempt): @@ -44,3 +45,23 @@ def censor_hash(hash_, plain_chars=5): return "" hash_ = encryptor.dec(hash_) return hash_[0: plain_chars] + ' ...' + + +def extract_shell_startup_files_modification_info(shell_startup_files_modification_info, required_file_names): + required_shell_startup_files_modification_info = [] + for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: + if any(file_name in shell_startup_file_result[0] for file_name in required_file_names): + shell_startup_files_modification_info.append({ + 'machine': shell_startup_files_modification_info[0]['machine'], + 'result': shell_startup_file_result + }) + return required_shell_startup_files_modification_info + + +def get_shell_startup_files_modification_status(shell_startup_files_modification_info): + status = [] + for startup_file in shell_startup_files_modification_info: + status.append(startup_file['result'][1]) + status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ + if status else ScanStatus.UNSCANNED.value + return status From dec7d9021f719eb77c7b03d05888452601370a42 Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 22 Jul 2020 01:08:31 +0530 Subject: [PATCH 04/27] Move data modification for PBA from frontend to backend --- .../telemetry/processing/post_breach.py | 30 +++++++++++++++---- .../report-components/security/PostBreach.js | 11 ------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 974a696d5..63cdfff48 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -1,4 +1,8 @@ -from common.data.post_breach_consts import POST_BREACH_COMMUNICATE_AS_NEW_USER +import copy + +from common.data.post_breach_consts import ( + POST_BREACH_COMMUNICATE_AS_NEW_USER, + POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) from monkey_island.cc.database import mongo from monkey_island.cc.models import Monkey from monkey_island.cc.services.telemetry.zero_trust_tests.communicate_as_new_user import \ @@ -12,16 +16,32 @@ def process_communicate_as_new_user_telemetry(telemetry_json): test_new_user_communication(current_monkey, success, message) +def process_shell_startup_file_modification_telemetry(telemetry_json): + modified_data = [] + for result in telemetry_json['data']['result']: + temp = copy.deepcopy(telemetry_json['data']) + temp['result'] = result + modified_data.append(temp) + telemetry_json['data'] = modified_data + + POST_BREACH_TELEMETRY_PROCESSING_FUNCS = { POST_BREACH_COMMUNICATE_AS_NEW_USER: process_communicate_as_new_user_telemetry, + POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: process_shell_startup_file_modification_telemetry, } def process_post_breach_telemetry(telemetry_json): - mongo.db.monkey.update( - {'guid': telemetry_json['monkey_guid']}, - {'$push': {'pba_results': telemetry_json['data']}}) - post_breach_action_name = telemetry_json["data"]["name"] if post_breach_action_name in POST_BREACH_TELEMETRY_PROCESSING_FUNCS: POST_BREACH_TELEMETRY_PROCESSING_FUNCS[post_breach_action_name](telemetry_json) + + if type(telemetry_json['data']) is list: + for pba_data in telemetry_json['data']: + mongo.db.monkey.update( + {'guid': telemetry_json['monkey_guid']}, + {'$push': {'pba_results': pba_data}}) + else: + mongo.db.monkey.update( + {'guid': telemetry_json['monkey_guid']}, + {'$push': {'pba_results': telemetry_json['data']}}) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js index f49995b27..cc9ea1c20 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js @@ -23,17 +23,6 @@ const subColumns = [ ]; let renderDetails = function (data) { - data.forEach(pba => { - if (typeof pba['result'][0] === "object") { // if `result` has more than one entry - let results = pba['result']; - let details = data.splice(data.indexOf(pba), 1); // remove that pba from `data` - results.forEach(result => { // add back those results to `data` as individual pba entries - let tempDetails = JSON.parse(JSON.stringify(details)); - tempDetails[0]['result'] = result; - data.push(tempDetails[0]); - }); - } - }); let defaultPageSize = data.length > pageSize ? pageSize : data.length; let showPagination = data.length > pageSize; return Date: Wed, 22 Jul 2020 01:57:11 +0530 Subject: [PATCH 05/27] Modify `run()` for "modify shell startup files" PBA --- .../actions/modify_shell_startup_files.py | 13 +------------ monkey/infection_monkey/post_breach/pba.py | 7 +++++-- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 3973724e0..352610c6b 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -21,7 +21,7 @@ class ModifyShellStartupFiles(PBA): super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) def run(self): - results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] + results = [pba.run(return_result=True) for pba in self.modify_shell_startup_PBA_list()] PostBreachTelem(self, results).send() def modify_shell_startup_PBA_list(self): @@ -51,14 +51,3 @@ class ModifyShellStartupFiles(PBA): super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, linux_cmd=linux_cmds, windows_cmd=windows_cmds) - - def run(self): - if self.command: - try: - output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() - if not output: - output = EXECUTION_WITHOUT_OUTPUT - return output, True - except subprocess.CalledProcessError as e: - # Return error output of the command - return e.output.decode(), False diff --git a/monkey/infection_monkey/post_breach/pba.py b/monkey/infection_monkey/post_breach/pba.py index a6a89edf8..0660449ad 100644 --- a/monkey/infection_monkey/post_breach/pba.py +++ b/monkey/infection_monkey/post_breach/pba.py @@ -54,7 +54,7 @@ class PBA(Plugin): """ return class_name in WormConfiguration.post_breach_actions - def run(self): + def run(self, return_result=False): """ Runs post breach action command """ @@ -63,7 +63,10 @@ class PBA(Plugin): result = exec_funct() if self.scripts_were_used_successfully(result): T1064Telem(ScanStatus.USED, f"Scripts were used to execute {self.name} post breach action.").send() - PostBreachTelem(self, result).send() + if return_result: + return result + else: + PostBreachTelem(self, result).send() else: LOG.debug(f"No command available for PBA '{self.name}' on current OS, skipping.") From 1fdca52788d69ac865c51a022fc099b43fb56168 Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 22 Jul 2020 01:57:40 +0530 Subject: [PATCH 06/27] Fixes --- .../post_breach/actions/modify_shell_startup_files.py | 4 ---- .../cc/services/attack/technique_reports/T1156.py | 9 +++++---- .../cc/services/attack/technique_reports/T1504.py | 9 +++++---- .../attack/technique_reports/technique_report_tools.py | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 352610c6b..85f039628 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -1,5 +1,3 @@ -import subprocess - from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from infection_monkey.post_breach.pba import PBA @@ -7,8 +5,6 @@ from infection_monkey.post_breach.shell_startup_files.shell_startup_files_modifi get_commands_to_modify_shell_startup_files from infection_monkey.telemetry.post_breach_telem import PostBreachTelem -EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" - class ModifyShellStartupFiles(PBA): """ 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 c6ddcba93..ed61bbc94 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -2,8 +2,9 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.attack.technique_reports.technique_report_tools import \ - extract_shell_startup_files_modification_info, get_shell_startup_files_modification_status +from monkey_island.cc.services.attack.technique_reports.technique_report_tools import ( + extract_shell_startup_files_modification_info, + get_shell_startup_files_modification_status) __author__ = "shreyamalviya" @@ -17,8 +18,8 @@ class T1156(AttackTechnique): query = [{'$match': {'telem_category': 'post_breach', 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION}}, {'$project': {'_id': 0, - 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'machine': {'hostname': {'$arrayElemAt': ['$data.hostname', 0]}, + 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}] @staticmethod 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 4fd0a475a..4da6ffd17 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -2,8 +2,9 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.attack.technique_reports.technique_report_tools import \ - extract_shell_startup_files_modification_info, get_shell_startup_files_modification_status +from monkey_island.cc.services.attack.technique_reports.technique_report_tools import ( + extract_shell_startup_files_modification_info, + get_shell_startup_files_modification_status) __author__ = "shreyamalviya" @@ -17,8 +18,8 @@ class T1504(AttackTechnique): query = [{'$match': {'telem_category': 'post_breach', 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION}}, {'$project': {'_id': 0, - 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'machine': {'hostname': {'$arrayElemAt': ['$data.hostname', 0]}, + 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}] @staticmethod diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index e7e2eb8e0..88dbaab58 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -1,5 +1,5 @@ -from monkey_island.cc.encryptor import encryptor from common.utils.attack_utils import ScanStatus +from monkey_island.cc.encryptor import encryptor def parse_creds(attempt): @@ -51,7 +51,7 @@ def extract_shell_startup_files_modification_info(shell_startup_files_modificati required_shell_startup_files_modification_info = [] for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: if any(file_name in shell_startup_file_result[0] for file_name in required_file_names): - shell_startup_files_modification_info.append({ + required_shell_startup_files_modification_info.append({ 'machine': shell_startup_files_modification_info[0]['machine'], 'result': shell_startup_file_result }) From 5a7e8a0b08d33faa87c732064ea00cb251e2f72c Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 24 Jul 2020 13:13:11 +0530 Subject: [PATCH 07/27] Override `run()` for PBA "modify shell startup files" + assign EXECUTION_WITHOUT_OUTPUT to all relevant PBAs on the island side --- .../post_breach/actions/modify_shell_startup_files.py | 9 +++++++++ monkey/infection_monkey/post_breach/pba.py | 11 ++--------- .../cc/services/telemetry/processing/post_breach.py | 8 ++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 85f039628..fdc7e18dc 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -47,3 +47,12 @@ class ModifyShellStartupFiles(PBA): super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, linux_cmd=linux_cmds, windows_cmd=windows_cmds) + + def run(self): + if self.command: + try: + output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() + return output, True + except subprocess.CalledProcessError as e: + # Return error output of the command + return e.output.decode(), False \ No newline at end of file diff --git a/monkey/infection_monkey/post_breach/pba.py b/monkey/infection_monkey/post_breach/pba.py index 0660449ad..93d10d45e 100644 --- a/monkey/infection_monkey/post_breach/pba.py +++ b/monkey/infection_monkey/post_breach/pba.py @@ -13,8 +13,6 @@ LOG = logging.getLogger(__name__) __author__ = 'VakarisZ' -EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" - class PBA(Plugin): """ @@ -54,7 +52,7 @@ class PBA(Plugin): """ return class_name in WormConfiguration.post_breach_actions - def run(self, return_result=False): + def run(self): """ Runs post breach action command """ @@ -63,10 +61,7 @@ class PBA(Plugin): result = exec_funct() if self.scripts_were_used_successfully(result): T1064Telem(ScanStatus.USED, f"Scripts were used to execute {self.name} post breach action.").send() - if return_result: - return result - else: - PostBreachTelem(self, result).send() + PostBreachTelem(self, result).send() else: LOG.debug(f"No command available for PBA '{self.name}' on current OS, skipping.") @@ -93,8 +88,6 @@ class PBA(Plugin): """ try: output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() - if not output: - output = EXECUTION_WITHOUT_OUTPUT return output, True except subprocess.CalledProcessError as e: # Return error output of the command diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 63cdfff48..446ac0372 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -8,6 +8,8 @@ from monkey_island.cc.models import Monkey from monkey_island.cc.services.telemetry.zero_trust_tests.communicate_as_new_user import \ test_new_user_communication +EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" + def process_communicate_as_new_user_telemetry(telemetry_json): current_monkey = Monkey.get_single_monkey_by_guid(telemetry_json['monkey_guid']) @@ -38,10 +40,16 @@ def process_post_breach_telemetry(telemetry_json): if type(telemetry_json['data']) is list: for pba_data in telemetry_json['data']: + modify_blank_outputs(pba_data) mongo.db.monkey.update( {'guid': telemetry_json['monkey_guid']}, {'$push': {'pba_results': pba_data}}) else: + modify_blank_outputs(telemetry_json['data']) mongo.db.monkey.update( {'guid': telemetry_json['monkey_guid']}, {'$push': {'pba_results': telemetry_json['data']}}) + + def modify_blank_outputs(data): + if not data['result']: + data['result'] = EXECUTION_WITHOUT_OUTPUT From 90fe06e212562772b179bdf99a3e0f8464079ae2 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 24 Jul 2020 16:41:46 +0530 Subject: [PATCH 08/27] Modifications to get the telemetry feed and reports rendering properly --- .../actions/modify_shell_startup_files.py | 4 +- .../cc/resources/telemetry_feed.py | 6 +-- .../attack/technique_reports/T1136.py | 2 +- .../attack/technique_reports/T1154.py | 2 +- .../attack/technique_reports/T1158.py | 12 +++--- .../attack/technique_reports/T1166.py | 2 +- .../attack/technique_reports/T1168.py | 9 ++-- .../telemetry/processing/post_breach.py | 42 +++++++++---------- 8 files changed, 42 insertions(+), 37 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index fdc7e18dc..932007252 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -1,3 +1,5 @@ +import subprocess + from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from infection_monkey.post_breach.pba import PBA @@ -17,7 +19,7 @@ class ModifyShellStartupFiles(PBA): super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) def run(self): - results = [pba.run(return_result=True) for pba in self.modify_shell_startup_PBA_list()] + results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] PostBreachTelem(self, results).send() def modify_shell_startup_PBA_list(self): diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py index c278d2f36..17f263320 100644 --- a/monkey/monkey_island/cc/resources/telemetry_feed.py +++ b/monkey/monkey_island/cc/resources/telemetry_feed.py @@ -98,9 +98,9 @@ class TelemetryFeed(flask_restful.Resource): @staticmethod def get_post_breach_telem_brief(telem): - return '%s post breach action executed on %s (%s) machine.' % (telem['data']['name'], - telem['data']['hostname'], - telem['data']['ip']) + return '%s post breach action executed on %s (%s) machine.' % (telem['data'][0]['name'], + telem['data'][0]['hostname'], + telem['data'][0]['ip']) @staticmethod def should_show_brief(telem): diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1136.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1136.py index cb68d3a4f..042fd3c77 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1136.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1136.py @@ -18,7 +18,7 @@ class T1136(AttackTechnique): {'data.name': POST_BREACH_COMMUNICATE_AS_NEW_USER}]}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py index c7bace482..a48f3ebbd 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py @@ -16,7 +16,7 @@ class T1154(AttackTechnique): 'data.name': POST_BREACH_TRAP_COMMAND}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1158.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1158.py index 2db37bbbe..6cf9faeb8 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1158.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1158.py @@ -16,7 +16,7 @@ class T1158(AttackTechnique): 'data.name': POST_BREACH_HIDDEN_FILES}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod @@ -25,11 +25,11 @@ class T1158(AttackTechnique): hidden_file_info = list(mongo.db.telemetry.aggregate(T1158.query)) - status = [] - for pba_node in hidden_file_info: - status.append(pba_node['result'][1]) - status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ - if status else ScanStatus.UNSCANNED.value + status = ScanStatus.UNSCANNED.value + if hidden_file_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_HIDDEN_FILES, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1158.get_base_data_by_status(status)) data.update({'info': hidden_file_info}) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py index 3c5b9b0bf..84e213607 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py @@ -16,7 +16,7 @@ class T1166(AttackTechnique): 'data.name': POST_BREACH_SETUID_SETGID}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1168.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1168.py index 48298a7fe..bda495845 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1168.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1168.py @@ -17,7 +17,7 @@ class T1168(AttackTechnique): 'data.command': {'$regex': 'crontab'}}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod @@ -26,8 +26,11 @@ class T1168(AttackTechnique): job_scheduling_info = list(mongo.db.telemetry.aggregate(T1168.query)) - status = (ScanStatus.USED.value if job_scheduling_info[0]['result'][1] - else ScanStatus.SCANNED.value) if job_scheduling_info else ScanStatus.UNSCANNED.value + status = ScanStatus.UNSCANNED.value + if job_scheduling_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_JOB_SCHEDULING, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1168.get_base_data_by_status(status)) data.update({'info': job_scheduling_info}) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 446ac0372..0588dc396 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -18,38 +18,38 @@ def process_communicate_as_new_user_telemetry(telemetry_json): test_new_user_communication(current_monkey, success, message) -def process_shell_startup_file_modification_telemetry(telemetry_json): - modified_data = [] - for result in telemetry_json['data']['result']: - temp = copy.deepcopy(telemetry_json['data']) - temp['result'] = result - modified_data.append(temp) +def modify_data(telemetry_json): + modified_data = [telemetry_json['data']] + if type(telemetry_json['data']['result'][0]) is list: + modified_data = [] + for result in telemetry_json['data']['result']: + temp = copy.deepcopy(telemetry_json['data']) + temp['result'] = result + modified_data.append(temp) telemetry_json['data'] = modified_data POST_BREACH_TELEMETRY_PROCESSING_FUNCS = { POST_BREACH_COMMUNICATE_AS_NEW_USER: process_communicate_as_new_user_telemetry, - POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: process_shell_startup_file_modification_telemetry, } def process_post_breach_telemetry(telemetry_json): + def modify_blank_outputs(data): + if not data['result'][0]: + data['result'][0] = EXECUTION_WITHOUT_OUTPUT + + def update_data(data): + modify_blank_outputs(data) + mongo.db.monkey.update( + {'guid': telemetry_json['monkey_guid']}, + {'$push': {'pba_results': data}}) + post_breach_action_name = telemetry_json["data"]["name"] if post_breach_action_name in POST_BREACH_TELEMETRY_PROCESSING_FUNCS: POST_BREACH_TELEMETRY_PROCESSING_FUNCS[post_breach_action_name](telemetry_json) - if type(telemetry_json['data']) is list: - for pba_data in telemetry_json['data']: - modify_blank_outputs(pba_data) - mongo.db.monkey.update( - {'guid': telemetry_json['monkey_guid']}, - {'$push': {'pba_results': pba_data}}) - else: - modify_blank_outputs(telemetry_json['data']) - mongo.db.monkey.update( - {'guid': telemetry_json['monkey_guid']}, - {'$push': {'pba_results': telemetry_json['data']}}) + modify_data(telemetry_json) - def modify_blank_outputs(data): - if not data['result']: - data['result'] = EXECUTION_WITHOUT_OUTPUT + for pba_data in telemetry_json['data']: + update_data(pba_data) From eaf0cc854f57c021c3f2a9331a4281d0b11a7cc3 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 24 Jul 2020 22:43:50 +0530 Subject: [PATCH 09/27] Generate T1156 and T1504 reports via mongo query --- .../attack/technique_reports/T1156.py | 20 ++++++++++--------- .../attack/technique_reports/T1504.py | 19 +++++++++--------- .../technique_report_tools.py | 20 ------------------- 3 files changed, 21 insertions(+), 38 deletions(-) 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 ed61bbc94..a379c3907 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -1,10 +1,8 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION +from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.attack.technique_reports.technique_report_tools import ( - extract_shell_startup_files_modification_info, - get_shell_startup_files_modification_status) __author__ = "shreyamalviya" @@ -20,18 +18,22 @@ class T1156(AttackTechnique): {'$project': {'_id': 0, 'machine': {'hostname': {'$arrayElemAt': ['$data.hostname', 0]}, 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, - 'result': '$data.result'}}] + 'result': '$data.result'}}, + {'$unwind': '$result'}, + {'$match': {'$or': [{'result': {'$regex': '\.bash'}}, + {'result': {'$regex': '\.profile'}}]}}] @staticmethod def get_report_data(): data = {'title': T1156.technique_title(), 'info': []} - shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) + bash_startup_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) - bash_startup_modification_info =\ - extract_shell_startup_files_modification_info(shell_startup_files_modification_info, [".bash", ".profile"]) - - status = get_shell_startup_files_modification_status(bash_startup_modification_info) + status = ScanStatus.UNSCANNED.value + if bash_startup_modification_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1156.get_base_data_by_status(status)) data.update({'info': bash_startup_modification_info}) 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 4da6ffd17..b1013085e 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -1,10 +1,8 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION +from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.attack.technique_reports.technique_report_tools import ( - extract_shell_startup_files_modification_info, - get_shell_startup_files_modification_status) __author__ = "shreyamalviya" @@ -20,18 +18,21 @@ class T1504(AttackTechnique): {'$project': {'_id': 0, 'machine': {'hostname': {'$arrayElemAt': ['$data.hostname', 0]}, 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, - 'result': '$data.result'}}] + 'result': '$data.result'}}, + {'$unwind': '$result'}, + {'$match': {'result': {'$regex': 'profile\.ps1'}}}] @staticmethod def get_report_data(): data = {'title': T1504.technique_title(), 'info': []} - shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) + powershell_startup_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) - powershell_startup_modification_info =\ - extract_shell_startup_files_modification_info(shell_startup_files_modification_info, ["profile.ps1"]) - - status = get_shell_startup_files_modification_status(powershell_startup_modification_info) + status = ScanStatus.UNSCANNED.value + if powershell_startup_modification_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1504.get_base_data_by_status(status)) data.update({'info': powershell_startup_modification_info}) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index 88dbaab58..44b2fdd82 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -45,23 +45,3 @@ def censor_hash(hash_, plain_chars=5): return "" hash_ = encryptor.dec(hash_) return hash_[0: plain_chars] + ' ...' - - -def extract_shell_startup_files_modification_info(shell_startup_files_modification_info, required_file_names): - required_shell_startup_files_modification_info = [] - for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: - if any(file_name in shell_startup_file_result[0] for file_name in required_file_names): - required_shell_startup_files_modification_info.append({ - 'machine': shell_startup_files_modification_info[0]['machine'], - 'result': shell_startup_file_result - }) - return required_shell_startup_files_modification_info - - -def get_shell_startup_files_modification_status(shell_startup_files_modification_info): - status = [] - for startup_file in shell_startup_files_modification_info: - status.append(startup_file['result'][1]) - status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ - if status else ScanStatus.UNSCANNED.value - return status From 45fdf4b62ca8fdafea6d16bfa2c2f613bb24a5f9 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 24 Jul 2020 23:01:37 +0530 Subject: [PATCH 10/27] Pass build --- .../post_breach/actions/modify_shell_startup_files.py | 4 +++- .../cc/services/attack/technique_reports/T1156.py | 4 ++-- .../cc/services/attack/technique_reports/T1504.py | 2 +- .../attack/technique_reports/technique_report_tools.py | 1 - 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 932007252..5e8208c96 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -53,7 +53,9 @@ class ModifyShellStartupFiles(PBA): def run(self): if self.command: try: - output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() + output = subprocess.check_output(self.command, # noqa: DUO116 + stderr=subprocess.STDOUT, + shell=True).decode() return output, True except subprocess.CalledProcessError as e: # Return error output of the command 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 a379c3907..a9c0ea338 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -20,8 +20,8 @@ class T1156(AttackTechnique): 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}, {'$unwind': '$result'}, - {'$match': {'$or': [{'result': {'$regex': '\.bash'}}, - {'result': {'$regex': '\.profile'}}]}}] + {'$match': {'$or': [{'result': {'$regex': '\.bash'}}, # noqa: W605 + {'result': {'$regex': '\.profile'}}]}}] # noqa: W605 @staticmethod def get_report_data(): 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 b1013085e..7bfda1d8e 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -20,7 +20,7 @@ class T1504(AttackTechnique): 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}, {'$unwind': '$result'}, - {'$match': {'result': {'$regex': 'profile\.ps1'}}}] + {'$match': {'result': {'$regex': 'profile\.ps1'}}}] # noqa: W605 @staticmethod def get_report_data(): diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index 44b2fdd82..80bfb952d 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -1,4 +1,3 @@ -from common.utils.attack_utils import ScanStatus from monkey_island.cc.encryptor import encryptor From e6560ba3d410014b87554688313ec3271c9583ef Mon Sep 17 00:00:00 2001 From: Shreya Date: Sun, 26 Jul 2020 23:25:30 +0530 Subject: [PATCH 11/27] Small CR changes --- .../post_breach/actions/modify_shell_startup_files.py | 2 +- .../cc/services/attack/technique_reports/T1156.py | 4 ++-- .../cc/services/attack/technique_reports/T1504.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 5e8208c96..f7bd43a6e 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -59,4 +59,4 @@ class ModifyShellStartupFiles(PBA): return output, True except subprocess.CalledProcessError as e: # Return error output of the command - return e.output.decode(), False \ No newline at end of file + return e.output.decode(), False 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 a9c0ea338..64c401e8f 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -20,8 +20,8 @@ class T1156(AttackTechnique): 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}, {'$unwind': '$result'}, - {'$match': {'$or': [{'result': {'$regex': '\.bash'}}, # noqa: W605 - {'result': {'$regex': '\.profile'}}]}}] # noqa: W605 + {'$match': {'$or': [{'result': {'$regex': r'\.bash'}}, + {'result': {'$regex': r'\.profile'}}]}}] @staticmethod def get_report_data(): 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 7bfda1d8e..05568fcb8 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -20,7 +20,7 @@ class T1504(AttackTechnique): 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}, {'$unwind': '$result'}, - {'$match': {'result': {'$regex': 'profile\.ps1'}}}] # noqa: W605 + {'$match': {'result': {'$regex': r'profile\.ps1'}}}] @staticmethod def get_report_data(): From e6c93056ccd7466b86a035dc42d3fc123f439155 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sun, 26 Jul 2020 23:25:58 +0530 Subject: [PATCH 12/27] Improve code readibility TODO: Add tests --- .../telemetry/processing/post_breach.py | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 0588dc396..0cb8fcb1e 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -18,38 +18,42 @@ def process_communicate_as_new_user_telemetry(telemetry_json): test_new_user_communication(current_monkey, success, message) -def modify_data(telemetry_json): - modified_data = [telemetry_json['data']] - if type(telemetry_json['data']['result'][0]) is list: - modified_data = [] - for result in telemetry_json['data']['result']: - temp = copy.deepcopy(telemetry_json['data']) - temp['result'] = result - modified_data.append(temp) - telemetry_json['data'] = modified_data - - POST_BREACH_TELEMETRY_PROCESSING_FUNCS = { POST_BREACH_COMMUNICATE_AS_NEW_USER: process_communicate_as_new_user_telemetry, } def process_post_breach_telemetry(telemetry_json): - def modify_blank_outputs(data): - if not data['result'][0]: - data['result'][0] = EXECUTION_WITHOUT_OUTPUT + def convert_telem_data_to_list(data): + modified_data = [data] + if type(data['result'][0]) is list: # multiple results in one pba + modified_data = separate_results_to_single_pba_telems(data) + return modified_data + + def separate_results_to_single_pba_telems(data): + modified_data = [] + for result in data['result']: + temp = copy.deepcopy(data) + temp['result'] = result + modified_data.append(temp) + return modified_data def update_data(data): - modify_blank_outputs(data) + data = add_message_for_blank_outputs(data) mongo.db.monkey.update( {'guid': telemetry_json['monkey_guid']}, {'$push': {'pba_results': data}}) + def add_message_for_blank_outputs(data): + if not data['result'][0]: + data['result'][0] = EXECUTION_WITHOUT_OUTPUT + return data + post_breach_action_name = telemetry_json["data"]["name"] if post_breach_action_name in POST_BREACH_TELEMETRY_PROCESSING_FUNCS: POST_BREACH_TELEMETRY_PROCESSING_FUNCS[post_breach_action_name](telemetry_json) - modify_data(telemetry_json) + telemetry_json['data'] = convert_telem_data_to_list(telemetry_json['data']) for pba_data in telemetry_json['data']: update_data(pba_data) From 18e73de6292182460ab7bc7d8ff7f08f38b9bb69 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sat, 27 Jun 2020 01:13:18 +0530 Subject: [PATCH 13/27] Modify logic to call PostBreachTelem.send() only once for modify shell startup files PBA --- .../actions/modify_shell_startup_files.py | 22 ++++++++++++++++++- .../attack/technique_reports/T1156.py | 20 ++++++++++++----- .../attack/technique_reports/T1504.py | 20 ++++++++++++----- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 1ab524e64..57b44f5ed 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -1,8 +1,13 @@ +import subprocess + from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from infection_monkey.post_breach.pba import PBA from infection_monkey.post_breach.shell_startup_files.shell_startup_files_modification import \ get_commands_to_modify_shell_startup_files +from infection_monkey.telemetry.post_breach_telem import PostBreachTelem + +EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" class ModifyShellStartupFiles(PBA): @@ -12,8 +17,12 @@ class ModifyShellStartupFiles(PBA): and profile.ps1 in windows. """ + def __init__(self): + super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) + def run(self): - [pba.run() for pba in self.modify_shell_startup_PBA_list()] + results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] + PostBreachTelem(self, results).send() def modify_shell_startup_PBA_list(self): return ShellStartupPBAGenerator.get_modify_shell_startup_pbas() @@ -43,3 +52,14 @@ class ModifyShellStartupFile(PBA): super(ModifyShellStartupFile, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, linux_cmd=linux_cmds, windows_cmd=windows_cmds) + + def run(self): + if self.command: + try: + output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() + if not output: + output = EXECUTION_WITHOUT_OUTPUT + return output, True + except subprocess.CalledProcessError as e: + # Return error output of the command + return e.output.decode(), False 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 4c8f0d11f..b1ef19251 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -14,8 +14,7 @@ class T1156(AttackTechnique): used_msg = "Monkey modified bash startup files on the system." query = [{'$match': {'telem_category': 'post_breach', - 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - 'data.command': {'$regex': 'bash'}}}, + 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', 'ips': ['$data.ip']}, @@ -25,14 +24,23 @@ class T1156(AttackTechnique): def get_report_data(): data = {'title': T1156.technique_title(), 'info': []} - bash_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) + shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) + + bash_startup_modification_info = [] + for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: + # only want bash startup files + if any(file_name in shell_startup_file_result[0] for file_name in [".bash", ".profile"]): + bash_startup_modification_info.append({ + 'machine': shell_startup_files_modification_info[0]['machine'], + 'result': shell_startup_file_result + }) status = [] - for pba_node in bash_modification_info: - status.append(pba_node['result'][1]) + for bash_startup_file in bash_startup_modification_info: + status.append(bash_startup_file['result'][1]) status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ if status else ScanStatus.UNSCANNED.value data.update(T1156.get_base_data_by_status(status)) - data.update({'info': bash_modification_info}) + data.update({'info': bash_startup_modification_info}) return data 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 a9aeb38b7..57f2bf21f 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -14,8 +14,7 @@ class T1504(AttackTechnique): used_msg = "Monkey modified powershell startup files on the system." query = [{'$match': {'telem_category': 'post_breach', - 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - 'data.command': {'$regex': 'powershell'}}}, + 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', 'ips': ['$data.ip']}, @@ -25,14 +24,23 @@ class T1504(AttackTechnique): def get_report_data(): data = {'title': T1504.technique_title(), 'info': []} - powershell_profile_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) + shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) + + powershell_startup_modification_info = [] + for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: + # only want powershell startup files + if "profile.ps1" in shell_startup_file_result[0]: + powershell_startup_modification_info.append({ + 'machine': shell_startup_files_modification_info[0]['machine'], + 'result': shell_startup_file_result + }) status = [] - for pba_node in powershell_profile_modification_info: - status.append(pba_node['result'][1]) + for powershell_startup_file in powershell_startup_modification_info: + status.append(powershell_startup_file['result'][1]) status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ if status else ScanStatus.UNSCANNED.value data.update(T1504.get_base_data_by_status(status)) - data.update({'info': powershell_profile_modification_info}) + data.update({'info': powershell_startup_modification_info}) return data From a6e7c934f52acc33086b5dd4d3696c15aada9080 Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 20 Jul 2020 10:15:28 +0530 Subject: [PATCH 14/27] Manipulate PBA data to show multiple results of PBAs as separate entries in the report --- .../report-components/security/PostBreach.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js index 390ad6189..45eac8149 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js @@ -23,6 +23,17 @@ const subColumns = [ ]; let renderDetails = function (data) { + data.forEach(pba => { + if (typeof pba['result'][0] === "object") { // if `result` has more than one entry + let results = pba['result']; + let details = data.splice(data.indexOf(pba), 1); // remove that pba from `data` + results.forEach(result => { // add back those results to `data` as individual pba entries + let tempDetails = JSON.parse(JSON.stringify(details)); + tempDetails[0]['result'] = result; + data.push(tempDetails[0]); + }); + } + }); let defaultPageSize = data.length > pageSize ? pageSize : data.length; let showPagination = data.length > pageSize; return Date: Tue, 21 Jul 2020 22:54:48 +0530 Subject: [PATCH 15/27] CR changes - Added nested classes - Extracted repetitive code --- .../actions/modify_shell_startup_files.py | 63 +++++++++---------- .../attack/technique_reports/T1156.py | 19 ++---- .../attack/technique_reports/T1504.py | 19 ++---- .../technique_report_tools.py | 21 +++++++ 4 files changed, 62 insertions(+), 60 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 57b44f5ed..3973724e0 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -18,48 +18,47 @@ class ModifyShellStartupFiles(PBA): """ def __init__(self): - super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) + super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) def run(self): results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] PostBreachTelem(self, results).send() def modify_shell_startup_PBA_list(self): - return ShellStartupPBAGenerator.get_modify_shell_startup_pbas() + return self.ShellStartupPBAGenerator().get_modify_shell_startup_pbas() + class ShellStartupPBAGenerator(): + def get_modify_shell_startup_pbas(self): + (cmds_for_linux, shell_startup_files_for_linux, usernames_for_linux),\ + (cmds_for_windows, shell_startup_files_per_user_for_windows) =\ + get_commands_to_modify_shell_startup_files() -class ShellStartupPBAGenerator(): - def get_modify_shell_startup_pbas(): - (cmds_for_linux, shell_startup_files_for_linux, usernames_for_linux),\ - (cmds_for_windows, shell_startup_files_per_user_for_windows) = get_commands_to_modify_shell_startup_files() + pbas = [] - pbas = [] + for startup_file_per_user in shell_startup_files_per_user_for_windows: + windows_cmds = ' '.join(cmds_for_windows).format(startup_file_per_user) + pbas.append(self.ModifyShellStartupFile(linux_cmds='', windows_cmds=['powershell.exe', windows_cmds])) - for startup_file_per_user in shell_startup_files_per_user_for_windows: - windows_cmds = ' '.join(cmds_for_windows).format(startup_file_per_user) - pbas.append(ModifyShellStartupFile(linux_cmds='', windows_cmds=['powershell.exe', windows_cmds])) + for username in usernames_for_linux: + for shell_startup_file in shell_startup_files_for_linux: + linux_cmds = ' '.join(cmds_for_linux).format(shell_startup_file).format(username) + pbas.append(self.ModifyShellStartupFile(linux_cmds=linux_cmds, windows_cmds='')) - for username in usernames_for_linux: - for shell_startup_file in shell_startup_files_for_linux: - linux_cmds = ' '.join(cmds_for_linux).format(shell_startup_file).format(username) - pbas.append(ModifyShellStartupFile(linux_cmds=linux_cmds, windows_cmds='')) + return pbas - return pbas + class ModifyShellStartupFile(PBA): + def __init__(self, linux_cmds, windows_cmds): + super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, + linux_cmd=linux_cmds, + windows_cmd=windows_cmds) - -class ModifyShellStartupFile(PBA): - def __init__(self, linux_cmds, windows_cmds): - super(ModifyShellStartupFile, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - linux_cmd=linux_cmds, - windows_cmd=windows_cmds) - - def run(self): - if self.command: - try: - output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() - if not output: - output = EXECUTION_WITHOUT_OUTPUT - return output, True - except subprocess.CalledProcessError as e: - # Return error output of the command - return e.output.decode(), False + def run(self): + if self.command: + try: + output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() + if not output: + output = EXECUTION_WITHOUT_OUTPUT + return output, True + except subprocess.CalledProcessError as e: + # Return error output of the command + return e.output.decode(), False 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 b1ef19251..c6ddcba93 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -1,8 +1,9 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION -from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.services.attack.technique_reports.technique_report_tools import \ + extract_shell_startup_files_modification_info, get_shell_startup_files_modification_status __author__ = "shreyamalviya" @@ -26,20 +27,10 @@ class T1156(AttackTechnique): shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) - bash_startup_modification_info = [] - for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: - # only want bash startup files - if any(file_name in shell_startup_file_result[0] for file_name in [".bash", ".profile"]): - bash_startup_modification_info.append({ - 'machine': shell_startup_files_modification_info[0]['machine'], - 'result': shell_startup_file_result - }) + bash_startup_modification_info =\ + extract_shell_startup_files_modification_info(shell_startup_files_modification_info, [".bash", ".profile"]) - status = [] - for bash_startup_file in bash_startup_modification_info: - status.append(bash_startup_file['result'][1]) - status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ - if status else ScanStatus.UNSCANNED.value + status = get_shell_startup_files_modification_status(bash_startup_modification_info) data.update(T1156.get_base_data_by_status(status)) data.update({'info': bash_startup_modification_info}) 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 57f2bf21f..4fd0a475a 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -1,8 +1,9 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION -from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.services.attack.technique_reports.technique_report_tools import \ + extract_shell_startup_files_modification_info, get_shell_startup_files_modification_status __author__ = "shreyamalviya" @@ -26,20 +27,10 @@ class T1504(AttackTechnique): shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) - powershell_startup_modification_info = [] - for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: - # only want powershell startup files - if "profile.ps1" in shell_startup_file_result[0]: - powershell_startup_modification_info.append({ - 'machine': shell_startup_files_modification_info[0]['machine'], - 'result': shell_startup_file_result - }) + powershell_startup_modification_info =\ + extract_shell_startup_files_modification_info(shell_startup_files_modification_info, ["profile.ps1"]) - status = [] - for powershell_startup_file in powershell_startup_modification_info: - status.append(powershell_startup_file['result'][1]) - status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ - if status else ScanStatus.UNSCANNED.value + status = get_shell_startup_files_modification_status(powershell_startup_modification_info) data.update(T1504.get_base_data_by_status(status)) data.update({'info': powershell_startup_modification_info}) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index 80bfb952d..e7e2eb8e0 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -1,4 +1,5 @@ from monkey_island.cc.encryptor import encryptor +from common.utils.attack_utils import ScanStatus def parse_creds(attempt): @@ -44,3 +45,23 @@ def censor_hash(hash_, plain_chars=5): return "" hash_ = encryptor.dec(hash_) return hash_[0: plain_chars] + ' ...' + + +def extract_shell_startup_files_modification_info(shell_startup_files_modification_info, required_file_names): + required_shell_startup_files_modification_info = [] + for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: + if any(file_name in shell_startup_file_result[0] for file_name in required_file_names): + shell_startup_files_modification_info.append({ + 'machine': shell_startup_files_modification_info[0]['machine'], + 'result': shell_startup_file_result + }) + return required_shell_startup_files_modification_info + + +def get_shell_startup_files_modification_status(shell_startup_files_modification_info): + status = [] + for startup_file in shell_startup_files_modification_info: + status.append(startup_file['result'][1]) + status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ + if status else ScanStatus.UNSCANNED.value + return status From 6698de3edb7e430501df7d4b220658dca36b1592 Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 22 Jul 2020 01:08:31 +0530 Subject: [PATCH 16/27] Move data modification for PBA from frontend to backend --- .../telemetry/processing/post_breach.py | 30 +++++++++++++++---- .../report-components/security/PostBreach.js | 11 ------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 974a696d5..63cdfff48 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -1,4 +1,8 @@ -from common.data.post_breach_consts import POST_BREACH_COMMUNICATE_AS_NEW_USER +import copy + +from common.data.post_breach_consts import ( + POST_BREACH_COMMUNICATE_AS_NEW_USER, + POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) from monkey_island.cc.database import mongo from monkey_island.cc.models import Monkey from monkey_island.cc.services.telemetry.zero_trust_tests.communicate_as_new_user import \ @@ -12,16 +16,32 @@ def process_communicate_as_new_user_telemetry(telemetry_json): test_new_user_communication(current_monkey, success, message) +def process_shell_startup_file_modification_telemetry(telemetry_json): + modified_data = [] + for result in telemetry_json['data']['result']: + temp = copy.deepcopy(telemetry_json['data']) + temp['result'] = result + modified_data.append(temp) + telemetry_json['data'] = modified_data + + POST_BREACH_TELEMETRY_PROCESSING_FUNCS = { POST_BREACH_COMMUNICATE_AS_NEW_USER: process_communicate_as_new_user_telemetry, + POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: process_shell_startup_file_modification_telemetry, } def process_post_breach_telemetry(telemetry_json): - mongo.db.monkey.update( - {'guid': telemetry_json['monkey_guid']}, - {'$push': {'pba_results': telemetry_json['data']}}) - post_breach_action_name = telemetry_json["data"]["name"] if post_breach_action_name in POST_BREACH_TELEMETRY_PROCESSING_FUNCS: POST_BREACH_TELEMETRY_PROCESSING_FUNCS[post_breach_action_name](telemetry_json) + + if type(telemetry_json['data']) is list: + for pba_data in telemetry_json['data']: + mongo.db.monkey.update( + {'guid': telemetry_json['monkey_guid']}, + {'$push': {'pba_results': pba_data}}) + else: + mongo.db.monkey.update( + {'guid': telemetry_json['monkey_guid']}, + {'$push': {'pba_results': telemetry_json['data']}}) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js index 45eac8149..390ad6189 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js @@ -23,17 +23,6 @@ const subColumns = [ ]; let renderDetails = function (data) { - data.forEach(pba => { - if (typeof pba['result'][0] === "object") { // if `result` has more than one entry - let results = pba['result']; - let details = data.splice(data.indexOf(pba), 1); // remove that pba from `data` - results.forEach(result => { // add back those results to `data` as individual pba entries - let tempDetails = JSON.parse(JSON.stringify(details)); - tempDetails[0]['result'] = result; - data.push(tempDetails[0]); - }); - } - }); let defaultPageSize = data.length > pageSize ? pageSize : data.length; let showPagination = data.length > pageSize; return Date: Wed, 22 Jul 2020 01:57:11 +0530 Subject: [PATCH 17/27] Modify `run()` for "modify shell startup files" PBA --- .../actions/modify_shell_startup_files.py | 13 +------------ monkey/infection_monkey/post_breach/pba.py | 7 +++++-- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 3973724e0..352610c6b 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -21,7 +21,7 @@ class ModifyShellStartupFiles(PBA): super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) def run(self): - results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] + results = [pba.run(return_result=True) for pba in self.modify_shell_startup_PBA_list()] PostBreachTelem(self, results).send() def modify_shell_startup_PBA_list(self): @@ -51,14 +51,3 @@ class ModifyShellStartupFiles(PBA): super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, linux_cmd=linux_cmds, windows_cmd=windows_cmds) - - def run(self): - if self.command: - try: - output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() - if not output: - output = EXECUTION_WITHOUT_OUTPUT - return output, True - except subprocess.CalledProcessError as e: - # Return error output of the command - return e.output.decode(), False diff --git a/monkey/infection_monkey/post_breach/pba.py b/monkey/infection_monkey/post_breach/pba.py index a6a89edf8..0660449ad 100644 --- a/monkey/infection_monkey/post_breach/pba.py +++ b/monkey/infection_monkey/post_breach/pba.py @@ -54,7 +54,7 @@ class PBA(Plugin): """ return class_name in WormConfiguration.post_breach_actions - def run(self): + def run(self, return_result=False): """ Runs post breach action command """ @@ -63,7 +63,10 @@ class PBA(Plugin): result = exec_funct() if self.scripts_were_used_successfully(result): T1064Telem(ScanStatus.USED, f"Scripts were used to execute {self.name} post breach action.").send() - PostBreachTelem(self, result).send() + if return_result: + return result + else: + PostBreachTelem(self, result).send() else: LOG.debug(f"No command available for PBA '{self.name}' on current OS, skipping.") From 177b713930e96efb81694eb1eeb6fd3dc8b4b48e Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 22 Jul 2020 01:57:40 +0530 Subject: [PATCH 18/27] Fixes --- .../post_breach/actions/modify_shell_startup_files.py | 4 ---- .../cc/services/attack/technique_reports/T1156.py | 9 +++++---- .../cc/services/attack/technique_reports/T1504.py | 9 +++++---- .../attack/technique_reports/technique_report_tools.py | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 352610c6b..85f039628 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -1,5 +1,3 @@ -import subprocess - from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from infection_monkey.post_breach.pba import PBA @@ -7,8 +5,6 @@ from infection_monkey.post_breach.shell_startup_files.shell_startup_files_modifi get_commands_to_modify_shell_startup_files from infection_monkey.telemetry.post_breach_telem import PostBreachTelem -EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" - class ModifyShellStartupFiles(PBA): """ 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 c6ddcba93..ed61bbc94 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -2,8 +2,9 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.attack.technique_reports.technique_report_tools import \ - extract_shell_startup_files_modification_info, get_shell_startup_files_modification_status +from monkey_island.cc.services.attack.technique_reports.technique_report_tools import ( + extract_shell_startup_files_modification_info, + get_shell_startup_files_modification_status) __author__ = "shreyamalviya" @@ -17,8 +18,8 @@ class T1156(AttackTechnique): query = [{'$match': {'telem_category': 'post_breach', 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION}}, {'$project': {'_id': 0, - 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'machine': {'hostname': {'$arrayElemAt': ['$data.hostname', 0]}, + 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}] @staticmethod 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 4fd0a475a..4da6ffd17 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -2,8 +2,9 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.attack.technique_reports.technique_report_tools import \ - extract_shell_startup_files_modification_info, get_shell_startup_files_modification_status +from monkey_island.cc.services.attack.technique_reports.technique_report_tools import ( + extract_shell_startup_files_modification_info, + get_shell_startup_files_modification_status) __author__ = "shreyamalviya" @@ -17,8 +18,8 @@ class T1504(AttackTechnique): query = [{'$match': {'telem_category': 'post_breach', 'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION}}, {'$project': {'_id': 0, - 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'machine': {'hostname': {'$arrayElemAt': ['$data.hostname', 0]}, + 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}] @staticmethod diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index e7e2eb8e0..88dbaab58 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -1,5 +1,5 @@ -from monkey_island.cc.encryptor import encryptor from common.utils.attack_utils import ScanStatus +from monkey_island.cc.encryptor import encryptor def parse_creds(attempt): @@ -51,7 +51,7 @@ def extract_shell_startup_files_modification_info(shell_startup_files_modificati required_shell_startup_files_modification_info = [] for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: if any(file_name in shell_startup_file_result[0] for file_name in required_file_names): - shell_startup_files_modification_info.append({ + required_shell_startup_files_modification_info.append({ 'machine': shell_startup_files_modification_info[0]['machine'], 'result': shell_startup_file_result }) From b92fe47005ac5668f5d48fdc3fafb9dd4331ebdd Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 24 Jul 2020 13:13:11 +0530 Subject: [PATCH 19/27] Override `run()` for PBA "modify shell startup files" + assign EXECUTION_WITHOUT_OUTPUT to all relevant PBAs on the island side --- .../post_breach/actions/modify_shell_startup_files.py | 9 +++++++++ monkey/infection_monkey/post_breach/pba.py | 11 ++--------- .../cc/services/telemetry/processing/post_breach.py | 8 ++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 85f039628..fdc7e18dc 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -47,3 +47,12 @@ class ModifyShellStartupFiles(PBA): super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, linux_cmd=linux_cmds, windows_cmd=windows_cmds) + + def run(self): + if self.command: + try: + output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() + return output, True + except subprocess.CalledProcessError as e: + # Return error output of the command + return e.output.decode(), False \ No newline at end of file diff --git a/monkey/infection_monkey/post_breach/pba.py b/monkey/infection_monkey/post_breach/pba.py index 0660449ad..93d10d45e 100644 --- a/monkey/infection_monkey/post_breach/pba.py +++ b/monkey/infection_monkey/post_breach/pba.py @@ -13,8 +13,6 @@ LOG = logging.getLogger(__name__) __author__ = 'VakarisZ' -EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" - class PBA(Plugin): """ @@ -54,7 +52,7 @@ class PBA(Plugin): """ return class_name in WormConfiguration.post_breach_actions - def run(self, return_result=False): + def run(self): """ Runs post breach action command """ @@ -63,10 +61,7 @@ class PBA(Plugin): result = exec_funct() if self.scripts_were_used_successfully(result): T1064Telem(ScanStatus.USED, f"Scripts were used to execute {self.name} post breach action.").send() - if return_result: - return result - else: - PostBreachTelem(self, result).send() + PostBreachTelem(self, result).send() else: LOG.debug(f"No command available for PBA '{self.name}' on current OS, skipping.") @@ -93,8 +88,6 @@ class PBA(Plugin): """ try: output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() - if not output: - output = EXECUTION_WITHOUT_OUTPUT return output, True except subprocess.CalledProcessError as e: # Return error output of the command diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 63cdfff48..446ac0372 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -8,6 +8,8 @@ from monkey_island.cc.models import Monkey from monkey_island.cc.services.telemetry.zero_trust_tests.communicate_as_new_user import \ test_new_user_communication +EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" + def process_communicate_as_new_user_telemetry(telemetry_json): current_monkey = Monkey.get_single_monkey_by_guid(telemetry_json['monkey_guid']) @@ -38,10 +40,16 @@ def process_post_breach_telemetry(telemetry_json): if type(telemetry_json['data']) is list: for pba_data in telemetry_json['data']: + modify_blank_outputs(pba_data) mongo.db.monkey.update( {'guid': telemetry_json['monkey_guid']}, {'$push': {'pba_results': pba_data}}) else: + modify_blank_outputs(telemetry_json['data']) mongo.db.monkey.update( {'guid': telemetry_json['monkey_guid']}, {'$push': {'pba_results': telemetry_json['data']}}) + + def modify_blank_outputs(data): + if not data['result']: + data['result'] = EXECUTION_WITHOUT_OUTPUT From a5fd87c2aacabd3de6130008d256cf6c7de2ed43 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 24 Jul 2020 16:41:46 +0530 Subject: [PATCH 20/27] Modifications to get the telemetry feed and reports rendering properly --- .../actions/modify_shell_startup_files.py | 4 +- .../cc/resources/telemetry_feed.py | 6 +-- .../attack/technique_reports/T1136.py | 2 +- .../attack/technique_reports/T1154.py | 2 +- .../attack/technique_reports/T1158.py | 12 +++--- .../attack/technique_reports/T1166.py | 2 +- .../attack/technique_reports/T1168.py | 9 ++-- .../telemetry/processing/post_breach.py | 42 +++++++++---------- 8 files changed, 42 insertions(+), 37 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index fdc7e18dc..932007252 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -1,3 +1,5 @@ +import subprocess + from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from infection_monkey.post_breach.pba import PBA @@ -17,7 +19,7 @@ class ModifyShellStartupFiles(PBA): super().__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) def run(self): - results = [pba.run(return_result=True) for pba in self.modify_shell_startup_PBA_list()] + results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] PostBreachTelem(self, results).send() def modify_shell_startup_PBA_list(self): diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py index c278d2f36..17f263320 100644 --- a/monkey/monkey_island/cc/resources/telemetry_feed.py +++ b/monkey/monkey_island/cc/resources/telemetry_feed.py @@ -98,9 +98,9 @@ class TelemetryFeed(flask_restful.Resource): @staticmethod def get_post_breach_telem_brief(telem): - return '%s post breach action executed on %s (%s) machine.' % (telem['data']['name'], - telem['data']['hostname'], - telem['data']['ip']) + return '%s post breach action executed on %s (%s) machine.' % (telem['data'][0]['name'], + telem['data'][0]['hostname'], + telem['data'][0]['ip']) @staticmethod def should_show_brief(telem): diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1136.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1136.py index cb68d3a4f..042fd3c77 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1136.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1136.py @@ -18,7 +18,7 @@ class T1136(AttackTechnique): {'data.name': POST_BREACH_COMMUNICATE_AS_NEW_USER}]}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py index c7bace482..a48f3ebbd 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py @@ -16,7 +16,7 @@ class T1154(AttackTechnique): 'data.name': POST_BREACH_TRAP_COMMAND}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1158.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1158.py index 2db37bbbe..6cf9faeb8 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1158.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1158.py @@ -16,7 +16,7 @@ class T1158(AttackTechnique): 'data.name': POST_BREACH_HIDDEN_FILES}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod @@ -25,11 +25,11 @@ class T1158(AttackTechnique): hidden_file_info = list(mongo.db.telemetry.aggregate(T1158.query)) - status = [] - for pba_node in hidden_file_info: - status.append(pba_node['result'][1]) - status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ - if status else ScanStatus.UNSCANNED.value + status = ScanStatus.UNSCANNED.value + if hidden_file_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_HIDDEN_FILES, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1158.get_base_data_by_status(status)) data.update({'info': hidden_file_info}) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py index 3c5b9b0bf..84e213607 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py @@ -16,7 +16,7 @@ class T1166(AttackTechnique): 'data.name': POST_BREACH_SETUID_SETGID}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1168.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1168.py index 48298a7fe..bda495845 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1168.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1168.py @@ -17,7 +17,7 @@ class T1168(AttackTechnique): 'data.command': {'$regex': 'crontab'}}}, {'$project': {'_id': 0, 'machine': {'hostname': '$data.hostname', - 'ips': ['$data.ip']}, + 'ips': '$data.ip'}, 'result': '$data.result'}}] @staticmethod @@ -26,8 +26,11 @@ class T1168(AttackTechnique): job_scheduling_info = list(mongo.db.telemetry.aggregate(T1168.query)) - status = (ScanStatus.USED.value if job_scheduling_info[0]['result'][1] - else ScanStatus.SCANNED.value) if job_scheduling_info else ScanStatus.UNSCANNED.value + status = ScanStatus.UNSCANNED.value + if job_scheduling_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_JOB_SCHEDULING, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1168.get_base_data_by_status(status)) data.update({'info': job_scheduling_info}) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 446ac0372..0588dc396 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -18,38 +18,38 @@ def process_communicate_as_new_user_telemetry(telemetry_json): test_new_user_communication(current_monkey, success, message) -def process_shell_startup_file_modification_telemetry(telemetry_json): - modified_data = [] - for result in telemetry_json['data']['result']: - temp = copy.deepcopy(telemetry_json['data']) - temp['result'] = result - modified_data.append(temp) +def modify_data(telemetry_json): + modified_data = [telemetry_json['data']] + if type(telemetry_json['data']['result'][0]) is list: + modified_data = [] + for result in telemetry_json['data']['result']: + temp = copy.deepcopy(telemetry_json['data']) + temp['result'] = result + modified_data.append(temp) telemetry_json['data'] = modified_data POST_BREACH_TELEMETRY_PROCESSING_FUNCS = { POST_BREACH_COMMUNICATE_AS_NEW_USER: process_communicate_as_new_user_telemetry, - POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: process_shell_startup_file_modification_telemetry, } def process_post_breach_telemetry(telemetry_json): + def modify_blank_outputs(data): + if not data['result'][0]: + data['result'][0] = EXECUTION_WITHOUT_OUTPUT + + def update_data(data): + modify_blank_outputs(data) + mongo.db.monkey.update( + {'guid': telemetry_json['monkey_guid']}, + {'$push': {'pba_results': data}}) + post_breach_action_name = telemetry_json["data"]["name"] if post_breach_action_name in POST_BREACH_TELEMETRY_PROCESSING_FUNCS: POST_BREACH_TELEMETRY_PROCESSING_FUNCS[post_breach_action_name](telemetry_json) - if type(telemetry_json['data']) is list: - for pba_data in telemetry_json['data']: - modify_blank_outputs(pba_data) - mongo.db.monkey.update( - {'guid': telemetry_json['monkey_guid']}, - {'$push': {'pba_results': pba_data}}) - else: - modify_blank_outputs(telemetry_json['data']) - mongo.db.monkey.update( - {'guid': telemetry_json['monkey_guid']}, - {'$push': {'pba_results': telemetry_json['data']}}) + modify_data(telemetry_json) - def modify_blank_outputs(data): - if not data['result']: - data['result'] = EXECUTION_WITHOUT_OUTPUT + for pba_data in telemetry_json['data']: + update_data(pba_data) From e19c3c20eb63f434a28f5ce6eee4349cd6aa1992 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 24 Jul 2020 22:43:50 +0530 Subject: [PATCH 21/27] Generate T1156 and T1504 reports via mongo query --- .../attack/technique_reports/T1156.py | 20 ++++++++++--------- .../attack/technique_reports/T1504.py | 19 +++++++++--------- .../technique_report_tools.py | 20 ------------------- 3 files changed, 21 insertions(+), 38 deletions(-) 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 ed61bbc94..a379c3907 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -1,10 +1,8 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION +from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.attack.technique_reports.technique_report_tools import ( - extract_shell_startup_files_modification_info, - get_shell_startup_files_modification_status) __author__ = "shreyamalviya" @@ -20,18 +18,22 @@ class T1156(AttackTechnique): {'$project': {'_id': 0, 'machine': {'hostname': {'$arrayElemAt': ['$data.hostname', 0]}, 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, - 'result': '$data.result'}}] + 'result': '$data.result'}}, + {'$unwind': '$result'}, + {'$match': {'$or': [{'result': {'$regex': '\.bash'}}, + {'result': {'$regex': '\.profile'}}]}}] @staticmethod def get_report_data(): data = {'title': T1156.technique_title(), 'info': []} - shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) + bash_startup_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) - bash_startup_modification_info =\ - extract_shell_startup_files_modification_info(shell_startup_files_modification_info, [".bash", ".profile"]) - - status = get_shell_startup_files_modification_status(bash_startup_modification_info) + status = ScanStatus.UNSCANNED.value + if bash_startup_modification_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1156.get_base_data_by_status(status)) data.update({'info': bash_startup_modification_info}) 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 4da6ffd17..b1013085e 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -1,10 +1,8 @@ from common.data.post_breach_consts import \ POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION +from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.attack.technique_reports.technique_report_tools import ( - extract_shell_startup_files_modification_info, - get_shell_startup_files_modification_status) __author__ = "shreyamalviya" @@ -20,18 +18,21 @@ class T1504(AttackTechnique): {'$project': {'_id': 0, 'machine': {'hostname': {'$arrayElemAt': ['$data.hostname', 0]}, 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, - 'result': '$data.result'}}] + 'result': '$data.result'}}, + {'$unwind': '$result'}, + {'$match': {'result': {'$regex': 'profile\.ps1'}}}] @staticmethod def get_report_data(): data = {'title': T1504.technique_title(), 'info': []} - shell_startup_files_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) + powershell_startup_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) - powershell_startup_modification_info =\ - extract_shell_startup_files_modification_info(shell_startup_files_modification_info, ["profile.ps1"]) - - status = get_shell_startup_files_modification_status(powershell_startup_modification_info) + status = ScanStatus.UNSCANNED.value + if powershell_startup_modification_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1504.get_base_data_by_status(status)) data.update({'info': powershell_startup_modification_info}) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index 88dbaab58..44b2fdd82 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -45,23 +45,3 @@ def censor_hash(hash_, plain_chars=5): return "" hash_ = encryptor.dec(hash_) return hash_[0: plain_chars] + ' ...' - - -def extract_shell_startup_files_modification_info(shell_startup_files_modification_info, required_file_names): - required_shell_startup_files_modification_info = [] - for shell_startup_file_result in shell_startup_files_modification_info[0]['result']: - if any(file_name in shell_startup_file_result[0] for file_name in required_file_names): - required_shell_startup_files_modification_info.append({ - 'machine': shell_startup_files_modification_info[0]['machine'], - 'result': shell_startup_file_result - }) - return required_shell_startup_files_modification_info - - -def get_shell_startup_files_modification_status(shell_startup_files_modification_info): - status = [] - for startup_file in shell_startup_files_modification_info: - status.append(startup_file['result'][1]) - status = (ScanStatus.USED.value if any(status) else ScanStatus.SCANNED.value)\ - if status else ScanStatus.UNSCANNED.value - return status From 5f53ea995c7ba03b0de43ac06054b0540d2a98d3 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 24 Jul 2020 23:01:37 +0530 Subject: [PATCH 22/27] Pass build --- .../post_breach/actions/modify_shell_startup_files.py | 4 +++- .../cc/services/attack/technique_reports/T1156.py | 4 ++-- .../cc/services/attack/technique_reports/T1504.py | 2 +- .../attack/technique_reports/technique_report_tools.py | 1 - 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 932007252..5e8208c96 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -53,7 +53,9 @@ class ModifyShellStartupFiles(PBA): def run(self): if self.command: try: - output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() + output = subprocess.check_output(self.command, # noqa: DUO116 + stderr=subprocess.STDOUT, + shell=True).decode() return output, True except subprocess.CalledProcessError as e: # Return error output of the command 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 a379c3907..a9c0ea338 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -20,8 +20,8 @@ class T1156(AttackTechnique): 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}, {'$unwind': '$result'}, - {'$match': {'$or': [{'result': {'$regex': '\.bash'}}, - {'result': {'$regex': '\.profile'}}]}}] + {'$match': {'$or': [{'result': {'$regex': '\.bash'}}, # noqa: W605 + {'result': {'$regex': '\.profile'}}]}}] # noqa: W605 @staticmethod def get_report_data(): 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 b1013085e..7bfda1d8e 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -20,7 +20,7 @@ class T1504(AttackTechnique): 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}, {'$unwind': '$result'}, - {'$match': {'result': {'$regex': 'profile\.ps1'}}}] + {'$match': {'result': {'$regex': 'profile\.ps1'}}}] # noqa: W605 @staticmethod def get_report_data(): diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index 44b2fdd82..80bfb952d 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -1,4 +1,3 @@ -from common.utils.attack_utils import ScanStatus from monkey_island.cc.encryptor import encryptor From 4833ec906a18ad5d979274813381259c56301623 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sun, 26 Jul 2020 23:25:30 +0530 Subject: [PATCH 23/27] Small CR changes --- .../post_breach/actions/modify_shell_startup_files.py | 2 +- .../cc/services/attack/technique_reports/T1156.py | 4 ++-- .../cc/services/attack/technique_reports/T1504.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 5e8208c96..f7bd43a6e 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -59,4 +59,4 @@ class ModifyShellStartupFiles(PBA): return output, True except subprocess.CalledProcessError as e: # Return error output of the command - return e.output.decode(), False \ No newline at end of file + return e.output.decode(), False 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 a9c0ea338..64c401e8f 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -20,8 +20,8 @@ class T1156(AttackTechnique): 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}, {'$unwind': '$result'}, - {'$match': {'$or': [{'result': {'$regex': '\.bash'}}, # noqa: W605 - {'result': {'$regex': '\.profile'}}]}}] # noqa: W605 + {'$match': {'$or': [{'result': {'$regex': r'\.bash'}}, + {'result': {'$regex': r'\.profile'}}]}}] @staticmethod def get_report_data(): 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 7bfda1d8e..05568fcb8 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -20,7 +20,7 @@ class T1504(AttackTechnique): 'ips': [{'$arrayElemAt': ['$data.ip', 0]}]}, 'result': '$data.result'}}, {'$unwind': '$result'}, - {'$match': {'result': {'$regex': 'profile\.ps1'}}}] # noqa: W605 + {'$match': {'result': {'$regex': r'profile\.ps1'}}}] @staticmethod def get_report_data(): From 3bc9fd5040ab7e32d5432314a4a74773b52a78e3 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sun, 26 Jul 2020 23:25:58 +0530 Subject: [PATCH 24/27] Improve code readibility TODO: Add tests --- .../telemetry/processing/post_breach.py | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 0588dc396..0cb8fcb1e 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -18,38 +18,42 @@ def process_communicate_as_new_user_telemetry(telemetry_json): test_new_user_communication(current_monkey, success, message) -def modify_data(telemetry_json): - modified_data = [telemetry_json['data']] - if type(telemetry_json['data']['result'][0]) is list: - modified_data = [] - for result in telemetry_json['data']['result']: - temp = copy.deepcopy(telemetry_json['data']) - temp['result'] = result - modified_data.append(temp) - telemetry_json['data'] = modified_data - - POST_BREACH_TELEMETRY_PROCESSING_FUNCS = { POST_BREACH_COMMUNICATE_AS_NEW_USER: process_communicate_as_new_user_telemetry, } def process_post_breach_telemetry(telemetry_json): - def modify_blank_outputs(data): - if not data['result'][0]: - data['result'][0] = EXECUTION_WITHOUT_OUTPUT + def convert_telem_data_to_list(data): + modified_data = [data] + if type(data['result'][0]) is list: # multiple results in one pba + modified_data = separate_results_to_single_pba_telems(data) + return modified_data + + def separate_results_to_single_pba_telems(data): + modified_data = [] + for result in data['result']: + temp = copy.deepcopy(data) + temp['result'] = result + modified_data.append(temp) + return modified_data def update_data(data): - modify_blank_outputs(data) + data = add_message_for_blank_outputs(data) mongo.db.monkey.update( {'guid': telemetry_json['monkey_guid']}, {'$push': {'pba_results': data}}) + def add_message_for_blank_outputs(data): + if not data['result'][0]: + data['result'][0] = EXECUTION_WITHOUT_OUTPUT + return data + post_breach_action_name = telemetry_json["data"]["name"] if post_breach_action_name in POST_BREACH_TELEMETRY_PROCESSING_FUNCS: POST_BREACH_TELEMETRY_PROCESSING_FUNCS[post_breach_action_name](telemetry_json) - modify_data(telemetry_json) + telemetry_json['data'] = convert_telem_data_to_list(telemetry_json['data']) for pba_data in telemetry_json['data']: update_data(pba_data) From 56975acf81476d45a8f55817e383f16379c94f49 Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 29 Jul 2020 14:51:00 +0530 Subject: [PATCH 25/27] Mongo query changes for T1156 and T1504 --- .../cc/services/attack/technique_reports/T1156.py | 12 ++++++++++++ .../cc/services/attack/technique_reports/T1504.py | 11 +++++++++++ 2 files changed, 23 insertions(+) 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 f09b70391..2841ed0ad 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -12,3 +12,15 @@ 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 db1ea8aa5..8d8956e6b 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -12,3 +12,14 @@ 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'}}}] From 6afeab003a0354b0cdc260ad45d04c249cec3814 Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 29 Jul 2020 15:02:55 +0530 Subject: [PATCH 26/27] Pass build --- .../cc/services/attack/technique_reports/pba_technique.py | 1 - .../cc/services/telemetry/processing/post_breach.py | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) 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 72188eb4e..da475c697 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 @@ -3,7 +3,6 @@ from typing import List from common.utils.attack_utils import ScanStatus from monkey_island.cc.database import mongo -from monkey_island.cc.services.attack.attack_config import AttackConfig from monkey_island.cc.services.attack.technique_reports import AttackTechnique diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index 0cb8fcb1e..fb54522b6 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -1,8 +1,6 @@ import copy -from common.data.post_breach_consts import ( - POST_BREACH_COMMUNICATE_AS_NEW_USER, - POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) +from common.data.post_breach_consts import POST_BREACH_COMMUNICATE_AS_NEW_USER from monkey_island.cc.database import mongo from monkey_island.cc.models import Monkey from monkey_island.cc.services.telemetry.zero_trust_tests.communicate_as_new_user import \ From d37fea06d82aacf0ca0647d93bb8dcccbe02e462 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 29 Jul 2020 12:49:51 +0300 Subject: [PATCH 27/27] Grouped Shell Startup modification PBA outputs data into a single PBA --- .../report-components/security/PostBreach.js | 2 ++ .../security/PostBreachParser.js | 33 +++++++++++++++++++ .../cc/ui/src/styles/report/ReportPage.scss | 2 ++ 3 files changed, 37 insertions(+) create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreachParser.js diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js index cc9ea1c20..4df0c33a1 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js @@ -2,6 +2,7 @@ import React from 'react'; import ReactTable from 'react-table'; import Pluralize from 'pluralize'; import {renderIpAddresses} from "../common/RenderArrays"; +import parsePbaResults from "./PostBreachParser"; let renderMachine = function (data) { return
{data.label} ( {renderIpAddresses(data)} )
@@ -54,6 +55,7 @@ class PostBreachComponent extends React.Component { let pbaMachines = this.props.data.filter(function (value) { return (value.pba_results !== 'None' && value.pba_results.length > 0); }); + pbaMachines = pbaMachines.map(pbaData => parsePbaResults(pbaData)); let defaultPageSize = pbaMachines.length > pageSize ? pageSize : pbaMachines.length; let showPagination = pbaMachines > pageSize; const pbaCount = pbaMachines.reduce((accumulated, pbaMachine) => accumulated+pbaMachine["pba_results"].length, 0); diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreachParser.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreachParser.js new file mode 100644 index 000000000..39dfecf7e --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreachParser.js @@ -0,0 +1,33 @@ +export default function parsePbaResults(results) { + results.pba_results = aggregateShellStartupPba(results.pba_results); + return results; +} + +const SHELL_STARTUP_NAME = 'Modify shell startup file'; + +function aggregateShellStartupPba(results) { + let isSuccess = false; + let aggregatedPbaResult = undefined; + let successfulOutputs = ''; + let failedOutputs = ''; + + for(let i = 0; i < results.length; i++){ + if(results[i].name === SHELL_STARTUP_NAME && aggregatedPbaResult === undefined){ + aggregatedPbaResult = results[i]; + } + if(results[i].name === SHELL_STARTUP_NAME && results[i].result[1]){ + successfulOutputs += results[i].result[0]; + isSuccess = true; + } + if(results[i].name === SHELL_STARTUP_NAME && ! results[i].result[1]){ + failedOutputs += results[i].result[0]; + } + } + if(aggregatedPbaResult === undefined) return; + + results = results.filter(result => result.name !== SHELL_STARTUP_NAME); + aggregatedPbaResult.result[0] = successfulOutputs + failedOutputs; + aggregatedPbaResult.result[1] = isSuccess; + results.push(aggregatedPbaResult); + return results; +} diff --git a/monkey/monkey_island/cc/ui/src/styles/report/ReportPage.scss b/monkey/monkey_island/cc/ui/src/styles/report/ReportPage.scss index 0c618bd7f..5fb8252fe 100644 --- a/monkey/monkey_island/cc/ui/src/styles/report/ReportPage.scss +++ b/monkey/monkey_island/cc/ui/src/styles/report/ReportPage.scss @@ -60,10 +60,12 @@ .pba-danger { background-color: #ffc7af; + white-space: pre-wrap; } .pba-success { background-color: #afd2a2; + white-space: pre-wrap; } div.report-wrapper {