Agent: Add LM and NT hashes to PowerShell Credentials

Adds two list parameters to get_credentials() that contain LM and NT
hashes respectively. Adds a "secret_type" field to Credentials so that
the user of the Credentials object can distinguish between using cached
credentials (on windows), passwords, and NT or LM hashes.
This commit is contained in:
Mike Salvatore 2021-09-02 12:29:49 -04:00
parent 3a6f725cc4
commit a2e6b0bfbd
4 changed files with 132 additions and 26 deletions

View File

@ -13,7 +13,11 @@ from infection_monkey.exploit.powershell_utils.auth_options import (
AuthOptions,
get_auth_options,
)
from infection_monkey.exploit.powershell_utils.credentials import Credentials, get_credentials
from infection_monkey.exploit.powershell_utils.credentials import (
Credentials,
SecretType,
get_credentials,
)
from infection_monkey.exploit.powershell_utils.powershell_client import (
AuthenticationError,
IPowerShellClient,
@ -49,7 +53,11 @@ class PowerShellExploiter(HostExploiter):
return False
credentials = get_credentials(
self._config.exploit_user_list, self._config.exploit_password_list, is_windows_os()
self._config.exploit_user_list,
self._config.exploit_password_list,
[],
[],
is_windows_os(),
)
auth_options = get_auth_options(credentials, is_https)
@ -89,6 +97,7 @@ class PowerShellExploiter(HostExploiter):
credentials = Credentials(
username="dummy_username",
secret="dummy_password",
secret_type=SecretType.PASSWORD,
)
auth_options = AuthOptions(

View File

@ -1,21 +1,36 @@
from dataclasses import dataclass
from enum import Enum
from itertools import product
from typing import List, Union
class SecretType(Enum):
CACHED = 1
PASSWORD = 2
LM_HASH = 3
NT_HASH = 4
@dataclass
class Credentials:
username: Union[str, None]
secret: Union[str, None]
secret_type: SecretType
def get_credentials(
usernames: List[str], passwords: List[str], is_windows: bool
usernames: List[str],
passwords: List[str],
lm_hashes: List[str],
nt_hashes: List[str],
is_windows: bool,
) -> List[Credentials]:
credentials = []
credentials.extend(_get_empty_credentials(is_windows))
credentials.extend(_get_username_only_credentials(usernames, is_windows))
credentials.extend(_get_username_password_credentials(usernames, passwords))
credentials.extend(_get_username_lm_hash_credentials(usernames, lm_hashes))
credentials.extend(_get_username_nt_hash_credentials(usernames, nt_hashes))
return credentials
@ -24,7 +39,7 @@ def get_credentials(
# will be used to attempt to log into the victim.
def _get_empty_credentials(is_windows: bool) -> List[Credentials]:
if is_windows:
return [Credentials(username=None, secret=None)]
return [Credentials(username=None, secret=None, secret_type=SecretType.CACHED)]
return []
@ -32,10 +47,18 @@ def _get_empty_credentials(is_windows: bool) -> List[Credentials]:
# On Windows systems, when password == None, the current user's password will bu used to attempt to
# log into the victim.
def _get_username_only_credentials(usernames: List[str], is_windows: bool) -> List[Credentials]:
credentials = [Credentials(username=username, secret="") for username in usernames]
credentials = [
Credentials(username=username, secret="", secret_type=SecretType.PASSWORD)
for username in usernames
]
if is_windows:
credentials.extend([Credentials(username=username, secret=None) for username in usernames])
credentials.extend(
[
Credentials(username=username, secret=None, secret_type=SecretType.CACHED)
for username in usernames
]
)
return credentials
@ -43,6 +66,27 @@ def _get_username_only_credentials(usernames: List[str], is_windows: bool) -> Li
def _get_username_password_credentials(
usernames: List[str], passwords: List[str]
) -> List[Credentials]:
username_password_pairs = product(usernames, passwords)
return _get_username_secret_credentials(usernames, passwords, SecretType.PASSWORD)
return [Credentials(credentials[0], credentials[1]) for credentials in username_password_pairs]
def _get_username_lm_hash_credentials(
usernames: List[str], lm_hashes: List[str]
) -> List[Credentials]:
return _get_username_secret_credentials(usernames, lm_hashes, SecretType.LM_HASH)
def _get_username_nt_hash_credentials(
usernames: List[str], nt_hashes: List[str]
) -> List[Credentials]:
return _get_username_secret_credentials(usernames, nt_hashes, SecretType.NT_HASH)
def _get_username_secret_credentials(
usernames: List[str], secrets: List[str], secret_type: SecretType
) -> List[Credentials]:
username_secret_pairs = product(usernames, secrets)
return [
Credentials(credentials[0], credentials[1], secret_type)
for credentials in username_secret_pairs
]

View File

@ -6,12 +6,12 @@ from infection_monkey.exploit.powershell_utils.auth_options import (
ENCRYPTION_NEVER,
get_auth_options,
)
from infection_monkey.exploit.powershell_utils.credentials import Credentials
from infection_monkey.exploit.powershell_utils.credentials import Credentials, SecretType
CREDENTIALS = [
Credentials("user1", "password1"),
Credentials("user2", ""),
Credentials("user3", None),
Credentials("user1", "password1", SecretType.PASSWORD),
Credentials("user2", "", SecretType.PASSWORD),
Credentials("user3", None, SecretType.CACHED),
]

View File

@ -1,44 +1,97 @@
from infection_monkey.exploit.powershell_utils.credentials import Credentials, get_credentials
from infection_monkey.exploit.powershell_utils.credentials import (
Credentials,
SecretType,
get_credentials,
)
TEST_USERNAMES = ["user1", "user2"]
TEST_PASSWORDS = ["p1", "p2"]
TEST_LM_HASHES = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"]
TEST_NT_HASHES = ["cccccccccccccccccccccccccccccccc", "dddddddddddddddddddddddddddddddd"]
def test_get_credentials__empty_windows_true():
credentials = get_credentials([], [], True)
credentials = get_credentials([], [], [], [], True)
assert len(credentials) == 1
assert credentials[0] == Credentials(username=None, secret=None)
assert credentials[0] == Credentials(username=None, secret=None, secret_type=SecretType.CACHED)
def test_get_credentials__empty_windows_false():
credentials = get_credentials([], [], False)
credentials = get_credentials([], [], [], [], False)
assert len(credentials) == 0
def test_get_credentials__username_only_windows_true():
credentials = get_credentials(TEST_USERNAMES, [], True)
credentials = get_credentials(TEST_USERNAMES, [], [], [], True)
assert len(credentials) == 5
assert Credentials(username=TEST_USERNAMES[0], secret="") in credentials
assert Credentials(username=TEST_USERNAMES[1], secret="") in credentials
assert Credentials(username=TEST_USERNAMES[0], secret=None) in credentials
assert Credentials(username=TEST_USERNAMES[1], secret=None) in credentials
assert (
Credentials(username=TEST_USERNAMES[0], secret="", secret_type=SecretType.PASSWORD)
in credentials
)
assert (
Credentials(username=TEST_USERNAMES[1], secret="", secret_type=SecretType.PASSWORD)
in credentials
)
assert (
Credentials(username=TEST_USERNAMES[0], secret=None, secret_type=SecretType.CACHED)
in credentials
)
assert (
Credentials(username=TEST_USERNAMES[1], secret=None, secret_type=SecretType.CACHED)
in credentials
)
def test_get_credentials__username_only_windows_false():
credentials = get_credentials(TEST_USERNAMES, [], False)
credentials = get_credentials(TEST_USERNAMES, [], [], [], False)
assert len(credentials) == 2
assert Credentials(username=TEST_USERNAMES[0], secret="") in credentials
assert Credentials(username=TEST_USERNAMES[1], secret="") in credentials
assert (
Credentials(username=TEST_USERNAMES[0], secret="", secret_type=SecretType.PASSWORD)
in credentials
)
assert (
Credentials(username=TEST_USERNAMES[1], secret="", secret_type=SecretType.PASSWORD)
in credentials
)
def test_get_credentials__username_password_windows_true():
credentials = get_credentials(TEST_USERNAMES, TEST_PASSWORDS, True)
credentials = get_credentials(TEST_USERNAMES, TEST_PASSWORDS, [], [], True)
assert len(credentials) == 9
for user in TEST_USERNAMES:
for password in TEST_PASSWORDS:
assert Credentials(username=user, secret=password) in credentials
assert (
Credentials(username=user, secret=password, secret_type=SecretType.PASSWORD)
in credentials
)
def test_get_credentials__username_lm_hash_windows_false():
credentials = get_credentials(TEST_USERNAMES, TEST_PASSWORDS, TEST_LM_HASHES, [], False)
assert len(credentials) == 10
for user in TEST_USERNAMES:
for lm_hash in TEST_LM_HASHES:
assert (
Credentials(username=user, secret=lm_hash, secret_type=SecretType.LM_HASH)
in credentials
)
def test_get_credentials__username_nt_hash_windows_false():
credentials = get_credentials(
TEST_USERNAMES, TEST_PASSWORDS, TEST_LM_HASHES, TEST_NT_HASHES, False
)
assert len(credentials) == 14
for user in TEST_USERNAMES:
for nt_hash in TEST_NT_HASHES:
assert (
Credentials(username=user, secret=nt_hash, secret_type=SecretType.NT_HASH)
in credentials
)