diff --git a/monkey/common/data/post_breach_consts.py b/monkey/common/data/post_breach_consts.py index 27167228e..16d53b746 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 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 new file mode 100644 index 000000000..74ffdcb28 --- /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=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..8a251e258 --- /dev/null +++ b/monkey/infection_monkey/post_breach/trap_command/linux_trap_command.py @@ -0,0 +1,5 @@ +def get_linux_trap_commands(): + return [ + '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 new file mode 100644 index 000000000..208b21eda --- /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..9d95bb087 --- /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." + 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}}, + {'$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 = 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}) + 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;