From d3a42792fb0605049c9d987cb2a7b6828fe45a0d Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Mon, 31 Dec 2018 18:41:56 +0200 Subject: [PATCH 1/5] Remove dead line of code in config.py --- monkey/infection_monkey/config.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 4a63c082b..74a98feb1 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -7,8 +7,6 @@ from abc import ABCMeta from itertools import product import importlib -importlib.import_module('infection_monkey', 'network') - __author__ = 'itamar' GUID = str(uuid.getnode()) From 077d5365266536685a3fd9d3846465e2167a89cb Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Wed, 2 Jan 2019 19:31:03 +0200 Subject: [PATCH 2/5] Add missing dependency --- monkey/infection_monkey/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/monkey/infection_monkey/requirements.txt b/monkey/infection_monkey/requirements.txt index 468b748e8..e08cbf4ca 100644 --- a/monkey/infection_monkey/requirements.txt +++ b/monkey/infection_monkey/requirements.txt @@ -14,4 +14,5 @@ six ecdsa netifaces ipaddress -wmi \ No newline at end of file +wmi +pywin32 \ No newline at end of file From 382b95c75d13f8d3129669cf1784cd9e6cd4d65b Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Mon, 31 Dec 2018 18:26:46 +0200 Subject: [PATCH 3/5] Add option for post breach actions to configuration --- monkey/infection_monkey/config.py | 6 +++++ monkey/infection_monkey/example.conf | 3 ++- .../cc/services/config_schema.py | 27 ++++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 74a98feb1..6234cd9ff 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -20,6 +20,7 @@ class Configuration(object): # now we won't work at <2.7 for sure network_import = importlib.import_module('infection_monkey.network') exploit_import = importlib.import_module('infection_monkey.exploit') + post_breach_import = importlib.import_module('infection_monkey.post_breach') unknown_items = [] for key, value in formatted_data.items(): @@ -39,6 +40,9 @@ class Configuration(object): elif key == 'exploiter_classes': class_objects = [getattr(exploit_import, val) for val in value] setattr(self, key, class_objects) + elif key == 'post_breach_actions': + class_objects = [getattr(post_breach_import, val) for val in value] + setattr(self, key, class_objects) else: if hasattr(self, key): setattr(self, key, value) @@ -266,5 +270,7 @@ class Configuration(object): extract_azure_creds = True + post_breach_actions = [] + WormConfiguration = Configuration() diff --git a/monkey/infection_monkey/example.conf b/monkey/infection_monkey/example.conf index 0779301d2..0bdcc0eb2 100644 --- a/monkey/infection_monkey/example.conf +++ b/monkey/infection_monkey/example.conf @@ -97,5 +97,6 @@ "timeout_between_iterations": 10, "use_file_logging": true, "victims_max_exploit": 7, - "victims_max_find": 30 + "victims_max_find": 30, + "post_breach_actions" : [] } diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index d4d294afc..0a1ca24d6 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -88,6 +88,19 @@ SCHEMA = { } ] }, + "post_breach_acts": { + "title": "Post breach actions", + "type": "string", + "anyOf": [ + { + "type": "string", + "enum": [ + "BackdoorUser" + ], + "title": "Back door user", + }, + ], + }, "finger_classes": { "title": "Fingerprint class", "type": "string", @@ -276,7 +289,19 @@ SCHEMA = { "type": "boolean", "default": True, "description": "Is the monkey alive" - } + }, + "post_breach_actions": { + "title": "Post breach actions", + "type": "array", + "uniqueItems": True, + "items": { + "$ref": "#/definitions/post_breach_acts" + }, + "default": [ + "BackdoorUser", + ], + "description": "List of actions the Monkey will run post breach" + }, } }, "behaviour": { From 95a2a0e4284cf2a7c94771e43a4e2781ea4cfc63 Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Wed, 2 Jan 2019 19:31:26 +0200 Subject: [PATCH 4/5] Add backdoor user functionality to Monkey itself. The backdoor user is purposefully disabled --- .../infection_monkey/post_breach/__init__.py | 4 ++ .../infection_monkey/post_breach/add_user.py | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 monkey/infection_monkey/post_breach/__init__.py create mode 100644 monkey/infection_monkey/post_breach/add_user.py diff --git a/monkey/infection_monkey/post_breach/__init__.py b/monkey/infection_monkey/post_breach/__init__.py new file mode 100644 index 000000000..3faa2233e --- /dev/null +++ b/monkey/infection_monkey/post_breach/__init__.py @@ -0,0 +1,4 @@ +__author__ = 'danielg' + + +from add_user import BackdoorUser \ No newline at end of file diff --git a/monkey/infection_monkey/post_breach/add_user.py b/monkey/infection_monkey/post_breach/add_user.py new file mode 100644 index 000000000..8551382b7 --- /dev/null +++ b/monkey/infection_monkey/post_breach/add_user.py @@ -0,0 +1,49 @@ +import datetime +import logging +import subprocess +import sys +from infection_monkey.config import WormConfiguration + +LOG = logging.getLogger(__name__) + +# Linux doesn't have WindowsError +try: + WindowsError +except NameError: + WindowsError = None + +__author__ = 'danielg' + + +class BackdoorUser(object): + """ + This module adds a disabled user to the system. + This tests part of the ATT&CK matrix + """ + + def act(self): + LOG.info("Adding a user") + if sys.platform.startswith("win"): + retval = self.add_user_windows() + else: + retval = self.add_user_linux() + if retval != 0: + LOG.warn("Failed to add a user") + else: + LOG.info("Done adding user") + + @staticmethod + def add_user_linux(): + cmd_line = ['useradd', '-M', '--expiredate', + datetime.datetime.today().strftime('%Y-%m-%d'), '--inactive', '0', '-c', 'MONKEY_USER', + WormConfiguration.ms08_067_remote_user_add] + retval = subprocess.call(cmd_line) + return retval + + @staticmethod + def add_user_windows(): + cmd_line = ['net', 'user', WormConfiguration.ms08_067_remote_user_add, + WormConfiguration.ms08_067_remote_user_pass, + '/add', '/ACTIVE:NO'] + retval = subprocess.call(cmd_line) + return retval From 7b5604a0de095692b3d24e680bfc60b20c6fe633 Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Wed, 2 Jan 2019 19:31:42 +0200 Subject: [PATCH 5/5] Make post breach actions happen in the monkey --- monkey/infection_monkey/monkey.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 30eb57f1c..4d5bdf7dc 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -109,6 +109,10 @@ class InfectionMonkey(object): system_info = system_info_collector.get_info() ControlClient.send_telemetry("system_info_collection", system_info) + for action_class in WormConfiguration.post_breach_actions: + action = action_class() + action.act() + if 0 == WormConfiguration.depth: LOG.debug("Reached max depth, shutting down") ControlClient.send_telemetry("trace", "Reached max depth, shutting down")