forked from p15670423/monkey
Agent: Skip empty password attempts in PowerShell if HTTP disabled
This commit is contained in:
parent
06899be264
commit
45658b5559
|
@ -39,7 +39,7 @@ class PowerShellExploiter(HostExploiter):
|
|||
self._client = None
|
||||
|
||||
def _exploit_host(self):
|
||||
if not self._is_any_default_port_open():
|
||||
if not self._any_powershell_port_is_open():
|
||||
message = "PowerShell Remoting appears to be disabled on the remote host"
|
||||
self.exploit_result.error_message = message
|
||||
logger.debug(message)
|
||||
|
@ -77,13 +77,21 @@ class PowerShellExploiter(HostExploiter):
|
|||
|
||||
return self.exploit_result
|
||||
|
||||
def _is_any_default_port_open(self) -> bool:
|
||||
return "tcp-5985" in self.host.services or "tcp-5986" in self.host.services
|
||||
def _any_powershell_port_is_open(self) -> bool:
|
||||
return self._http_powershell_port_is_open() or self._https_powershell_port_is_open()
|
||||
|
||||
def _http_powershell_port_is_open(self) -> bool:
|
||||
return "tcp-5985" in self.host.services
|
||||
|
||||
def _https_powershell_port_is_open(self) -> bool:
|
||||
return "tcp-5986" in self.host.services
|
||||
|
||||
def _authenticate_via_brute_force(
|
||||
self, credentials: List[Credentials], auth_options: List[AuthOptions]
|
||||
) -> Optional[IPowerShellClient]:
|
||||
for (creds, opts) in interruptible_iter(zip(credentials, auth_options), self.interrupt):
|
||||
creds_opts_pairs = filter(self.check_ssl_setting_is_valid, zip(credentials, auth_options))
|
||||
for (creds, opts) in interruptible_iter(creds_opts_pairs, self.interrupt):
|
||||
|
||||
try:
|
||||
client = PowerShellClient(self.host.ip_addr, creds, opts)
|
||||
client.connect()
|
||||
|
@ -105,6 +113,17 @@ class PowerShellExploiter(HostExploiter):
|
|||
|
||||
return None
|
||||
|
||||
def check_ssl_setting_is_valid(self, creds_opts_pair):
|
||||
opts = creds_opts_pair[1]
|
||||
|
||||
if opts.ssl and not self._https_powershell_port_is_open():
|
||||
return False
|
||||
|
||||
if not opts.ssl and not self._http_powershell_port_is_open():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
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)
|
||||
|
|
|
@ -76,8 +76,6 @@ def test_powershell_http(monkeypatch, powershell_exploiter, powershell_arguments
|
|||
|
||||
|
||||
def test_powershell_https(monkeypatch, powershell_exploiter, powershell_arguments, https_only_host):
|
||||
powershell_arguments["host"] = https_only_host
|
||||
|
||||
mock_powershell_client = MagicMock()
|
||||
mock_powershell_client.connect = MagicMock(side_effect=Exception("Failed login"))
|
||||
mock_powershell_client_constructor = MagicMock(return_value=mock_powershell_client)
|
||||
|
@ -85,11 +83,15 @@ def test_powershell_https(monkeypatch, powershell_exploiter, powershell_argument
|
|||
|
||||
powershell_exploiter.exploit_host(**powershell_arguments)
|
||||
|
||||
non_ssl_calls = 0
|
||||
for call_args in mock_powershell_client_constructor.call_args_list:
|
||||
if call_args[0][1].secret != "":
|
||||
assert call_args[0][2].ssl
|
||||
else:
|
||||
assert not call_args[0][2].ssl
|
||||
non_ssl_calls += 1
|
||||
|
||||
assert non_ssl_calls > 0
|
||||
|
||||
|
||||
def test_no_valid_credentials(monkeypatch, powershell_exploiter, powershell_arguments):
|
||||
|
@ -185,3 +187,22 @@ def test_build_monkey_execution_command():
|
|||
|
||||
assert f"-d {depth}" in cmd
|
||||
assert executable_path in cmd
|
||||
|
||||
|
||||
def test_skip_http_only_logins(
|
||||
monkeypatch, powershell_exploiter, powershell_arguments, https_only_host
|
||||
):
|
||||
# Only HTTPS is enabled on the destination, so we should never try to connect with "" empty
|
||||
# password, since connection with empty password requires SSL == False.
|
||||
powershell_arguments["host"] = https_only_host
|
||||
|
||||
mock_powershell_client = MagicMock()
|
||||
mock_powershell_client.connect = MagicMock(side_effect=Exception("Failed login"))
|
||||
mock_powershell_client_constructor = MagicMock(return_value=mock_powershell_client)
|
||||
monkeypatch.setattr(powershell, "PowerShellClient", mock_powershell_client_constructor)
|
||||
|
||||
powershell_exploiter.exploit_host(**powershell_arguments)
|
||||
|
||||
for call_args in mock_powershell_client_constructor.call_args_list:
|
||||
assert call_args[0][1].secret != ""
|
||||
assert call_args[0][2].ssl
|
||||
|
|
Loading…
Reference in New Issue