forked from p15670423/monkey
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:
parent
3a6f725cc4
commit
a2e6b0bfbd
|
@ -13,7 +13,11 @@ from infection_monkey.exploit.powershell_utils.auth_options import (
|
||||||
AuthOptions,
|
AuthOptions,
|
||||||
get_auth_options,
|
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 (
|
from infection_monkey.exploit.powershell_utils.powershell_client import (
|
||||||
AuthenticationError,
|
AuthenticationError,
|
||||||
IPowerShellClient,
|
IPowerShellClient,
|
||||||
|
@ -49,7 +53,11 @@ class PowerShellExploiter(HostExploiter):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
credentials = get_credentials(
|
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)
|
auth_options = get_auth_options(credentials, is_https)
|
||||||
|
|
||||||
|
@ -89,6 +97,7 @@ class PowerShellExploiter(HostExploiter):
|
||||||
credentials = Credentials(
|
credentials = Credentials(
|
||||||
username="dummy_username",
|
username="dummy_username",
|
||||||
secret="dummy_password",
|
secret="dummy_password",
|
||||||
|
secret_type=SecretType.PASSWORD,
|
||||||
)
|
)
|
||||||
|
|
||||||
auth_options = AuthOptions(
|
auth_options = AuthOptions(
|
||||||
|
|
|
@ -1,21 +1,36 @@
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from enum import Enum
|
||||||
from itertools import product
|
from itertools import product
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
|
|
||||||
|
|
||||||
|
class SecretType(Enum):
|
||||||
|
CACHED = 1
|
||||||
|
PASSWORD = 2
|
||||||
|
LM_HASH = 3
|
||||||
|
NT_HASH = 4
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Credentials:
|
class Credentials:
|
||||||
username: Union[str, None]
|
username: Union[str, None]
|
||||||
secret: Union[str, None]
|
secret: Union[str, None]
|
||||||
|
secret_type: SecretType
|
||||||
|
|
||||||
|
|
||||||
def get_credentials(
|
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]:
|
) -> List[Credentials]:
|
||||||
credentials = []
|
credentials = []
|
||||||
credentials.extend(_get_empty_credentials(is_windows))
|
credentials.extend(_get_empty_credentials(is_windows))
|
||||||
credentials.extend(_get_username_only_credentials(usernames, is_windows))
|
credentials.extend(_get_username_only_credentials(usernames, is_windows))
|
||||||
credentials.extend(_get_username_password_credentials(usernames, passwords))
|
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
|
return credentials
|
||||||
|
|
||||||
|
@ -24,7 +39,7 @@ def get_credentials(
|
||||||
# will be used to attempt to log into the victim.
|
# will be used to attempt to log into the victim.
|
||||||
def _get_empty_credentials(is_windows: bool) -> List[Credentials]:
|
def _get_empty_credentials(is_windows: bool) -> List[Credentials]:
|
||||||
if is_windows:
|
if is_windows:
|
||||||
return [Credentials(username=None, secret=None)]
|
return [Credentials(username=None, secret=None, secret_type=SecretType.CACHED)]
|
||||||
|
|
||||||
return []
|
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
|
# On Windows systems, when password == None, the current user's password will bu used to attempt to
|
||||||
# log into the victim.
|
# log into the victim.
|
||||||
def _get_username_only_credentials(usernames: List[str], is_windows: bool) -> List[Credentials]:
|
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:
|
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
|
return credentials
|
||||||
|
|
||||||
|
@ -43,6 +66,27 @@ def _get_username_only_credentials(usernames: List[str], is_windows: bool) -> Li
|
||||||
def _get_username_password_credentials(
|
def _get_username_password_credentials(
|
||||||
usernames: List[str], passwords: List[str]
|
usernames: List[str], passwords: List[str]
|
||||||
) -> List[Credentials]:
|
) -> 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
|
||||||
|
]
|
||||||
|
|
|
@ -6,12 +6,12 @@ from infection_monkey.exploit.powershell_utils.auth_options import (
|
||||||
ENCRYPTION_NEVER,
|
ENCRYPTION_NEVER,
|
||||||
get_auth_options,
|
get_auth_options,
|
||||||
)
|
)
|
||||||
from infection_monkey.exploit.powershell_utils.credentials import Credentials
|
from infection_monkey.exploit.powershell_utils.credentials import Credentials, SecretType
|
||||||
|
|
||||||
CREDENTIALS = [
|
CREDENTIALS = [
|
||||||
Credentials("user1", "password1"),
|
Credentials("user1", "password1", SecretType.PASSWORD),
|
||||||
Credentials("user2", ""),
|
Credentials("user2", "", SecretType.PASSWORD),
|
||||||
Credentials("user3", None),
|
Credentials("user3", None, SecretType.CACHED),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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_USERNAMES = ["user1", "user2"]
|
||||||
TEST_PASSWORDS = ["p1", "p2"]
|
TEST_PASSWORDS = ["p1", "p2"]
|
||||||
|
TEST_LM_HASHES = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"]
|
||||||
|
TEST_NT_HASHES = ["cccccccccccccccccccccccccccccccc", "dddddddddddddddddddddddddddddddd"]
|
||||||
|
|
||||||
|
|
||||||
def test_get_credentials__empty_windows_true():
|
def test_get_credentials__empty_windows_true():
|
||||||
credentials = get_credentials([], [], True)
|
credentials = get_credentials([], [], [], [], True)
|
||||||
|
|
||||||
assert len(credentials) == 1
|
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():
|
def test_get_credentials__empty_windows_false():
|
||||||
credentials = get_credentials([], [], False)
|
credentials = get_credentials([], [], [], [], False)
|
||||||
|
|
||||||
assert len(credentials) == 0
|
assert len(credentials) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_get_credentials__username_only_windows_true():
|
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 len(credentials) == 5
|
||||||
assert Credentials(username=TEST_USERNAMES[0], secret="") in credentials
|
assert (
|
||||||
assert Credentials(username=TEST_USERNAMES[1], secret="") in credentials
|
Credentials(username=TEST_USERNAMES[0], secret="", secret_type=SecretType.PASSWORD)
|
||||||
assert Credentials(username=TEST_USERNAMES[0], secret=None) in credentials
|
in credentials
|
||||||
assert Credentials(username=TEST_USERNAMES[1], secret=None) 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():
|
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 len(credentials) == 2
|
||||||
assert Credentials(username=TEST_USERNAMES[0], secret="") in credentials
|
assert (
|
||||||
assert Credentials(username=TEST_USERNAMES[1], secret="") in credentials
|
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():
|
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
|
assert len(credentials) == 9
|
||||||
for user in TEST_USERNAMES:
|
for user in TEST_USERNAMES:
|
||||||
for password in TEST_PASSWORDS:
|
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
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue