Merge pull request #242 from guardicore/feature/post_breach_actions

Post breach actions
This commit is contained in:
Daniel Goldberg 2019-01-07 10:26:07 +02:00 committed by GitHub
commit 70545d28f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 93 additions and 5 deletions

View File

@ -7,8 +7,6 @@ from abc import ABCMeta
from itertools import product from itertools import product
import importlib import importlib
importlib.import_module('infection_monkey', 'network')
__author__ = 'itamar' __author__ = 'itamar'
GUID = str(uuid.getnode()) GUID = str(uuid.getnode())
@ -22,6 +20,7 @@ class Configuration(object):
# now we won't work at <2.7 for sure # now we won't work at <2.7 for sure
network_import = importlib.import_module('infection_monkey.network') network_import = importlib.import_module('infection_monkey.network')
exploit_import = importlib.import_module('infection_monkey.exploit') exploit_import = importlib.import_module('infection_monkey.exploit')
post_breach_import = importlib.import_module('infection_monkey.post_breach')
unknown_items = [] unknown_items = []
for key, value in formatted_data.items(): for key, value in formatted_data.items():
@ -41,6 +40,9 @@ class Configuration(object):
elif key == 'exploiter_classes': elif key == 'exploiter_classes':
class_objects = [getattr(exploit_import, val) for val in value] class_objects = [getattr(exploit_import, val) for val in value]
setattr(self, key, class_objects) 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: else:
if hasattr(self, key): if hasattr(self, key):
setattr(self, key, value) setattr(self, key, value)
@ -268,5 +270,7 @@ class Configuration(object):
extract_azure_creds = True extract_azure_creds = True
post_breach_actions = []
WormConfiguration = Configuration() WormConfiguration = Configuration()

View File

@ -97,5 +97,6 @@
"timeout_between_iterations": 10, "timeout_between_iterations": 10,
"use_file_logging": true, "use_file_logging": true,
"victims_max_exploit": 7, "victims_max_exploit": 7,
"victims_max_find": 30 "victims_max_find": 30,
"post_breach_actions" : []
} }

View File

@ -109,6 +109,10 @@ class InfectionMonkey(object):
system_info = system_info_collector.get_info() system_info = system_info_collector.get_info()
ControlClient.send_telemetry("system_info_collection", system_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: if 0 == WormConfiguration.depth:
LOG.debug("Reached max depth, shutting down") LOG.debug("Reached max depth, shutting down")
ControlClient.send_telemetry("trace", "Reached max depth, shutting down") ControlClient.send_telemetry("trace", "Reached max depth, shutting down")

View File

@ -0,0 +1,4 @@
__author__ = 'danielg'
from add_user import BackdoorUser

View File

@ -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

View File

@ -14,4 +14,5 @@ six
ecdsa ecdsa
netifaces netifaces
ipaddress ipaddress
wmi wmi
pywin32

View File

@ -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": { "finger_classes": {
"title": "Fingerprint class", "title": "Fingerprint class",
"type": "string", "type": "string",
@ -276,7 +289,19 @@ SCHEMA = {
"type": "boolean", "type": "boolean",
"default": True, "default": True,
"description": "Is the monkey alive" "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": { "behaviour": {