Refactor exploiters into plugins.

Change configuration to support it and remove unneeded complex importing.
Changed main monkey code to support exploiter plugins.
This commit is contained in:
Daniel Goldberg 2019-11-21 15:21:41 +02:00
parent 0f8e8925b3
commit 43d4c36507
14 changed files with 116 additions and 117 deletions

View File

@ -20,10 +20,6 @@ HIDDEN_FIELD_REPLACEMENT_CONTENT = "hidden"
class Configuration(object):
def from_kv(self, formatted_data):
# 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')
unknown_items = []
for key, value in list(formatted_data.items()):
if key.startswith('_'):
@ -32,15 +28,10 @@ class Configuration(object):
continue
if self._depth_from_commandline and key == "depth":
continue
# handle in cases
elif key == 'exploiter_classes':
class_objects = [getattr(exploit_import, val) for val in value]
setattr(self, key, class_objects)
if hasattr(self, key):
setattr(self, key, value)
else:
if hasattr(self, key):
setattr(self, key, value)
else:
unknown_items.append(key)
unknown_items.append(key)
return unknown_items
def from_json(self, json_data):

View File

@ -0,0 +1,98 @@
from abc import abstractmethod
from infection_monkey.config import WormConfiguration
from common.utils.exploit_enum import ExploitType
from datetime import datetime
from infection_monkey.utils.plugins.plugin import Plugin
import infection_monkey.exploit
__author__ = 'itamar'
class HostExploiter(Plugin):
@staticmethod
def should_run(class_name):
"""
Decides if post breach action is enabled in config
:return: True if it needs to be ran, false otherwise
"""
return class_name in WormConfiguration.exploiter_classes
@staticmethod
def base_package_file():
return infection_monkey.exploit.__file__
@staticmethod
def base_package_name():
return infection_monkey.exploit.__package__
_TARGET_OS_TYPE = []
# Usual values are 'vulnerability' or 'brute_force'
EXPLOIT_TYPE = ExploitType.VULNERABILITY
@property
@abstractmethod
def _EXPLOITED_SERVICE(self):
pass
def __init__(self, host):
self._config = WormConfiguration
self.exploit_info = {'display_name': self._EXPLOITED_SERVICE,
'started': '',
'finished': '',
'vulnerable_urls': [],
'vulnerable_ports': [],
'executed_cmds': []}
self.exploit_attempts = []
self.host = host
def set_start_time(self):
self.exploit_info['started'] = datetime.now().isoformat()
def set_finish_time(self):
self.exploit_info['finished'] = datetime.now().isoformat()
def is_os_supported(self):
return self.host.os.get('type') in self._TARGET_OS_TYPE
def send_exploit_telemetry(self, result):
from infection_monkey.telemetry.exploit_telem import ExploitTelem
ExploitTelem(self, result).send()
def report_login_attempt(self, result, user, password='', lm_hash='', ntlm_hash='', ssh_key=''):
self.exploit_attempts.append({'result': result, 'user': user, 'password': password,
'lm_hash': lm_hash, 'ntlm_hash': ntlm_hash, 'ssh_key': ssh_key})
def exploit_host(self):
self.pre_exploit()
try:
result = self._exploit_host()
finally:
self.post_exploit()
return result
def pre_exploit(self):
self.set_start_time()
def post_exploit(self):
self.set_finish_time()
@abstractmethod
def _exploit_host(self):
raise NotImplementedError()
def add_vuln_url(self, url):
self.exploit_info['vulnerable_urls'].append(url)
def add_vuln_port(self, port):
self.exploit_info['vulnerable_ports'].append(port)
def add_executed_cmd(self, cmd):
"""
Appends command to exploiter's info.
:param cmd: String of executed command. e.g. 'echo Example'
"""
powershell = True if "powershell" in cmd.lower() else False
self.exploit_info['executed_cmds'].append({'cmd': cmd, 'powershell': powershell})

View File

@ -1,92 +0,0 @@
from abc import ABCMeta, abstractmethod, abstractproperty
import infection_monkey.config
from common.utils.exploit_enum import ExploitType
from datetime import datetime
__author__ = 'itamar'
class HostExploiter(object, metaclass=ABCMeta):
_TARGET_OS_TYPE = []
# Usual values are 'vulnerability' or 'brute_force'
EXPLOIT_TYPE = ExploitType.VULNERABILITY
@property
@abstractmethod
def _EXPLOITED_SERVICE(self):
pass
def __init__(self, host):
self._config = infection_monkey.config.WormConfiguration
self.exploit_info = {'display_name': self._EXPLOITED_SERVICE,
'started': '',
'finished': '',
'vulnerable_urls': [],
'vulnerable_ports': [],
'executed_cmds': []}
self.exploit_attempts = []
self.host = host
def set_start_time(self):
self.exploit_info['started'] = datetime.now().isoformat()
def set_finish_time(self):
self.exploit_info['finished'] = datetime.now().isoformat()
def is_os_supported(self):
return self.host.os.get('type') in self._TARGET_OS_TYPE
def send_exploit_telemetry(self, result):
from infection_monkey.telemetry.exploit_telem import ExploitTelem
ExploitTelem(self, result).send()
def report_login_attempt(self, result, user, password='', lm_hash='', ntlm_hash='', ssh_key=''):
self.exploit_attempts.append({'result': result, 'user': user, 'password': password,
'lm_hash': lm_hash, 'ntlm_hash': ntlm_hash, 'ssh_key': ssh_key})
def exploit_host(self):
self.pre_exploit()
try:
result = self._exploit_host()
finally:
self.post_exploit()
return result
def pre_exploit(self):
self.set_start_time()
def post_exploit(self):
self.set_finish_time()
@abstractmethod
def _exploit_host(self):
raise NotImplementedError()
def add_vuln_url(self, url):
self.exploit_info['vulnerable_urls'].append(url)
def add_vuln_port(self, port):
self.exploit_info['vulnerable_ports'].append(port)
def add_executed_cmd(self, cmd):
"""
Appends command to exploiter's info.
:param cmd: String of executed command. e.g. 'echo Example'
"""
powershell = True if "powershell" in cmd.lower() else False
self.exploit_info['executed_cmds'].append({'cmd': cmd, 'powershell': powershell})
from infection_monkey.exploit.win_ms08_067 import Ms08_067_Exploiter
from infection_monkey.exploit.wmiexec import WmiExploiter
from infection_monkey.exploit.smbexec import SmbExploiter
from infection_monkey.exploit.sshexec import SSHExploiter
from infection_monkey.exploit.shellshock import ShellShockExploiter
from infection_monkey.exploit.sambacry import SambaCryExploiter
from infection_monkey.exploit.elasticgroovy import ElasticGroovyExploiter
from infection_monkey.exploit.struts2 import Struts2Exploiter
from infection_monkey.exploit.weblogic import WebLogicExploiter
from infection_monkey.exploit.hadoop import HadoopExploiter
from infection_monkey.exploit.mssqlexec import MSSQLExploiter
from infection_monkey.exploit.vsftpd import VSFTPDExploiter

View File

@ -6,7 +6,7 @@ from time import sleep
import pymssql
from common.utils.exploit_enum import ExploitType
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.http_tools import MonkeyHTTPServer
from infection_monkey.exploit.tools.helpers import get_monkey_dest_path, build_monkey_commandline, get_monkey_depth
from infection_monkey.model import DROPPER_ARG

View File

@ -16,7 +16,7 @@ from impacket.smb3structs import SMB2_IL_IMPERSONATION, SMB2_CREATE, SMB2_FLAGS_
from impacket.smbconnection import SMBConnection
import infection_monkey.monkeyfs as monkeyfs
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.model import DROPPER_ARG
from infection_monkey.network.smbfinger import SMB_SERVICE
from infection_monkey.exploit.tools.helpers import build_monkey_commandline, get_target_monkey_by_os, get_monkey_depth

View File

@ -7,7 +7,7 @@ from random import choice
import requests
from common.utils.attack_utils import ScanStatus
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_target_monkey, get_monkey_depth, build_monkey_commandline
from infection_monkey.model import DROPPER_ARG
from infection_monkey.exploit.shellshock_resources import CGI_FILES

View File

@ -3,7 +3,7 @@ from logging import getLogger
from impacket.dcerpc.v5 import transport, scmr
from impacket.smbconnection import SMB_DIALECT
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_target_monkey, get_monkey_depth, build_monkey_commandline
from infection_monkey.exploit.tools.smb_tools import SmbTools
from infection_monkey.model import MONKEY_CMDLINE_DETACHED_WINDOWS, DROPPER_CMDLINE_DETACHED_WINDOWS

View File

@ -5,7 +5,7 @@ import time
import paramiko
import infection_monkey.monkeyfs as monkeyfs
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_target_monkey, get_monkey_depth, build_monkey_commandline
from infection_monkey.model import MONKEY_ARG
from infection_monkey.network.tools import check_tcp_port, get_interface_to_target

View File

@ -8,7 +8,7 @@ import socket
import time
from common.utils.attack_utils import ScanStatus
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_target_monkey, build_monkey_commandline, get_monkey_depth
from infection_monkey.exploit.tools.http_tools import HTTPTools
from infection_monkey.model import MONKEY_ARG, CHMOD_MONKEY, RUN_MONKEY, WGET_HTTP_UPLOAD, DOWNLOAD_TIMEOUT

View File

@ -3,7 +3,7 @@ import re
from posixpath import join
from abc import abstractmethod
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_target_monkey, get_monkey_depth, build_monkey_commandline
from infection_monkey.exploit.tools.http_tools import HTTPTools
from infection_monkey.model import CHECK_COMMAND, ID_STRING, GET_ARCH_LINUX, GET_ARCH_WINDOWS, BITSADMIN_CMDLINE_HTTP, \

View File

@ -7,7 +7,7 @@ from requests import post, exceptions
from http.server import BaseHTTPRequestHandler, HTTPServer
from infection_monkey.exploit.web_rce import WebRCE
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.network.tools import get_interface_to_target
from infection_monkey.network.info import get_free_tcp_port
from http.server import BaseHTTPRequestHandler, HTTPServer

View File

@ -19,7 +19,7 @@ from infection_monkey.exploit.tools.smb_tools import SmbTools
from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
from infection_monkey.network.smbfinger import SMBFinger
from infection_monkey.network.tools import check_tcp_port
from . import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
LOG = getLogger(__name__)

View File

@ -5,7 +5,7 @@ import traceback
from impacket.dcerpc.v5.rpcrt import DCERPCException
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_target_monkey, \
get_monkey_depth, build_monkey_commandline
from infection_monkey.exploit.tools.wmi_tools import AccessDeniedException

View File

@ -30,6 +30,7 @@ from infection_monkey.network.tools import get_interface_to_target
from infection_monkey.exploit.tools.exceptions import ExploitingVulnerableMachineError, FailedExploitationError
from infection_monkey.telemetry.attack.t1106_telem import T1106Telem
from common.utils.attack_utils import ScanStatus, UsageEnum
from infection_monkey.exploit.HostExploiter import HostExploiter
__author__ = 'itamar'
@ -144,10 +145,10 @@ class InfectionMonkey(object):
self._network.initialize()
self._exploiters = WormConfiguration.exploiter_classes
self._fingerprint = HostFinger.get_instances()
self._exploiters = HostExploiter.get_classes()
if not self._keep_running or not WormConfiguration.alive:
break
@ -183,7 +184,8 @@ class InfectionMonkey(object):
if self._default_server:
if self._network.on_island(self._default_server):
machine.set_default_server(get_interface_to_target(machine.ip_addr) +
(':' + self._default_server_port if self._default_server_port else ''))
(
':' + self._default_server_port if self._default_server_port else ''))
else:
machine.set_default_server(self._default_server)
LOG.debug("Default server for machine: %r set to %s" % (machine, machine.default_server))