From a74f2a5ead543644052d39bb6314cc5c473622ea Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 29 Jun 2020 18:59:34 +0530 Subject: [PATCH 1/3] Add PBA T1154 --- monkey/common/data/post_breach_consts.py | 1 + .../post_breach/actions/use_trap_command.py | 13 ++++++ .../trap_command/linux/trap_command.py | 6 +++ .../post_breach/trap_command/trap_command.py | 7 +++ .../cc/services/attack/attack_report.py | 5 ++- .../cc/services/attack/attack_schema.py | 11 ++++- .../attack/technique_reports/T1154.py | 37 +++++++++++++++ .../cc/services/config_schema.py | 11 ++++- .../src/components/attack/techniques/T1154.js | 45 +++++++++++++++++++ 9 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 monkey/infection_monkey/post_breach/actions/use_trap_command.py create mode 100644 monkey/infection_monkey/post_breach/trap_command/linux/trap_command.py create mode 100644 monkey/infection_monkey/post_breach/trap_command/trap_command.py create mode 100644 monkey/monkey_island/cc/services/attack/technique_reports/T1154.py create mode 100644 monkey/monkey_island/cc/ui/src/components/attack/techniques/T1154.js diff --git a/monkey/common/data/post_breach_consts.py b/monkey/common/data/post_breach_consts.py index 27167228e..408904a33 100644 --- a/monkey/common/data/post_breach_consts.py +++ b/monkey/common/data/post_breach_consts.py @@ -3,3 +3,4 @@ POST_BREACH_BACKDOOR_USER = "Backdoor user" POST_BREACH_FILE_EXECUTION = "File execution" POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION = "Modify shell startup file" POST_BREACH_HIDDEN_FILES = "Hide files and directories" +POST_BREACH_TRAP_COMMAND = "Execute command on signal interrupt" diff --git a/monkey/infection_monkey/post_breach/actions/use_trap_command.py b/monkey/infection_monkey/post_breach/actions/use_trap_command.py new file mode 100644 index 000000000..eb9aed4a0 --- /dev/null +++ b/monkey/infection_monkey/post_breach/actions/use_trap_command.py @@ -0,0 +1,13 @@ +from common.data.post_breach_consts import POST_BREACH_TRAP_COMMAND +from infection_monkey.post_breach.pba import PBA +from infection_monkey.post_breach.trap_command.trap_command import\ + get_trap_commands +from infection_monkey.utils.environment import is_windows_os + + +class TrapCommand(PBA): + def __init__(self): + if not is_windows_os(): + linux_cmds = get_trap_commands() + super(TrapCommand, self).__init__(POST_BREACH_TRAP_COMMAND, + linux_cmd=' '.join(linux_cmds)) diff --git a/monkey/infection_monkey/post_breach/trap_command/linux/trap_command.py b/monkey/infection_monkey/post_breach/trap_command/linux/trap_command.py new file mode 100644 index 000000000..a042a0432 --- /dev/null +++ b/monkey/infection_monkey/post_breach/trap_command/linux/trap_command.py @@ -0,0 +1,6 @@ +def get_linux_trap_commands(): + return [ + 'trap \'echo \"Successfully used trap command\"\' INT &&', + 'kill -2 $$ ;', # send SIGINT signal + 'trap - INT' # untrap SIGINT + ] diff --git a/monkey/infection_monkey/post_breach/trap_command/trap_command.py b/monkey/infection_monkey/post_breach/trap_command/trap_command.py new file mode 100644 index 000000000..d4d2b94cb --- /dev/null +++ b/monkey/infection_monkey/post_breach/trap_command/trap_command.py @@ -0,0 +1,7 @@ +from infection_monkey.post_breach.trap_command.linux.trap_command import\ + get_linux_trap_commands + + +def get_trap_commands(): + linux_cmds = get_linux_trap_commands() + return linux_cmds diff --git a/monkey/monkey_island/cc/services/attack/attack_report.py b/monkey/monkey_island/cc/services/attack/attack_report.py index 16e6e51a1..088d6dfb6 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, T1504, T1158 +from monkey_island.cc.services.attack.technique_reports import T1136, T1156, T1504, T1158, T1154 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 @@ -40,7 +40,8 @@ TECHNIQUES = {'T1210': T1210.T1210, 'T1136': T1136.T1136, 'T1156': T1156.T1156, 'T1504': T1504.T1504, - 'T1158': T1158.T1158 + 'T1158': T1158.T1158, + 'T1154': T1154.T1154 } 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 c70ff2a70..f981eb9c8 100644 --- a/monkey/monkey_island/cc/services/attack/attack_schema.py +++ b/monkey/monkey_island/cc/services/attack/attack_schema.py @@ -63,8 +63,17 @@ SCHEMA = { "description": "Adversaries may execute a binary, command, or script via a method " "that interacts with Windows services, such as the Service Control Manager.", "depends_on": ["T1210"] + }, + "T1154": { + "title": "Trap", + "type": "bool", + "value": True, + "necessary": False, + "link": "https://attack.mitre.org/techniques/T1154", + "description": "Adversaries can use the trap command to register code to be executed " + "when the shell encounters specific interrupts." } - } + }, }, "persistence": { "title": "Persistence", diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py new file mode 100644 index 000000000..f23f1bbca --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py @@ -0,0 +1,37 @@ +from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.database import mongo +from common.utils.attack_utils import ScanStatus +from common.data.post_breach_consts import POST_BREACH_TRAP_COMMAND + + +__author__ = "shreyamalviya" + + +class T1154(AttackTechnique): + tech_id = "T1154" + unscanned_msg = "Monkey did not use the trap command on the system." + scanned_msg = "Monkey tried using the trap command but failed on the system." + used_msg = "Monkey used the trap command on the system." + + query = [{'$match': {'telem_category': 'post_breach', + 'data.name': POST_BREACH_TRAP_COMMAND}}, + {'$project': {'_id': 0, + 'machine': {'hostname': '$data.hostname', + 'ips': ['$data.ip']}, + 'result': '$data.result'}}] + + @staticmethod + def get_report_data(): + data = {'title': T1154.technique_title(), 'info': []} + + trap_command_info = list(mongo.db.telemetry.aggregate(T1154.query)) + + status = [] + for pba_node in trap_command_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(T1154.get_base_data_by_status(status)) + data.update({'info': trap_command_info}) + return data diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index 30425dc1d..75173ab6f 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -175,6 +175,14 @@ SCHEMA = { ], "title": "Hidden files and directories", "attack_techniques": ["T1158"] + }, + { + "type": "string", + "enum": [ + "TrapCommand" + ], + "title": "Trap", + "attack_techniques": ["T1154"] } ], }, @@ -397,7 +405,8 @@ SCHEMA = { "BackdoorUser", "CommunicateAsNewUser", "ModifyShellStartupFiles", - "HiddenFiles" + "HiddenFiles", + "TrapCommand" ], "description": "List of actions the Monkey will run post breach" }, diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1154.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1154.js new file mode 100644 index 000000000..c136b8017 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1154.js @@ -0,0 +1,45 @@ +import React from 'react'; +import ReactTable from 'react-table'; +import {renderMachineFromSystemData, ScanStatus} from './Helpers'; +import MitigationsComponent from './MitigationsComponent'; + +class T1154 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 T1154; From d9d8c813aa11d42eed2d7742b894902596d75b16 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 3 Jul 2020 22:54:09 +0530 Subject: [PATCH 2/3] Code review + other tiny changes --- monkey/common/data/post_breach_consts.py | 2 +- .../post_breach/actions/use_trap_command.py | 2 +- .../{linux/trap_command.py => linux_trap_command.py} | 3 +-- .../post_breach/trap_command/trap_command.py | 2 +- .../cc/services/attack/technique_reports/T1154.py | 6 +++--- 5 files changed, 7 insertions(+), 8 deletions(-) rename monkey/infection_monkey/post_breach/trap_command/{linux/trap_command.py => linux_trap_command.py} (75%) diff --git a/monkey/common/data/post_breach_consts.py b/monkey/common/data/post_breach_consts.py index 408904a33..16d53b746 100644 --- a/monkey/common/data/post_breach_consts.py +++ b/monkey/common/data/post_breach_consts.py @@ -3,4 +3,4 @@ POST_BREACH_BACKDOOR_USER = "Backdoor user" POST_BREACH_FILE_EXECUTION = "File execution" POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION = "Modify shell startup file" POST_BREACH_HIDDEN_FILES = "Hide files and directories" -POST_BREACH_TRAP_COMMAND = "Execute command on signal interrupt" +POST_BREACH_TRAP_COMMAND = "Execute command when a particular signal is received" diff --git a/monkey/infection_monkey/post_breach/actions/use_trap_command.py b/monkey/infection_monkey/post_breach/actions/use_trap_command.py index eb9aed4a0..74ffdcb28 100644 --- a/monkey/infection_monkey/post_breach/actions/use_trap_command.py +++ b/monkey/infection_monkey/post_breach/actions/use_trap_command.py @@ -10,4 +10,4 @@ class TrapCommand(PBA): if not is_windows_os(): linux_cmds = get_trap_commands() super(TrapCommand, self).__init__(POST_BREACH_TRAP_COMMAND, - linux_cmd=' '.join(linux_cmds)) + linux_cmd=linux_cmds) diff --git a/monkey/infection_monkey/post_breach/trap_command/linux/trap_command.py b/monkey/infection_monkey/post_breach/trap_command/linux_trap_command.py similarity index 75% rename from monkey/infection_monkey/post_breach/trap_command/linux/trap_command.py rename to monkey/infection_monkey/post_breach/trap_command/linux_trap_command.py index a042a0432..8a251e258 100644 --- a/monkey/infection_monkey/post_breach/trap_command/linux/trap_command.py +++ b/monkey/infection_monkey/post_breach/trap_command/linux_trap_command.py @@ -1,6 +1,5 @@ def get_linux_trap_commands(): return [ - 'trap \'echo \"Successfully used trap command\"\' INT &&', - 'kill -2 $$ ;', # send SIGINT signal + 'trap \'echo \"Successfully used trap command\"\' INT && kill -2 $$ ;', # trap and send SIGINT signal 'trap - INT' # untrap SIGINT ] diff --git a/monkey/infection_monkey/post_breach/trap_command/trap_command.py b/monkey/infection_monkey/post_breach/trap_command/trap_command.py index d4d2b94cb..208b21eda 100644 --- a/monkey/infection_monkey/post_breach/trap_command/trap_command.py +++ b/monkey/infection_monkey/post_breach/trap_command/trap_command.py @@ -1,4 +1,4 @@ -from infection_monkey.post_breach.trap_command.linux.trap_command import\ +from infection_monkey.post_breach.trap_command.linux_trap_command import\ get_linux_trap_commands 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 f23f1bbca..5a1d56503 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py @@ -9,9 +9,9 @@ __author__ = "shreyamalviya" class T1154(AttackTechnique): tech_id = "T1154" - unscanned_msg = "Monkey did not use the trap command on the system." - scanned_msg = "Monkey tried using the trap command but failed on the system." - used_msg = "Monkey used the trap command on the system." + unscanned_msg = "Monkey did not use the trap command." + scanned_msg = "Monkey tried using the trap command but failed." + used_msg = "Monkey used the trap command successfully." query = [{'$match': {'telem_category': 'post_breach', 'data.name': POST_BREACH_TRAP_COMMAND}}, From e6b3613db28e985789d68dc2ae066363622ba9cf Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 13 Jul 2020 19:20:38 +0530 Subject: [PATCH 3/3] Check status using mongo --- .../cc/services/attack/technique_reports/T1154.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 5a1d56503..9d95bb087 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1154.py @@ -26,11 +26,11 @@ class T1154(AttackTechnique): trap_command_info = list(mongo.db.telemetry.aggregate(T1154.query)) - status = [] - for pba_node in trap_command_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 trap_command_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_TRAP_COMMAND, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value data.update(T1154.get_base_data_by_status(status)) data.update({'info': trap_command_info})