diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index 6bfabb1e2..c20580989 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -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( diff --git a/monkey/infection_monkey/exploit/powershell_utils/credentials.py b/monkey/infection_monkey/exploit/powershell_utils/credentials.py index ab3c7f542..982f9da29 100644 --- a/monkey/infection_monkey/exploit/powershell_utils/credentials.py +++ b/monkey/infection_monkey/exploit/powershell_utils/credentials.py @@ -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 + ] diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_auth_options.py b/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_auth_options.py index 0a917adac..d19fffbd0 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_auth_options.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_auth_options.py @@ -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), ] diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_credentials.py b/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_credentials.py index 64a13a5e5..0954d9dc8 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_credentials.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_credentials.py @@ -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 + )