Exploit ordering implemented using enum
This commit is contained in:
parent
85044bc0c7
commit
04358d556a
|
@ -0,0 +1,7 @@
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class ExploitType(Enum):
|
||||||
|
VULNERABILITY = 1
|
||||||
|
OTHER = 8
|
||||||
|
BRUTE_FORCE = 9
|
|
@ -1,5 +1,6 @@
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
import infection_monkey.config
|
import infection_monkey.config
|
||||||
|
from common.utils.exploit_enum import ExploitType
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
|
@ -9,6 +10,9 @@ class HostExploiter(object):
|
||||||
|
|
||||||
_TARGET_OS_TYPE = []
|
_TARGET_OS_TYPE = []
|
||||||
|
|
||||||
|
# Usual values are 'vulnerability' or 'brute_force'
|
||||||
|
EXPLOIT_TYPE = ExploitType.VULNERABILITY
|
||||||
|
|
||||||
def __init__(self, host):
|
def __init__(self, host):
|
||||||
self._config = infection_monkey.config.WormConfiguration
|
self._config = infection_monkey.config.WormConfiguration
|
||||||
self._exploit_info = {}
|
self._exploit_info = {}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import logging
|
||||||
import pymssql
|
import pymssql
|
||||||
|
|
||||||
from infection_monkey.exploit import HostExploiter, mssqlexec_utils
|
from infection_monkey.exploit import HostExploiter, mssqlexec_utils
|
||||||
|
from common.utils.exploit_enum import ExploitType
|
||||||
|
|
||||||
__author__ = 'Maor Rayzin'
|
__author__ = 'Maor Rayzin'
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ LOG = logging.getLogger(__name__)
|
||||||
class MSSQLExploiter(HostExploiter):
|
class MSSQLExploiter(HostExploiter):
|
||||||
|
|
||||||
_TARGET_OS_TYPE = ['windows']
|
_TARGET_OS_TYPE = ['windows']
|
||||||
|
EXPLOIT_TYPE = ExploitType.BRUTE_FORCE
|
||||||
LOGIN_TIMEOUT = 15
|
LOGIN_TIMEOUT = 15
|
||||||
SQL_DEFAULT_TCP_PORT = '1433'
|
SQL_DEFAULT_TCP_PORT = '1433'
|
||||||
DEFAULT_PAYLOAD_PATH = os.path.expandvars(r'%TEMP%\~PLD123.bat') if platform.system() else '/tmp/~PLD123.bat'
|
DEFAULT_PAYLOAD_PATH = os.path.expandvars(r'%TEMP%\~PLD123.bat') if platform.system() else '/tmp/~PLD123.bat'
|
||||||
|
|
|
@ -16,6 +16,7 @@ from infection_monkey.model import RDP_CMDLINE_HTTP_BITS, RDP_CMDLINE_HTTP_VBS
|
||||||
from infection_monkey.network.tools import check_tcp_port
|
from infection_monkey.network.tools import check_tcp_port
|
||||||
from infection_monkey.exploit.tools import build_monkey_commandline
|
from infection_monkey.exploit.tools import build_monkey_commandline
|
||||||
from infection_monkey.utils import utf_to_ascii
|
from infection_monkey.utils import utf_to_ascii
|
||||||
|
from common.utils.exploit_enum import ExploitType
|
||||||
|
|
||||||
__author__ = 'hoffer'
|
__author__ = 'hoffer'
|
||||||
|
|
||||||
|
@ -235,6 +236,7 @@ class CMDClientFactory(rdp.ClientFactory):
|
||||||
class RdpExploiter(HostExploiter):
|
class RdpExploiter(HostExploiter):
|
||||||
|
|
||||||
_TARGET_OS_TYPE = ['windows']
|
_TARGET_OS_TYPE = ['windows']
|
||||||
|
EXPLOIT_TYPE = ExploitType.BRUTE_FORCE
|
||||||
|
|
||||||
def __init__(self, host):
|
def __init__(self, host):
|
||||||
super(RdpExploiter, self).__init__(host)
|
super(RdpExploiter, self).__init__(host)
|
||||||
|
|
|
@ -9,12 +9,14 @@ from infection_monkey.model import MONKEY_CMDLINE_DETACHED_WINDOWS, DROPPER_CMDL
|
||||||
from infection_monkey.network import SMBFinger
|
from infection_monkey.network import SMBFinger
|
||||||
from infection_monkey.network.tools import check_tcp_port
|
from infection_monkey.network.tools import check_tcp_port
|
||||||
from infection_monkey.exploit.tools import build_monkey_commandline
|
from infection_monkey.exploit.tools import build_monkey_commandline
|
||||||
|
from common.utils.exploit_enum import ExploitType
|
||||||
|
|
||||||
LOG = getLogger(__name__)
|
LOG = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SmbExploiter(HostExploiter):
|
class SmbExploiter(HostExploiter):
|
||||||
_TARGET_OS_TYPE = ['windows']
|
_TARGET_OS_TYPE = ['windows']
|
||||||
|
EXPLOIT_TYPE = ExploitType.BRUTE_FORCE
|
||||||
KNOWN_PROTOCOLS = {
|
KNOWN_PROTOCOLS = {
|
||||||
'139/SMB': (r'ncacn_np:%s[\pipe\svcctl]', 139),
|
'139/SMB': (r'ncacn_np:%s[\pipe\svcctl]', 139),
|
||||||
'445/SMB': (r'ncacn_np:%s[\pipe\svcctl]', 445),
|
'445/SMB': (r'ncacn_np:%s[\pipe\svcctl]', 445),
|
||||||
|
|
|
@ -10,6 +10,7 @@ from infection_monkey.exploit.tools import get_target_monkey, get_monkey_depth
|
||||||
from infection_monkey.model import MONKEY_ARG
|
from infection_monkey.model import MONKEY_ARG
|
||||||
from infection_monkey.network.tools import check_tcp_port
|
from infection_monkey.network.tools import check_tcp_port
|
||||||
from infection_monkey.exploit.tools import build_monkey_commandline
|
from infection_monkey.exploit.tools import build_monkey_commandline
|
||||||
|
from common.utils.exploit_enum import ExploitType
|
||||||
|
|
||||||
__author__ = 'hoffer'
|
__author__ = 'hoffer'
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ TRANSFER_UPDATE_RATE = 15
|
||||||
|
|
||||||
class SSHExploiter(HostExploiter):
|
class SSHExploiter(HostExploiter):
|
||||||
_TARGET_OS_TYPE = ['linux', None]
|
_TARGET_OS_TYPE = ['linux', None]
|
||||||
|
EXPLOIT_TYPE = ExploitType.BRUTE_FORCE
|
||||||
|
|
||||||
def __init__(self, host):
|
def __init__(self, host):
|
||||||
super(SSHExploiter, self).__init__(host)
|
super(SSHExploiter, self).__init__(host)
|
||||||
|
|
|
@ -9,12 +9,14 @@ from infection_monkey.exploit import HostExploiter
|
||||||
from infection_monkey.exploit.tools import SmbTools, WmiTools, AccessDeniedException, get_target_monkey, \
|
from infection_monkey.exploit.tools import SmbTools, WmiTools, AccessDeniedException, get_target_monkey, \
|
||||||
get_monkey_depth, build_monkey_commandline
|
get_monkey_depth, build_monkey_commandline
|
||||||
from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
|
from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
|
||||||
|
from common.utils.exploit_enum import ExploitType
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class WmiExploiter(HostExploiter):
|
class WmiExploiter(HostExploiter):
|
||||||
_TARGET_OS_TYPE = ['windows']
|
_TARGET_OS_TYPE = ['windows']
|
||||||
|
EXPLOIT_TYPE = ExploitType.BRUTE_FORCE
|
||||||
|
|
||||||
def __init__(self, host):
|
def __init__(self, host):
|
||||||
super(WmiExploiter, self).__init__(host)
|
super(WmiExploiter, self).__init__(host)
|
||||||
|
|
|
@ -167,44 +167,17 @@ class InfectionMonkey(object):
|
||||||
LOG.debug("Default server: %s set to machine: %r" % (self._default_server, machine))
|
LOG.debug("Default server: %s set to machine: %r" % (self._default_server, machine))
|
||||||
machine.set_default_server(self._default_server)
|
machine.set_default_server(self._default_server)
|
||||||
|
|
||||||
successful_exploiter = None
|
# Order exploits according to their type
|
||||||
|
self._exploiters = sorted(self._exploiters, key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value)
|
||||||
|
host_exploited = False
|
||||||
for exploiter in [exploiter(machine) for exploiter in self._exploiters]:
|
for exploiter in [exploiter(machine) for exploiter in self._exploiters]:
|
||||||
if not exploiter.is_os_supported():
|
if self.try_exploiting(machine, exploiter):
|
||||||
LOG.info("Skipping exploiter %s host:%r, os is not supported",
|
host_exploited = True
|
||||||
exploiter.__class__.__name__, machine)
|
|
||||||
continue
|
|
||||||
|
|
||||||
LOG.info("Trying to exploit %r with exploiter %s...", machine, exploiter.__class__.__name__)
|
|
||||||
|
|
||||||
result = False
|
|
||||||
try:
|
|
||||||
result = exploiter.exploit_host()
|
|
||||||
if result:
|
|
||||||
successful_exploiter = exploiter
|
|
||||||
break
|
break
|
||||||
else:
|
if not host_exploited:
|
||||||
LOG.info("Failed exploiting %r with exploiter %s", machine, exploiter.__class__.__name__)
|
|
||||||
|
|
||||||
except Exception as exc:
|
|
||||||
LOG.exception("Exception while attacking %s using %s: %s",
|
|
||||||
machine, exploiter.__class__.__name__, exc)
|
|
||||||
finally:
|
|
||||||
exploiter.send_exploit_telemetry(result)
|
|
||||||
|
|
||||||
if successful_exploiter:
|
|
||||||
self._exploited_machines.add(machine)
|
|
||||||
|
|
||||||
LOG.info("Successfully propagated to %s using %s",
|
|
||||||
machine, successful_exploiter.__class__.__name__)
|
|
||||||
|
|
||||||
# check if max-exploitation limit is reached
|
|
||||||
if WormConfiguration.victims_max_exploit <= len(self._exploited_machines):
|
|
||||||
self._keep_running = False
|
|
||||||
|
|
||||||
LOG.info("Max exploited victims reached (%d)", WormConfiguration.victims_max_exploit)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
self._fail_exploitation_machines.add(machine)
|
self._fail_exploitation_machines.add(machine)
|
||||||
|
if not self._keep_running:
|
||||||
|
break
|
||||||
|
|
||||||
if (not is_empty) and (WormConfiguration.max_iterations > iteration_index + 1):
|
if (not is_empty) and (WormConfiguration.max_iterations > iteration_index + 1):
|
||||||
time_to_sleep = WormConfiguration.timeout_between_iterations
|
time_to_sleep = WormConfiguration.timeout_between_iterations
|
||||||
|
@ -279,3 +252,50 @@ class InfectionMonkey(object):
|
||||||
log = ''
|
log = ''
|
||||||
|
|
||||||
ControlClient.send_log(log)
|
ControlClient.send_log(log)
|
||||||
|
|
||||||
|
def try_exploiting(self, machine, exploiter):
|
||||||
|
"""
|
||||||
|
Workflow of exploiting one machine with one exploiter
|
||||||
|
:param machine: Machine monkey tries to exploit
|
||||||
|
:param exploiter: Exploiter to use on that machine
|
||||||
|
:return: True if successfully exploited, False otherwise
|
||||||
|
"""
|
||||||
|
if not exploiter.is_os_supported():
|
||||||
|
LOG.info("Skipping exploiter %s host:%r, os is not supported",
|
||||||
|
exploiter.__class__.__name__, machine)
|
||||||
|
return False
|
||||||
|
|
||||||
|
LOG.info("Trying to exploit %r with exploiter %s...", machine, exploiter.__class__.__name__)
|
||||||
|
|
||||||
|
result = False
|
||||||
|
try:
|
||||||
|
result = exploiter.exploit_host()
|
||||||
|
if result:
|
||||||
|
self.successfully_exploited(machine, exploiter)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
LOG.info("Failed exploiting %r with exploiter %s", machine, exploiter.__class__.__name__)
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
LOG.exception("Exception while attacking %s using %s: %s",
|
||||||
|
machine, exploiter.__class__.__name__, exc)
|
||||||
|
finally:
|
||||||
|
exploiter.send_exploit_telemetry(result)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def successfully_exploited(self, machine, exploiter):
|
||||||
|
"""
|
||||||
|
Workflow of registering successfully exploited machine
|
||||||
|
:param machine: machine that was exploited
|
||||||
|
:param exploiter: exploiter that succeeded
|
||||||
|
"""
|
||||||
|
self._exploited_machines.add(machine)
|
||||||
|
|
||||||
|
LOG.info("Successfully propagated to %s using %s",
|
||||||
|
machine, exploiter.__class__.__name__)
|
||||||
|
|
||||||
|
# check if max-exploitation limit is reached
|
||||||
|
if WormConfiguration.victims_max_exploit <= len(self._exploited_machines):
|
||||||
|
self._keep_running = False
|
||||||
|
|
||||||
|
LOG.info("Max exploited victims reached (%d)", WormConfiguration.victims_max_exploit)
|
||||||
|
|
Loading…
Reference in New Issue