Agent: change the interface of Credentials
Refactor from dataclass to object with tuples. This enforces read only identities and secrets so users don't modify them
This commit is contained in:
parent
8868fb9b0c
commit
ac376a0014
|
@ -1,10 +1,11 @@
|
||||||
from dataclasses import dataclass
|
from typing import Iterable
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from .credential_components.i_credential_component import ICredentialComponent
|
from .credential_components.i_credential_component import ICredentialComponent
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Credentials:
|
class Credentials:
|
||||||
identities: List[ICredentialComponent]
|
def __init__(
|
||||||
secrets: List[ICredentialComponent]
|
self, identities: Iterable[ICredentialComponent], secrets: Iterable[ICredentialComponent]
|
||||||
|
):
|
||||||
|
self.identities = tuple(identities)
|
||||||
|
self.secrets = tuple(secrets)
|
||||||
|
|
|
@ -8,7 +8,6 @@ from infection_monkey.credential_collectors import (
|
||||||
Password,
|
Password,
|
||||||
Username,
|
Username,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import pypykatz_handler
|
from . import pypykatz_handler
|
||||||
from .windows_credentials import WindowsCredentials
|
from .windows_credentials import WindowsCredentials
|
||||||
|
|
||||||
|
@ -22,24 +21,24 @@ class MimikatzCredentialCollector(ICredentialCollector):
|
||||||
def _to_credentials(win_creds: List[WindowsCredentials]) -> [Credentials]:
|
def _to_credentials(win_creds: List[WindowsCredentials]) -> [Credentials]:
|
||||||
all_creds = []
|
all_creds = []
|
||||||
for win_cred in win_creds:
|
for win_cred in win_creds:
|
||||||
creds_obj = Credentials(identities=[], secrets=[])
|
identities = []
|
||||||
|
secrets = []
|
||||||
if win_cred.username:
|
if win_cred.username:
|
||||||
identity = Username(win_cred.username)
|
identity = Username(win_cred.username)
|
||||||
creds_obj.identities.append(identity)
|
identities.append(identity)
|
||||||
|
|
||||||
if win_cred.password:
|
if win_cred.password:
|
||||||
password = Password(win_cred.password)
|
password = Password(win_cred.password)
|
||||||
creds_obj.secrets.append(password)
|
secrets.append(password)
|
||||||
|
|
||||||
if win_cred.lm_hash:
|
if win_cred.lm_hash:
|
||||||
lm_hash = LMHash(lm_hash=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:
|
if win_cred.ntlm_hash:
|
||||||
lm_hash = NTHash(nt_hash=win_cred.ntlm_hash)
|
lm_hash = NTHash(nt_hash=win_cred.ntlm_hash)
|
||||||
creds_obj.secrets.append(lm_hash)
|
secrets.append(lm_hash)
|
||||||
|
|
||||||
if creds_obj.identities != [] or creds_obj.secrets != []:
|
|
||||||
all_creds.append(creds_obj)
|
|
||||||
|
|
||||||
|
if identities != [] or secrets != []:
|
||||||
|
all_creds.append(Credentials(identities, secrets))
|
||||||
return all_creds
|
return all_creds
|
||||||
|
|
|
@ -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 (
|
from infection_monkey.credential_collectors.mimikatz_collector.mimikatz_cred_collector import (
|
||||||
MimikatzCredentialCollector,
|
MimikatzCredentialCollector,
|
||||||
)
|
)
|
||||||
|
@ -28,27 +28,57 @@ def test_empty_results(monkeypatch):
|
||||||
|
|
||||||
|
|
||||||
def test_pypykatz_result_parsing(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 = [
|
win_creds = [
|
||||||
WindowsCredentials(username="user", password="secret", ntlm_hash="", lm_hash=""),
|
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=""),
|
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"),
|
WindowsCredentials(username="user2", password="secret2", lm_hash="lm_hash"),
|
||||||
]
|
]
|
||||||
patch_pypykatz(win_creds, monkeypatch)
|
patch_pypykatz(win_creds, monkeypatch)
|
||||||
|
|
||||||
# Expected credentials
|
# Expected credentials
|
||||||
username = Username("user")
|
username = Username("user2")
|
||||||
username2 = Username("user2")
|
password = Password("secret2")
|
||||||
password = Password("secret")
|
lm_hash = LMHash("lm_hash")
|
||||||
password2 = Password("secret2")
|
|
||||||
nt_hash = NTHash(nt_hash="ntlm_hash")
|
|
||||||
lm_hash = LMHash(lm_hash="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()
|
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__
|
||||||
|
|
Loading…
Reference in New Issue