From a9c763cd9cfa8552dadeb07981dbac2164080c7d Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 12 Jun 2020 02:44:17 +0530 Subject: [PATCH 01/18] Add linux PBA + report components --- monkey/common/data/post_breach_consts.py | 1 + .../actions/modify_shell_startup_files.py | 32 +++++++++++++ .../linux/shell_startup_files_modification.py | 16 +++++++ .../utils/shell_startup_files_modification.py | 10 +++++ .../shell_startup_files_modification.py | 3 ++ .../cc/services/attack/attack_report.py | 5 ++- .../cc/services/attack/attack_schema.py | 10 +++++ .../attack/technique_reports/T1156.py | 37 +++++++++++++++ .../cc/services/config_schema.py | 11 ++++- .../src/components/attack/techniques/T1156.js | 45 +++++++++++++++++++ 10 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py create mode 100644 monkey/infection_monkey/utils/linux/shell_startup_files_modification.py create mode 100644 monkey/infection_monkey/utils/shell_startup_files_modification.py create mode 100644 monkey/infection_monkey/utils/windows/shell_startup_files_modification.py create mode 100644 monkey/monkey_island/cc/services/attack/technique_reports/T1156.py create mode 100644 monkey/monkey_island/cc/ui/src/components/attack/techniques/T1156.js diff --git a/monkey/common/data/post_breach_consts.py b/monkey/common/data/post_breach_consts.py index dee4f67d0..1e36f9e20 100644 --- a/monkey/common/data/post_breach_consts.py +++ b/monkey/common/data/post_breach_consts.py @@ -1,3 +1,4 @@ POST_BREACH_COMMUNICATE_AS_NEW_USER = "Communicate as new user" POST_BREACH_BACKDOOR_USER = "Backdoor user" POST_BREACH_FILE_EXECUTION = "File execution" +POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION = "Modify shell startup file" 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 new file mode 100644 index 000000000..a2d92db6c --- /dev/null +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -0,0 +1,32 @@ +from common.data.post_breach_consts import POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION +from infection_monkey.post_breach.pba import PBA +from infection_monkey.utils.shell_startup_files_modification import\ + get_commands_to_modify_shell_startup_files +from infection_monkey.utils.environment import is_windows_os + + +class ModifyShellStartupFiles(PBA): + """ + This PBA attempts to modify shell startup files, + like ~/.profile, ~/.bashrc, ~/.bash_profile in linux, + and profile.ps1 in windows. + """ + + def __init__(self): + super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) + + def run(self): + (cmds_for_linux, shell_startup_files_for_linux), windows_cmds = get_commands_to_modify_shell_startup_files() + + if is_windows_os(): + super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, + linux_cmd=' '.join(linux_cmds), + windows_cmd=windows_cmds) + super(ModifyShellStartupFiles, self).run() + else: + for shell_startup_file in shell_startup_files_for_linux: + linux_cmds = ' '.join(cmds_for_linux).format(shell_startup_file) + super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, + linux_cmd=linux_cmds, + windows_cmd=windows_cmds) + super(ModifyShellStartupFiles, self).run() diff --git a/monkey/infection_monkey/utils/linux/shell_startup_files_modification.py b/monkey/infection_monkey/utils/linux/shell_startup_files_modification.py new file mode 100644 index 000000000..f6f8c3ffd --- /dev/null +++ b/monkey/infection_monkey/utils/linux/shell_startup_files_modification.py @@ -0,0 +1,16 @@ +BASH_STARTUP_FILES = ["~/.bashrc", "~/.profile", "~/.bash_profile"] + + +def get_linux_commands_to_modify_shell_startup_files(): + return [ + 'if [ -f {0} ] ;', # does the file exist? + 'then', + 'echo \"# Succesfully modified {0}\" |', + 'tee -a', + '{0}', # add comment to file + '&&', + 'sed -i \'$d\' {0} ;', # remove last line of file + 'else', + 'echo \"{0} does not exist\" ; fi' # mention if file does not exist + ],\ + BASH_STARTUP_FILES diff --git a/monkey/infection_monkey/utils/shell_startup_files_modification.py b/monkey/infection_monkey/utils/shell_startup_files_modification.py new file mode 100644 index 000000000..c97ca34b7 --- /dev/null +++ b/monkey/infection_monkey/utils/shell_startup_files_modification.py @@ -0,0 +1,10 @@ +from infection_monkey.utils.linux.shell_startup_files_modification import\ + get_linux_commands_to_modify_shell_startup_files +from infection_monkey.utils.windows.shell_startup_files_modification import\ + get_windows_commands_to_modify_shell_startup_files + + +def get_commands_to_modify_shell_startup_files(): + linux_cmds = get_linux_commands_to_modify_shell_startup_files() + windows_cmds = get_windows_commands_to_modify_shell_startup_files() + return linux_cmds, windows_cmds diff --git a/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py b/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py new file mode 100644 index 000000000..efc9480d8 --- /dev/null +++ b/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py @@ -0,0 +1,3 @@ +def get_windows_commands_to_modify_shell_startup_files(): + # TODO: add for powershell + return 'dir' diff --git a/monkey/monkey_island/cc/services/attack/attack_report.py b/monkey/monkey_island/cc/services/attack/attack_report.py index c7130158b..7f8576941 100644 --- a/monkey/monkey_island/cc/services/attack/attack_report.py +++ b/monkey/monkey_island/cc/services/attack/attack_report.py @@ -4,7 +4,7 @@ from monkey_island.cc.models import Monkey from monkey_island.cc.services.attack.technique_reports import T1210, T1197, T1110, T1075, T1003, T1059, T1086, T1082 from monkey_island.cc.services.attack.technique_reports import T1145, T1105, T1065, T1035, T1129, T1106, T1107, T1188 from monkey_island.cc.services.attack.technique_reports import T1090, T1041, T1222, T1005, T1018, T1016, T1021, T1064 -from monkey_island.cc.services.attack.technique_reports import T1136 +from monkey_island.cc.services.attack.technique_reports import T1136, T1156 from monkey_island.cc.services.attack.attack_config import AttackConfig from monkey_island.cc.database import mongo from monkey_island.cc.services.reporting.report_generation_synchronisation import safe_generate_attack_report @@ -37,7 +37,8 @@ TECHNIQUES = {'T1210': T1210.T1210, 'T1016': T1016.T1016, 'T1021': T1021.T1021, 'T1064': T1064.T1064, - 'T1136': T1136.T1136 + 'T1136': T1136.T1136, + 'T1156': T1156.T1156 } REPORT_NAME = 'new_report' diff --git a/monkey/monkey_island/cc/services/attack/attack_schema.py b/monkey/monkey_island/cc/services/attack/attack_schema.py index 177dc9eaa..c834faab3 100644 --- a/monkey/monkey_island/cc/services/attack/attack_schema.py +++ b/monkey/monkey_island/cc/services/attack/attack_schema.py @@ -71,6 +71,16 @@ SCHEMA = { "type": "object", "link": "https://attack.mitre.org/tactics/TA0003/", "properties": { + "T1156": { + "title": ".bash_profile and .bashrc", + "type": "bool", + "value": True, + "necessary": False, + "link": "https://attack.mitre.org/techniques/T1156", + "description": "Adversaries may abuse shell scripts by " + "inserting arbitrary shell commands to gain persistence, which " + "would be executed every time the user logs in or opens a new shell." + }, "T1136": { "title": "Create account", "type": "bool", diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py new file mode 100644 index 000000000..96028865a --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -0,0 +1,37 @@ +from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.services.reporting.report import ReportService +from common.utils.attack_utils import ScanStatus +from common.data.post_breach_consts import POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION + + +__author__ = "shreyamalviya" + + +class T1156(AttackTechnique): + tech_id = "T1156" + unscanned_msg = "Monkey did not try modifying shell startup files on the system." + scanned_msg = "Monkey tried modifying shell startup files on the system but failed." + used_msg = "Monkey modified shell startup files on the system." + + @staticmethod + def get_report_data(): + data = {'title': T1156.technique_title(), 'info': []} + + scanned_nodes = ReportService.get_scanned() + status = ScanStatus.UNSCANNED.value + + for node in scanned_nodes: + if node['pba_results'] != 'None': + for pba in node['pba_results']: + if pba['name'] == POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: + status = ScanStatus.USED.value if pba['result'][1]\ + else ScanStatus.SCANNED.value + data['info'].append({ + 'machine': { + 'hostname': pba['hostname'], + 'ips': node['ip_addresses'] + }, + 'result': pba['result'][0].replace('#', '') + }) + data.update(T1156.get_base_data_by_status(status)) + return data diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index b6668af38..a1e8bcb3d 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -160,6 +160,14 @@ SCHEMA = { "title": "Communicate as new user", "attack_techniques": ["T1136"] }, + { + "type": "string", + "enum": [ + "ModifyShellStartupFiles" + ], + "title": "Modify shell startup files", + "attack_techniques": ["T1156"] + } ], }, "finger_classes": { @@ -379,7 +387,8 @@ SCHEMA = { }, "default": [ "BackdoorUser", - "CommunicateAsNewUser" + "CommunicateAsNewUser", + "ModifyShellStartupFiles" ], "description": "List of actions the Monkey will run post breach" }, diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1156.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1156.js new file mode 100644 index 000000000..ce136284c --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1156.js @@ -0,0 +1,45 @@ +import React from 'react'; +import ReactTable from 'react-table'; +import {renderMachineFromSystemData, ScanStatus} from './Helpers'; +import MitigationsComponent from './MitigationsComponent'; + +class T1156 extends React.Component { + + constructor(props) { + super(props); + } + + static getColumns() { + return ([{ + columns: [ + { Header: 'Machine', + id: 'machine', + accessor: x => renderMachineFromSystemData(x.machine), + style: {'whiteSpace': 'unset'}}, + { Header: 'Result', + id: 'result', + accessor: x => x.result, + style: {'whiteSpace': 'unset'}} + ] + }]) + } + + render() { + return ( +
+
{this.props.data.message}
+
+ {this.props.data.status === ScanStatus.USED ? + : ''} + +
+ ); + } + } + + export default T1156; From e2d35ca2674f6b48ea49bb03d2fdf99cbfa3cdde Mon Sep 17 00:00:00 2001 From: Shreya Date: Sat, 13 Jun 2020 19:37:01 +0530 Subject: [PATCH 02/18] Simpler bash commands for linux PBA --- .../utils/linux/shell_startup_files_modification.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/monkey/infection_monkey/utils/linux/shell_startup_files_modification.py b/monkey/infection_monkey/utils/linux/shell_startup_files_modification.py index f6f8c3ffd..8c54b9168 100644 --- a/monkey/infection_monkey/utils/linux/shell_startup_files_modification.py +++ b/monkey/infection_monkey/utils/linux/shell_startup_files_modification.py @@ -3,14 +3,11 @@ BASH_STARTUP_FILES = ["~/.bashrc", "~/.profile", "~/.bash_profile"] def get_linux_commands_to_modify_shell_startup_files(): return [ - 'if [ -f {0} ] ;', # does the file exist? - 'then', - 'echo \"# Succesfully modified {0}\" |', - 'tee -a', - '{0}', # add comment to file + 'echo \"# Succesfully modified {0}\"', + '3<{0} 3<&- |', # check for existence of file + 'tee -a', # append to file + '{0}', '&&', - 'sed -i \'$d\' {0} ;', # remove last line of file - 'else', - 'echo \"{0} does not exist\" ; fi' # mention if file does not exist + 'sed -i \'$d\' {0}', # remove last line of file ],\ BASH_STARTUP_FILES From dfa34e602f9fd89e01f13c5b1b466d1a9e1d1adf Mon Sep 17 00:00:00 2001 From: Shreya Date: Sat, 13 Jun 2020 21:09:19 +0530 Subject: [PATCH 03/18] Started T1504 implementation Add to `attack_schema.py`, `attack_report.py` Add report `T1504.js` --- .../cc/services/attack/attack_report.py | 5 ++- .../cc/services/attack/attack_schema.py | 27 +++++++++++ .../src/components/attack/techniques/T1504.js | 45 +++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 monkey/monkey_island/cc/ui/src/components/attack/techniques/T1504.js diff --git a/monkey/monkey_island/cc/services/attack/attack_report.py b/monkey/monkey_island/cc/services/attack/attack_report.py index 7f8576941..b2ad3234a 100644 --- a/monkey/monkey_island/cc/services/attack/attack_report.py +++ b/monkey/monkey_island/cc/services/attack/attack_report.py @@ -4,7 +4,7 @@ from monkey_island.cc.models import Monkey from monkey_island.cc.services.attack.technique_reports import T1210, T1197, T1110, T1075, T1003, T1059, T1086, T1082 from monkey_island.cc.services.attack.technique_reports import T1145, T1105, T1065, T1035, T1129, T1106, T1107, T1188 from monkey_island.cc.services.attack.technique_reports import T1090, T1041, T1222, T1005, T1018, T1016, T1021, T1064 -from monkey_island.cc.services.attack.technique_reports import T1136, T1156 +from monkey_island.cc.services.attack.technique_reports import T1136, T1156, T1504 from monkey_island.cc.services.attack.attack_config import AttackConfig from monkey_island.cc.database import mongo from monkey_island.cc.services.reporting.report_generation_synchronisation import safe_generate_attack_report @@ -38,7 +38,8 @@ TECHNIQUES = {'T1210': T1210.T1210, 'T1021': T1021.T1021, 'T1064': T1064.T1064, 'T1136': T1136.T1136, - 'T1156': T1156.T1156 + 'T1156': T1156.T1156, + 'T1504': T1504.T1504 } REPORT_NAME = 'new_report' diff --git a/monkey/monkey_island/cc/services/attack/attack_schema.py b/monkey/monkey_island/cc/services/attack/attack_schema.py index c834faab3..7ef15a509 100644 --- a/monkey/monkey_island/cc/services/attack/attack_schema.py +++ b/monkey/monkey_island/cc/services/attack/attack_schema.py @@ -89,6 +89,33 @@ SCHEMA = { "link": "https://attack.mitre.org/techniques/T1136", "description": "Adversaries with a sufficient level of access " "may create a local system, domain, or cloud tenant account." + }, + "T1504": { + "title": "PowerShell profile", + "type": "bool", + "value": True, + "necessary": False, + "link": "https://attack.mitre.org/techniques/T1504", + "description": "Adversaries may gain persistence and elevate privileges " + "in certain situations by abusing PowerShell profiles which " + "are scripts that run when PowerShell starts." + } + } + }, + "privilege_escalation": { + "title": "Privilege escalation", + "type": "object", + "link": "https://attack.mitre.org/tactics/TA0004/", + "properties": { + "T1504": { + "title": "PowerShell profile", + "type": "bool", + "value": True, + "necessary": False, + "link": "https://attack.mitre.org/techniques/T1504", + "description": "Adversaries may gain persistence and elevate privileges " + "in certain situations by abusing PowerShell profiles which " + "are scripts that run when PowerShell starts." } } }, diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1504.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1504.js new file mode 100644 index 000000000..f85bbffd2 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1504.js @@ -0,0 +1,45 @@ +import React from 'react'; +import ReactTable from 'react-table'; +import {renderMachineFromSystemData, ScanStatus} from './Helpers'; +import MitigationsComponent from './MitigationsComponent'; + +class T1504 extends React.Component { + + constructor(props) { + super(props); + } + + static getColumns() { + return ([{ + columns: [ + { Header: 'Machine', + id: 'machine', + accessor: x => renderMachineFromSystemData(x.machine), + style: {'whiteSpace': 'unset'}}, + { Header: 'Result', + id: 'result', + accessor: x => x.result, + style: {'whiteSpace': 'unset'}} + ] + }]) + } + + render() { + return ( +
+
{this.props.data.message}
+
+ {this.props.data.status === ScanStatus.USED ? + : ''} + +
+ ); + } + } + + export default T1504; From 3fe4dd679bc5d829a59c141c91848bcc4e29ad0a Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 15 Jun 2020 17:42:11 +0530 Subject: [PATCH 04/18] Pass empty string to linux_cmds if OS is windows --- .../post_breach/actions/modify_shell_startup_files.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a2d92db6c..a526acad6 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 @@ -20,7 +20,7 @@ class ModifyShellStartupFiles(PBA): if is_windows_os(): super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - linux_cmd=' '.join(linux_cmds), + linux_cmd='', # windows so won't matter windows_cmd=windows_cmds) super(ModifyShellStartupFiles, self).run() else: From 1b040dc874d1ed614b7bb6eb9cda39da312b2ce1 Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 15 Jun 2020 17:44:28 +0530 Subject: [PATCH 05/18] Add windows PBA --- .../windows/shell_startup_files_modification.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py b/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py index efc9480d8..15e44b832 100644 --- a/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py +++ b/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py @@ -1,3 +1,12 @@ +SHELL_STARTUP_FILE = '$Profile' + + def get_windows_commands_to_modify_shell_startup_files(): - # TODO: add for powershell - return 'dir' + return [ + 'powershell.exe', # run with powershell + 'Add-Content {0} '.format(SHELL_STARTUP_FILE), + '\"# Successfully modified {0}\" ;'.format(SHELL_STARTUP_FILE), # add line to $profile + 'cat {0} | Select -last 1 ;'.format(SHELL_STARTUP_FILE), # print last line of $profile + '$OldProfile = cat {0} | Select -skiplast 1 ;'.format(SHELL_STARTUP_FILE), + 'Set-Content {0} -Value $OldProfile ;'.format(SHELL_STARTUP_FILE) # remove last line of $profile +] From 8bb5096addf22e6aaf0d581f338c157fd981ffa5 Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 15 Jun 2020 17:45:23 +0530 Subject: [PATCH 06/18] Add T1504 report data + modify T1156 report data --- .../attack/technique_reports/T1156.py | 19 +++++----- .../attack/technique_reports/T1504.py | 38 +++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 monkey/monkey_island/cc/services/attack/technique_reports/T1504.py 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 96028865a..b618e743a 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -24,14 +24,15 @@ class T1156(AttackTechnique): if node['pba_results'] != 'None': for pba in node['pba_results']: if pba['name'] == POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: - status = ScanStatus.USED.value if pba['result'][1]\ - else ScanStatus.SCANNED.value - data['info'].append({ - 'machine': { - 'hostname': pba['hostname'], - 'ips': node['ip_addresses'] - }, - 'result': pba['result'][0].replace('#', '') - }) + if 'powershell.exe' not in pba['command']: + status = ScanStatus.USED.value if pba['result'][1]\ + else ScanStatus.SCANNED.value + data['info'].append({ + 'machine': { + 'hostname': pba['hostname'], + 'ips': node['ip_addresses'] + }, + 'result': pba['result'][0].replace('#', '') + }) data.update(T1156.get_base_data_by_status(status)) 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 new file mode 100644 index 000000000..585599c86 --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -0,0 +1,38 @@ +from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.services.reporting.report import ReportService +from common.utils.attack_utils import ScanStatus +from common.data.post_breach_consts import POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION + + +__author__ = "shreyamalviya" + + +class T1504(AttackTechnique): + tech_id = "T1504" + unscanned_msg = "Monkey did not try modifying shell startup files on the system." + scanned_msg = "Monkey tried modifying shell startup files on the system but failed." + used_msg = "Monkey modified shell startup files on the system." + + @staticmethod + def get_report_data(): + data = {'title': T1504.technique_title(), 'info': []} + + scanned_nodes = ReportService.get_scanned() + status = ScanStatus.UNSCANNED.value + + for node in scanned_nodes: + if node['pba_results'] != 'None': + for pba in node['pba_results']: + if pba['name'] == POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: + if 'powershell.exe' in pba['command']: + status = ScanStatus.USED.value if pba['result'][1]\ + else ScanStatus.SCANNED.value + data['info'].append({ + 'machine': { + 'hostname': pba['hostname'], + 'ips': node['ip_addresses'] + }, + 'result': pba['result'][0].replace('#', '') + }) + data.update(T1504.get_base_data_by_status(status)) + return data From ef6bb52302b4b2549942d9cd0983813d47883f83 Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 15 Jun 2020 17:54:44 +0530 Subject: [PATCH 07/18] Remove Privilege escalation/T1504 in attack_schema Shows it twice in ATT&CK matrix in the configuration, but shows it only once in the ATT&CK matrix in the report section. --- .../cc/services/attack/attack_schema.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/monkey/monkey_island/cc/services/attack/attack_schema.py b/monkey/monkey_island/cc/services/attack/attack_schema.py index 7ef15a509..99e8dcfd2 100644 --- a/monkey/monkey_island/cc/services/attack/attack_schema.py +++ b/monkey/monkey_island/cc/services/attack/attack_schema.py @@ -102,23 +102,6 @@ SCHEMA = { } } }, - "privilege_escalation": { - "title": "Privilege escalation", - "type": "object", - "link": "https://attack.mitre.org/tactics/TA0004/", - "properties": { - "T1504": { - "title": "PowerShell profile", - "type": "bool", - "value": True, - "necessary": False, - "link": "https://attack.mitre.org/techniques/T1504", - "description": "Adversaries may gain persistence and elevate privileges " - "in certain situations by abusing PowerShell profiles which " - "are scripts that run when PowerShell starts." - } - } - }, "defence_evasion": { "title": "Defence evasion", "type": "object", From 58a0a67244b7576199a59461118c76e40362f5ad Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 15 Jun 2020 17:58:46 +0530 Subject: [PATCH 08/18] Add T1504 to config_schema --- monkey/monkey_island/cc/services/config_schema.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index a1e8bcb3d..e37f3a75f 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -166,7 +166,7 @@ SCHEMA = { "ModifyShellStartupFiles" ], "title": "Modify shell startup files", - "attack_techniques": ["T1156"] + "attack_techniques": ["T1156", "T1504"] } ], }, From 6d98f95d4c63b74c28b493c0861958262e3bca60 Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 15 Jun 2020 18:26:05 +0530 Subject: [PATCH 09/18] Make used/scanned/unscanned messages descriptive --- .../cc/services/attack/technique_reports/T1156.py | 6 +++--- .../cc/services/attack/technique_reports/T1504.py | 6 +++--- 2 files changed, 6 insertions(+), 6 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 b618e743a..9ceb2c027 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -9,9 +9,9 @@ __author__ = "shreyamalviya" class T1156(AttackTechnique): tech_id = "T1156" - unscanned_msg = "Monkey did not try modifying shell startup files on the system." - scanned_msg = "Monkey tried modifying shell startup files on the system but failed." - used_msg = "Monkey modified shell startup files on the system." + unscanned_msg = "Monkey did not try modifying Linux's shell startup files on the system." + scanned_msg = "Monkey tried modifying Linux's shell startup files on the system but failed." + used_msg = "Monkey modified Linux's shell startup files on the system." @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 585599c86..34e25323e 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -9,9 +9,9 @@ __author__ = "shreyamalviya" class T1504(AttackTechnique): tech_id = "T1504" - unscanned_msg = "Monkey did not try modifying shell startup files on the system." - scanned_msg = "Monkey tried modifying shell startup files on the system but failed." - used_msg = "Monkey modified shell startup files on the system." + unscanned_msg = "Monkey did not try modifying Window's shell startup files on the system." + scanned_msg = "Monkey tried modifying Window's shell startup files on the system but failed." + used_msg = "Monkey modified Window's shell startup files on the system." @staticmethod def get_report_data(): From 60207e3a794948d75f4a984b66cf69f44e11b1e4 Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 17 Jun 2020 02:09:02 +0530 Subject: [PATCH 10/18] Change file locations --- .../linux/shell_startup_files_modification.py | 0 .../shell_startup_files}/shell_startup_files_modification.py | 4 ++-- .../windows/shell_startup_files_modification.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename monkey/infection_monkey/{utils => post_breach/shell_startup_files}/linux/shell_startup_files_modification.py (100%) rename monkey/infection_monkey/{utils => post_breach/shell_startup_files}/shell_startup_files_modification.py (62%) rename monkey/infection_monkey/{utils => post_breach/shell_startup_files}/windows/shell_startup_files_modification.py (98%) diff --git a/monkey/infection_monkey/utils/linux/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py similarity index 100% rename from monkey/infection_monkey/utils/linux/shell_startup_files_modification.py rename to monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py diff --git a/monkey/infection_monkey/utils/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/shell_startup_files_modification.py similarity index 62% rename from monkey/infection_monkey/utils/shell_startup_files_modification.py rename to monkey/infection_monkey/post_breach/shell_startup_files/shell_startup_files_modification.py index c97ca34b7..bc83ec499 100644 --- a/monkey/infection_monkey/utils/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/shell_startup_files_modification.py @@ -1,6 +1,6 @@ -from infection_monkey.utils.linux.shell_startup_files_modification import\ +from infection_monkey.post_breach.shell_startup_files.linux.shell_startup_files_modification import\ get_linux_commands_to_modify_shell_startup_files -from infection_monkey.utils.windows.shell_startup_files_modification import\ +from infection_monkey.post_breach.shell_startup_files.windows.shell_startup_files_modification import\ get_windows_commands_to_modify_shell_startup_files diff --git a/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py similarity index 98% rename from monkey/infection_monkey/utils/windows/shell_startup_files_modification.py rename to monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py index 15e44b832..44315df4b 100644 --- a/monkey/infection_monkey/utils/windows/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py @@ -9,4 +9,4 @@ def get_windows_commands_to_modify_shell_startup_files(): 'cat {0} | Select -last 1 ;'.format(SHELL_STARTUP_FILE), # print last line of $profile '$OldProfile = cat {0} | Select -skiplast 1 ;'.format(SHELL_STARTUP_FILE), 'Set-Content {0} -Value $OldProfile ;'.format(SHELL_STARTUP_FILE) # remove last line of $profile -] + ] From 0c60ad16aed66d1b2fae83b6a0cfb81fe09a7094 Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 17 Jun 2020 11:49:03 +0530 Subject: [PATCH 11/18] Code design changes --- .../actions/modify_shell_startup_files.py | 42 ++++++++++++------- monkey/infection_monkey/post_breach/pba.py | 11 ++--- 2 files changed, 32 insertions(+), 21 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 a526acad6..8417849db 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,6 +1,6 @@ from common.data.post_breach_consts import POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION from infection_monkey.post_breach.pba import PBA -from infection_monkey.utils.shell_startup_files_modification import\ +from infection_monkey.post_breach.shell_startup_files.shell_startup_files_modification import\ get_commands_to_modify_shell_startup_files from infection_monkey.utils.environment import is_windows_os @@ -12,21 +12,31 @@ 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()] + + def modify_shell_startup_PBA_list(self): + return ShellStartupPBAGenerator.get_modify_shell_startup_pbas() + + +class ShellStartupPBAGenerator(): + def get_modify_shell_startup_pbas(): (cmds_for_linux, shell_startup_files_for_linux), windows_cmds = get_commands_to_modify_shell_startup_files() - if is_windows_os(): - super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - linux_cmd='', # windows so won't matter - windows_cmd=windows_cmds) - super(ModifyShellStartupFiles, self).run() - else: - for shell_startup_file in shell_startup_files_for_linux: - linux_cmds = ' '.join(cmds_for_linux).format(shell_startup_file) - super(ModifyShellStartupFiles, self).__init__(name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION, - linux_cmd=linux_cmds, - windows_cmd=windows_cmds) - super(ModifyShellStartupFiles, self).run() + pbas = [ModifyShellStartupFile(linux_cmds='', windows_cmds=windows_cmds)] + + for shell_startup_file in shell_startup_files_for_linux: + linux_cmds = ' '.join(cmds_for_linux).format(shell_startup_file) + pbas.append(ModifyShellStartupFile(linux_cmds=linux_cmds, windows_cmds='')) + + return pbas + + +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): + super(ModifyShellStartupFile, self).run() diff --git a/monkey/infection_monkey/post_breach/pba.py b/monkey/infection_monkey/post_breach/pba.py index 3d8da9dab..e5a91b733 100644 --- a/monkey/infection_monkey/post_breach/pba.py +++ b/monkey/infection_monkey/post_breach/pba.py @@ -57,11 +57,12 @@ class PBA(Plugin): """ Runs post breach action command """ - exec_funct = self._execute_default - result = exec_funct() - if self.scripts_were_used_successfully(result): - T1064Telem(ScanStatus.USED, "Scripts were used to execute %s post breach action." % self.name).send() - PostBreachTelem(self, result).send() + if self.command: + exec_funct = self._execute_default + result = exec_funct() + if self.scripts_were_used_successfully(result): + T1064Telem(ScanStatus.USED, "Scripts were used to execute %s post breach action." % self.name).send() + PostBreachTelem(self, result).send() def is_script(self): """ From e5f92d29b55e09b6cf12fd30d2c6322fc2fbe8bb Mon Sep 17 00:00:00 2001 From: Shreya Date: Sat, 20 Jun 2020 16:47:08 +0530 Subject: [PATCH 12/18] Add startup files for fish, zsh, dash, ksh, sh, csh, tcsh --- .../linux/shell_startup_files_modification.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py index 8c54b9168..745caf6c8 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py @@ -1,4 +1,12 @@ -BASH_STARTUP_FILES = ["~/.bashrc", "~/.profile", "~/.bash_profile"] +STARTUP_FILES = [ + "~/.profile", # bash, dash, ksh, sh + "~/.bashrc", "~/.bash_profile", # bash + "~/.config/fish/config.fish", # fish + "~/.zshrc", "~/.zshenv", "~/.zprofile", # zsh + "~/.kshrc", # ksh + "~/.tcshrc", # tcsh + "~/.cshrc", # csh + ] def get_linux_commands_to_modify_shell_startup_files(): @@ -10,4 +18,4 @@ def get_linux_commands_to_modify_shell_startup_files(): '&&', 'sed -i \'$d\' {0}', # remove last line of file ],\ - BASH_STARTUP_FILES + STARTUP_FILES From 8d2aaac65f2056b3001e09d28c91753e800acf13 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sat, 20 Jun 2020 23:30:32 +0530 Subject: [PATCH 13/18] Fix + make linux PBA commands cleaner --- .../post_breach/actions/modify_shell_startup_files.py | 3 --- .../linux/shell_startup_files_modification.py | 10 ++++------ 2 files changed, 4 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 8417849db..09063fa2d 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 @@ -37,6 +37,3 @@ 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): - super(ModifyShellStartupFile, self).run() diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py index 745caf6c8..552904506 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py @@ -11,11 +11,9 @@ STARTUP_FILES = [ def get_linux_commands_to_modify_shell_startup_files(): return [ - 'echo \"# Succesfully modified {0}\"', - '3<{0} 3<&- |', # check for existence of file - 'tee -a', # append to file - '{0}', - '&&', - 'sed -i \'$d\' {0}', # remove last line of file + '3<{0} 3<&- &&', # check for existence of file + 'echo \"# Succesfully modified {0}\" |', + 'tee -a {0} &&', # append to file + 'sed -i \'$d\' {0}', # remove last line of file (undo changes) ],\ STARTUP_FILES From 7459105bbcfbbd512ea7eab6e4e2dbff8231ae23 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sun, 21 Jun 2020 00:43:15 +0530 Subject: [PATCH 14/18] Extend linux PBA for all users on system TODO: ATT&CK report stuff (mongo search + show only bash file modification info) TODO: Windows --- .../actions/modify_shell_startup_files.py | 10 +++--- .../linux/shell_startup_files_modification.py | 34 ++++++++++++++----- 2 files changed, 32 insertions(+), 12 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 09063fa2d..38c82bf02 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,13 +21,15 @@ class ModifyShellStartupFiles(PBA): class ShellStartupPBAGenerator(): def get_modify_shell_startup_pbas(): - (cmds_for_linux, shell_startup_files_for_linux), windows_cmds = get_commands_to_modify_shell_startup_files() + (cmds_for_linux, shell_startup_files_for_linux, usernames_for_linux), windows_cmds =\ + get_commands_to_modify_shell_startup_files() pbas = [ModifyShellStartupFile(linux_cmds='', windows_cmds=windows_cmds)] - for shell_startup_file in shell_startup_files_for_linux: - linux_cmds = ' '.join(cmds_for_linux).format(shell_startup_file) - pbas.append(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 diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py index 552904506..b4d498296 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py @@ -1,12 +1,30 @@ +import subprocess + + +HOME_DIR = "/home/" + +# get list of usernames +USERS = subprocess.check_output( + "cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1", + shell=True + ).decode().split('\n')[:-1] + +# get list of paths of different shell startup files with place for username STARTUP_FILES = [ - "~/.profile", # bash, dash, ksh, sh - "~/.bashrc", "~/.bash_profile", # bash - "~/.config/fish/config.fish", # fish - "~/.zshrc", "~/.zshenv", "~/.zprofile", # zsh - "~/.kshrc", # ksh - "~/.tcshrc", # tcsh - "~/.cshrc", # csh + file_path.format(HOME_DIR) for file_path in + [ + "{0}{{0}}/.profile", # bash, dash, ksh, sh + "{0}{{0}}/.bashrc", # bash + "{0}{{0}}/.bash_profile", + "{0}{{0}}/.config/fish/config.fish", # fish + "{0}{{0}}/.zshrc", # zsh + "{0}{{0}}/.zshenv", + "{0}{{0}}/.zprofile", + "{0}{{0}}/.kshrc", # ksh + "{0}{{0}}/.tcshrc", # tcsh + "{0}{{0}}/.cshrc", # csh ] +] def get_linux_commands_to_modify_shell_startup_files(): @@ -16,4 +34,4 @@ def get_linux_commands_to_modify_shell_startup_files(): 'tee -a {0} &&', # append to file 'sed -i \'$d\' {0}', # remove last line of file (undo changes) ],\ - STARTUP_FILES + STARTUP_FILES, USERS From 6f6bfca9f9e2f6c7b79d8456f11c201421bed64e Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 22 Jun 2020 17:58:12 +0530 Subject: [PATCH 15/18] Use mongo search for report data (For linux, shows only bash startup files in ATT&CK report) --- .../attack/technique_reports/T1156.py | 42 +++++++++---------- .../attack/technique_reports/T1504.py | 42 +++++++++---------- 2 files changed, 42 insertions(+), 42 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 9ceb2c027..a1719c909 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1156.py @@ -1,5 +1,5 @@ from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.reporting.report import ReportService +from monkey_island.cc.database import mongo from common.utils.attack_utils import ScanStatus from common.data.post_breach_consts import POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION @@ -9,30 +9,30 @@ __author__ = "shreyamalviya" class T1156(AttackTechnique): tech_id = "T1156" - unscanned_msg = "Monkey did not try modifying Linux's shell startup files on the system." - scanned_msg = "Monkey tried modifying Linux's shell startup files on the system but failed." - used_msg = "Monkey modified Linux's shell startup files on the system." + unscanned_msg = "Monkey did not try modifying bash startup files on the system." + scanned_msg = "Monkey tried modifying bash startup files on the system but failed." + 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'}}}, + {'$project': {'_id': 0, + 'machine': {'hostname': '$data.hostname', + 'ips': ['$data.ip']}, + 'result': '$data.result'}}] @staticmethod def get_report_data(): data = {'title': T1156.technique_title(), 'info': []} - scanned_nodes = ReportService.get_scanned() - status = ScanStatus.UNSCANNED.value + bash_modification_info = list(mongo.db.telemetry.aggregate(T1156.query)) - for node in scanned_nodes: - if node['pba_results'] != 'None': - for pba in node['pba_results']: - if pba['name'] == POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: - if 'powershell.exe' not in pba['command']: - status = ScanStatus.USED.value if pba['result'][1]\ - else ScanStatus.SCANNED.value - data['info'].append({ - 'machine': { - 'hostname': pba['hostname'], - 'ips': node['ip_addresses'] - }, - 'result': pba['result'][0].replace('#', '') - }) - data.update(T1156.get_base_data_by_status(status)) + status = [] + for pba_node in bash_modification_info: + status.append(pba_node['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}) 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 34e25323e..396067f17 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1504.py @@ -1,5 +1,5 @@ from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.reporting.report import ReportService +from monkey_island.cc.database import mongo from common.utils.attack_utils import ScanStatus from common.data.post_breach_consts import POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION @@ -9,30 +9,30 @@ __author__ = "shreyamalviya" class T1504(AttackTechnique): tech_id = "T1504" - unscanned_msg = "Monkey did not try modifying Window's shell startup files on the system." - scanned_msg = "Monkey tried modifying Window's shell startup files on the system but failed." - used_msg = "Monkey modified Window's shell startup files on the system." + unscanned_msg = "Monkey did not try modifying powershell startup files on the system." + scanned_msg = "Monkey tried modifying powershell startup files on the system but failed." + 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'}}}, + {'$project': {'_id': 0, + 'machine': {'hostname': '$data.hostname', + 'ips': ['$data.ip']}, + 'result': '$data.result'}}] @staticmethod def get_report_data(): data = {'title': T1504.technique_title(), 'info': []} - scanned_nodes = ReportService.get_scanned() - status = ScanStatus.UNSCANNED.value + powershell_profile_modification_info = list(mongo.db.telemetry.aggregate(T1504.query)) - for node in scanned_nodes: - if node['pba_results'] != 'None': - for pba in node['pba_results']: - if pba['name'] == POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION: - if 'powershell.exe' in pba['command']: - status = ScanStatus.USED.value if pba['result'][1]\ - else ScanStatus.SCANNED.value - data['info'].append({ - 'machine': { - 'hostname': pba['hostname'], - 'ips': node['ip_addresses'] - }, - 'result': pba['result'][0].replace('#', '') - }) - data.update(T1504.get_base_data_by_status(status)) + status = [] + for pba_node in powershell_profile_modification_info: + status.append(pba_node['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}) return data From 7efeff3ff07099adc54b17e3f93c07917a452a1f Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 22 Jun 2020 18:30:06 +0530 Subject: [PATCH 16/18] Modify linux PBA so it doesn't give errors when running on windows --- .../linux/shell_startup_files_modification.py | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py index b4d498296..8a1ed7246 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py @@ -1,37 +1,39 @@ import subprocess - - -HOME_DIR = "/home/" - -# get list of usernames -USERS = subprocess.check_output( - "cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1", - shell=True - ).decode().split('\n')[:-1] - -# get list of paths of different shell startup files with place for username -STARTUP_FILES = [ - file_path.format(HOME_DIR) for file_path in - [ - "{0}{{0}}/.profile", # bash, dash, ksh, sh - "{0}{{0}}/.bashrc", # bash - "{0}{{0}}/.bash_profile", - "{0}{{0}}/.config/fish/config.fish", # fish - "{0}{{0}}/.zshrc", # zsh - "{0}{{0}}/.zshenv", - "{0}{{0}}/.zprofile", - "{0}{{0}}/.kshrc", # ksh - "{0}{{0}}/.tcshrc", # tcsh - "{0}{{0}}/.cshrc", # csh - ] -] +from infection_monkey.utils.environment import is_windows_os def get_linux_commands_to_modify_shell_startup_files(): + if is_windows_os(): + return '', [], [] + + HOME_DIR = "/home/" + + # get list of usernames + USERS = subprocess.check_output( + "cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1", + shell=True + ).decode().split('\n')[:-1] + + # get list of paths of different shell startup files with place for username + STARTUP_FILES = [ + file_path.format(HOME_DIR) for file_path in + [ + "{0}{{0}}/.profile", # bash, dash, ksh, sh + "{0}{{0}}/.bashrc", # bash + "{0}{{0}}/.bash_profile", + "{0}{{0}}/.config/fish/config.fish", # fish + "{0}{{0}}/.zshrc", # zsh + "{0}{{0}}/.zshenv", + "{0}{{0}}/.zprofile", + "{0}{{0}}/.kshrc", # ksh + "{0}{{0}}/.tcshrc", # tcsh + "{0}{{0}}/.cshrc", # csh + ] + ] + return [ '3<{0} 3<&- &&', # check for existence of file 'echo \"# Succesfully modified {0}\" |', 'tee -a {0} &&', # append to file 'sed -i \'$d\' {0}', # remove last line of file (undo changes) - ],\ - STARTUP_FILES, USERS + ], STARTUP_FILES, USERS From f21dbde27d4e644fb7ea8071422449ffff12f540 Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 22 Jun 2020 21:32:41 +0530 Subject: [PATCH 17/18] Extend windows PBA for all users on system --- .../actions/modify_shell_startup_files.py | 11 ++++--- .../shell_startup_files_modification.py | 31 ++++++++++++++----- 2 files changed, 30 insertions(+), 12 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 38c82bf02..095c7cb11 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 @@ -2,7 +2,6 @@ from common.data.post_breach_consts import POST_BREACH_SHELL_STARTUP_FILE_MODIFI 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.utils.environment import is_windows_os class ModifyShellStartupFiles(PBA): @@ -21,10 +20,14 @@ class ModifyShellStartupFiles(PBA): class ShellStartupPBAGenerator(): def get_modify_shell_startup_pbas(): - (cmds_for_linux, shell_startup_files_for_linux, usernames_for_linux), windows_cmds =\ - get_commands_to_modify_shell_startup_files() + (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 = [ModifyShellStartupFile(linux_cmds='', windows_cmds=windows_cmds)] + 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(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: diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py index 44315df4b..a9116c221 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py @@ -1,12 +1,27 @@ -SHELL_STARTUP_FILE = '$Profile' +import subprocess +from infection_monkey.utils.environment import is_windows_os def get_windows_commands_to_modify_shell_startup_files(): + if not is_windows_os(): + return '', [] + + # get powershell startup file path + SHELL_STARTUP_FILE = subprocess.check_output('powershell $Profile').decode().split("\r\n")[0] + SHELL_STARTUP_FILE_PATH_COMPONENTS = SHELL_STARTUP_FILE.split("\\") + + # get list of usernames + USERS = subprocess.check_output('dir C:\\Users /b', shell=True).decode().split("\r\n")[:-1] + + STARTUP_FILES_PER_USER = ['\\'.join(SHELL_STARTUP_FILE_PATH_COMPONENTS[:2] + + [user] + + SHELL_STARTUP_FILE_PATH_COMPONENTS[3:]) + for user in USERS] + return [ - 'powershell.exe', # run with powershell - 'Add-Content {0} '.format(SHELL_STARTUP_FILE), - '\"# Successfully modified {0}\" ;'.format(SHELL_STARTUP_FILE), # add line to $profile - 'cat {0} | Select -last 1 ;'.format(SHELL_STARTUP_FILE), # print last line of $profile - '$OldProfile = cat {0} | Select -skiplast 1 ;'.format(SHELL_STARTUP_FILE), - 'Set-Content {0} -Value $OldProfile ;'.format(SHELL_STARTUP_FILE) # remove last line of $profile - ] + 'Add-Content {0}', + '\"# Successfully modified {0}\" ;', # add line to $profile + 'cat {0} | Select -last 1 ;', # print last line of $profile + '$OldProfile = cat {0} | Select -skiplast 1 ;', + 'Set-Content {0} -Value $OldProfile ;' # remove last line of $profile + ], STARTUP_FILES_PER_USER From 53e6f893c69a9130b681f676582f434a69c713cb Mon Sep 17 00:00:00 2001 From: Shreya Date: Wed, 24 Jun 2020 13:58:52 +0530 Subject: [PATCH 18/18] Disabled prop-types warning in eslint (Accidentally force-pushed over the previous commit changing this) --- .travis.yml | 2 +- monkey/monkey_island/cc/ui/.eslintrc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c7b12ca86..6640812b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ script: - cd monkey_island/cc/ui - npm ci # See https://docs.npmjs.com/cli/ci.html - eslint ./src --quiet # Test for errors -- JS_WARNINGS_AMOUNT_UPPER_LIMIT=490 +- JS_WARNINGS_AMOUNT_UPPER_LIMIT=90 - eslint ./src --max-warnings $JS_WARNINGS_AMOUNT_UPPER_LIMIT # Test for max warnings after_success: diff --git a/monkey/monkey_island/cc/ui/.eslintrc b/monkey/monkey_island/cc/ui/.eslintrc index c784bd178..ff1695a1c 100644 --- a/monkey/monkey_island/cc/ui/.eslintrc +++ b/monkey/monkey_island/cc/ui/.eslintrc @@ -53,7 +53,7 @@ "react/jsx-uses-react": 1, "react/jsx-uses-vars": 1, "react/jsx-key": 1, - "react/prop-types": 1, + "react/prop-types": 0, "react/no-unescaped-entities": 1, "react/no-unknown-property": [1, { "ignore": ["class"] }], "react/no-string-refs": 1,