diff --git a/monkey/common/data/post_breach_consts.py b/monkey/common/data/post_breach_consts.py index 16d53b746..dc7bb7310 100644 --- a/monkey/common/data/post_breach_consts.py +++ b/monkey/common/data/post_breach_consts.py @@ -4,3 +4,4 @@ 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" +POST_BREACH_SETUID_SETGID = "Setuid and Setgid" diff --git a/monkey/infection_monkey/post_breach/actions/change_file_privileges.py b/monkey/infection_monkey/post_breach/actions/change_file_privileges.py new file mode 100644 index 000000000..325098202 --- /dev/null +++ b/monkey/infection_monkey/post_breach/actions/change_file_privileges.py @@ -0,0 +1,13 @@ +from common.data.post_breach_consts import POST_BREACH_SETUID_SETGID +from infection_monkey.post_breach.pba import PBA +from infection_monkey.post_breach.setuid_setgid.setuid_setgid import\ + get_commands_to_change_setuid_setgid +from infection_monkey.utils.environment import is_windows_os + + +class ChangeSetuidSetgid(PBA): + def __init__(self): + if not is_windows_os(): + linux_cmds = get_commands_to_change_setuid_setgid() + super(ChangeSetuidSetgid, self).__init__(POST_BREACH_SETUID_SETGID, + linux_cmd=' '.join(linux_cmds)) diff --git a/monkey/infection_monkey/post_breach/setuid_setgid/linux_setuid_setgid.py b/monkey/infection_monkey/post_breach/setuid_setgid/linux_setuid_setgid.py new file mode 100644 index 000000000..b1f40b5b7 --- /dev/null +++ b/monkey/infection_monkey/post_breach/setuid_setgid/linux_setuid_setgid.py @@ -0,0 +1,11 @@ +TEMP_FILE = '$HOME/monkey-temp-file' + +# Commands from https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1548.001/T1548.001.md + + +def get_linux_commands_to_setuid_setgid(): + return [ + f'touch {TEMP_FILE} && chown root {TEMP_FILE} && chmod u+s {TEMP_FILE} && chmod g+s {TEMP_FILE} &&', + 'echo "Successfully changed setuid/setgid bits" &&', + f'rm {TEMP_FILE}' + ] diff --git a/monkey/infection_monkey/post_breach/setuid_setgid/setuid_setgid.py b/monkey/infection_monkey/post_breach/setuid_setgid/setuid_setgid.py new file mode 100644 index 000000000..ab4d8a7ed --- /dev/null +++ b/monkey/infection_monkey/post_breach/setuid_setgid/setuid_setgid.py @@ -0,0 +1,7 @@ +from infection_monkey.post_breach.setuid_setgid.linux_setuid_setgid import\ + get_linux_commands_to_setuid_setgid + + +def get_commands_to_change_setuid_setgid(): + linux_cmds = get_linux_commands_to_setuid_setgid() + 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 088d6dfb6..c96db0651 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, T1154 +from monkey_island.cc.services.attack.technique_reports import T1136, T1156, T1504, T1158, T1154, T1166 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 @@ -41,7 +41,8 @@ TECHNIQUES = {'T1210': T1210.T1210, 'T1156': T1156.T1156, 'T1504': T1504.T1504, 'T1158': T1158.T1158, - 'T1154': T1154.T1154 + 'T1154': T1154.T1154, + 'T1166': T1166.T1166 } 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 f981eb9c8..abb26b71a 100644 --- a/monkey/monkey_island/cc/services/attack/attack_schema.py +++ b/monkey/monkey_island/cc/services/attack/attack_schema.py @@ -118,6 +118,15 @@ SCHEMA = { "description": "Adversaries may gain persistence and elevate privileges " "in certain situations by abusing PowerShell profiles which " "are scripts that run when PowerShell starts." + }, + "T1166": { + "title": "Setuid and Setgid", + "type": "bool", + "value": True, + "necessary": False, + "link": "https://attack.mitre.org/techniques/T1166", + "description": "Adversaries can set the setuid or setgid bits to get code running in " + "a different user’s context." } } }, diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1166.py new file mode 100644 index 000000000..f4a2bafa2 --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1166.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_SETUID_SETGID + + +__author__ = "shreyamalviya" + + +class T1166(AttackTechnique): + tech_id = "T1166" + unscanned_msg = "Monkey did not try creating hidden files or folders." + scanned_msg = "Monkey tried creating hidden files and folders on the system but failed." + used_msg = "Monkey created hidden files and folders on the system." + + query = [{'$match': {'telem_category': 'post_breach', + 'data.name': POST_BREACH_SETUID_SETGID}}, + {'$project': {'_id': 0, + 'machine': {'hostname': '$data.hostname', + 'ips': ['$data.ip']}, + 'result': '$data.result'}}] + + @staticmethod + def get_report_data(): + data = {'title': T1166.technique_title(), 'info': []} + + setuid_setgid_info = list(mongo.db.telemetry.aggregate(T1166.query)) + + status = ScanStatus.UNSCANNED.value + if setuid_setgid_info: + successful_PBAs = mongo.db.telemetry.count({'data.name': POST_BREACH_SETUID_SETGID, + 'data.result.1': True}) + status = ScanStatus.USED.value if successful_PBAs else ScanStatus.SCANNED.value + + data.update(T1166.get_base_data_by_status(status)) + data.update({'info': setuid_setgid_info}) + return data diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index 75173ab6f..4f7027cbc 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -183,6 +183,14 @@ SCHEMA = { ], "title": "Trap", "attack_techniques": ["T1154"] + }, + { + "type": "string", + "enum": [ + "ChangeSetuidSetgid" + ], + "title": "Setuid and Setgid", + "attack_techniques": ["T1166"] } ], }, @@ -406,7 +414,8 @@ SCHEMA = { "CommunicateAsNewUser", "ModifyShellStartupFiles", "HiddenFiles", - "TrapCommand" + "TrapCommand", + "ChangeSetuidSetgid" ], "description": "List of actions the Monkey will run post breach" }, diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1166.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1166.js new file mode 100644 index 000000000..2fa496731 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1166.js @@ -0,0 +1,45 @@ +import React from 'react'; +import ReactTable from 'react-table'; +import {renderMachineFromSystemData, ScanStatus} from './Helpers'; +import MitigationsComponent from './MitigationsComponent'; + +class T1166 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 T1166;