diff --git a/monkey/infection_monkey/credential_collectors/credentials.py b/monkey/infection_monkey/credential_collectors/credentials.py index dc7d9a375..1e3d05844 100644 --- a/monkey/infection_monkey/credential_collectors/credentials.py +++ b/monkey/infection_monkey/credential_collectors/credentials.py @@ -1,10 +1,11 @@ -from dataclasses import dataclass -from typing import List +from typing import Iterable from .credential_components.i_credential_component import ICredentialComponent -@dataclass class Credentials: - identities: List[ICredentialComponent] - secrets: List[ICredentialComponent] + def __init__( + self, identities: Iterable[ICredentialComponent], secrets: Iterable[ICredentialComponent] + ): + self.identities = tuple(identities) + self.secrets = tuple(secrets) diff --git a/monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_cred_collector.py b/monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_cred_collector.py index 75a84c0bb..9463b3d4f 100644 --- a/monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_cred_collector.py +++ b/monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_cred_collector.py @@ -8,7 +8,6 @@ from infection_monkey.credential_collectors import ( Password, Username, ) - from . import pypykatz_handler from .windows_credentials import WindowsCredentials @@ -22,24 +21,24 @@ class MimikatzCredentialCollector(ICredentialCollector): def _to_credentials(win_creds: List[WindowsCredentials]) -> [Credentials]: all_creds = [] for win_cred in win_creds: - creds_obj = Credentials(identities=[], secrets=[]) + identities = [] + secrets = [] if win_cred.username: identity = Username(win_cred.username) - creds_obj.identities.append(identity) + identities.append(identity) if win_cred.password: password = Password(win_cred.password) - creds_obj.secrets.append(password) + secrets.append(password) if win_cred.lm_hash: lm_hash = LMHash(lm_hash=win_cred.lm_hash) - creds_obj.secrets.append(lm_hash) + secrets.append(lm_hash) if win_cred.ntlm_hash: lm_hash = NTHash(nt_hash=win_cred.ntlm_hash) - creds_obj.secrets.append(lm_hash) - - if creds_obj.identities != [] or creds_obj.secrets != []: - all_creds.append(creds_obj) + secrets.append(lm_hash) + if identities != [] or secrets != []: + all_creds.append(Credentials(identities, secrets)) return all_creds diff --git a/monkey/tests/unit_tests/infection_monkey/credential_collectors/mimikatz_collector/test_mimikatz_collector.py b/monkey/tests/unit_tests/infection_monkey/credential_collectors/mimikatz_collector/test_mimikatz_collector.py index 0bf0c3628..9e45fd4c6 100644 --- a/monkey/tests/unit_tests/infection_monkey/credential_collectors/mimikatz_collector/test_mimikatz_collector.py +++ b/monkey/tests/unit_tests/infection_monkey/credential_collectors/mimikatz_collector/test_mimikatz_collector.py @@ -1,4 +1,4 @@ -from infection_monkey.credential_collectors import Credentials, LMHash, NTHash, Password, Username +from infection_monkey.credential_collectors import LMHash, NTHash, Password, Username from infection_monkey.credential_collectors.mimikatz_collector.mimikatz_cred_collector import ( MimikatzCredentialCollector, ) @@ -28,27 +28,57 @@ def test_empty_results(monkeypatch): def test_pypykatz_result_parsing(monkeypatch): + win_creds = [WindowsCredentials(username="user", password="secret", ntlm_hash="", lm_hash="")] + patch_pypykatz(win_creds, monkeypatch) + + # Expected credentials + username = Username("user") + password = Password("secret") + + collected = MimikatzCredentialCollector().collect_credentials() + assert len(list(collected)) == 1 + assert list(collected)[0].identities[0].__dict__ == username.__dict__ + assert list(collected)[0].secrets[0].__dict__ == password.__dict__ + + +def test_pypykatz_result_parsing_duplicates(monkeypatch): win_creds = [ WindowsCredentials(username="user", password="secret", ntlm_hash="", lm_hash=""), - WindowsCredentials(username="", password="", ntlm_hash="ntlm_hash", lm_hash="lm_hash"), WindowsCredentials(username="user", password="secret", ntlm_hash="", lm_hash=""), + ] + patch_pypykatz(win_creds, monkeypatch) + + collected = MimikatzCredentialCollector().collect_credentials() + assert len(list(collected)) == 2 + + +def test_pypykatz_result_parsing_defaults(monkeypatch): + win_creds = [ WindowsCredentials(username="user2", password="secret2", lm_hash="lm_hash"), ] patch_pypykatz(win_creds, monkeypatch) # Expected credentials - username = Username("user") - username2 = Username("user2") - password = Password("secret") - password2 = Password("secret2") - nt_hash = NTHash(nt_hash="ntlm_hash") - lm_hash = LMHash(lm_hash="lm_hash") + username = Username("user2") + password = Password("secret2") + lm_hash = LMHash("lm_hash") - expected = [ - Credentials(identities=[username], secrets=[password]), - Credentials(identities=[], secrets=[lm_hash, nt_hash]), - Credentials(identities=[username], secrets=[password]), - Credentials(identities=[username2], secrets=[password2, lm_hash]), - ] collected = MimikatzCredentialCollector().collect_credentials() - assert expected == collected + assert list(collected)[0].identities[0].__dict__ == username.__dict__ + assert list(collected)[0].secrets[0].__dict__ == password.__dict__ + assert list(collected)[0].secrets[1].__dict__ == lm_hash.__dict__ + + +def test_pypykatz_result_parsing_no_identities(monkeypatch): + win_creds = [ + WindowsCredentials(username="", password="", ntlm_hash="ntlm_hash", lm_hash="lm_hash"), + ] + patch_pypykatz(win_creds, monkeypatch) + + # Expected credentials + nt_hash = NTHash("ntlm_hash") + lm_hash = LMHash("lm_hash") + + collected = MimikatzCredentialCollector().collect_credentials() + assert list(collected)[0].secrets[0].__dict__ == lm_hash.__dict__ + assert list(collected)[0].secrets[1].__dict__ == nt_hash.__dict__