Agent: Format NT/LM hashes for use with pypsrp in PowerShellClient

This commit is contained in:
Mike Salvatore 2021-09-02 13:21:05 -04:00
parent 9cc488d36a
commit 1a1a130716
2 changed files with 71 additions and 3 deletions

View File

@ -1,6 +1,6 @@
import abc import abc
import logging import logging
from typing import Union from typing import Optional, Union
import pypsrp import pypsrp
import spnego import spnego
@ -12,7 +12,7 @@ from urllib3 import connectionpool
from infection_monkey.exploit.consts import WIN_ARCH_32, WIN_ARCH_64 from infection_monkey.exploit.consts import WIN_ARCH_32, WIN_ARCH_64
from infection_monkey.exploit.powershell_utils.auth_options import AuthOptions from infection_monkey.exploit.powershell_utils.auth_options import AuthOptions
from infection_monkey.exploit.powershell_utils.credentials import Credentials from infection_monkey.exploit.powershell_utils.credentials import Credentials, SecretType
from infection_monkey.model import GET_ARCH_WINDOWS from infection_monkey.model import GET_ARCH_WINDOWS
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -27,6 +27,22 @@ def _set_sensitive_packages_log_level_to_error():
logging.getLogger(package.__name__).setLevel(logging.ERROR) logging.getLogger(package.__name__).setLevel(logging.ERROR)
def format_password(credentials: Credentials) -> Optional[str]:
if credentials.secret_type == SecretType.CACHED:
return None
if credentials.secret_type == SecretType.PASSWORD:
return credentials.secret
if credentials.secret_type == SecretType.LM_HASH:
return f"{credentials.secret}:00000000000000000000000000000000"
if credentials.secret_type == SecretType.NT_HASH:
return f"00000000000000000000000000000000:{credentials.secret}"
raise ValueError(f"Unknown secret type {credentials.secret_type}")
class IPowerShellClient(Protocol, metaclass=abc.ABCMeta): class IPowerShellClient(Protocol, metaclass=abc.ABCMeta):
@abc.abstractmethod @abc.abstractmethod
def execute_cmd(self, cmd: str) -> str: def execute_cmd(self, cmd: str) -> str:
@ -53,7 +69,7 @@ class PowerShellClient(IPowerShellClient):
self._client = Client( self._client = Client(
ip_addr, ip_addr,
username=credentials.username, username=credentials.username,
password=credentials.secret, password=format_password(credentials),
cert_validation=False, cert_validation=False,
auth=auth_options.auth_type, auth=auth_options.auth_type,
encryption=auth_options.encryption, encryption=auth_options.encryption,

View File

@ -0,0 +1,52 @@
import pytest
from infection_monkey.exploit.powershell_utils.credentials import Credentials, SecretType
from infection_monkey.exploit.powershell_utils.powershell_client import format_password
def test_format_cached_credentials():
expected = None
creds = Credentials("test_user", expected, SecretType.CACHED)
actual = format_password(creds)
assert expected == actual
def test_format_password():
expected = "test_password"
creds = Credentials("test_user", expected, SecretType.PASSWORD)
actual = format_password(creds)
assert expected == actual
def test_format_lm_hash():
lm_hash = "c080132b6f2a0c4e5d1029cc06f48a92"
expected = f"{lm_hash}:00000000000000000000000000000000"
creds = Credentials("test_user", lm_hash, SecretType.LM_HASH)
actual = format_password(creds)
assert expected == actual
def test_format_nt_hash():
nt_hash = "c080132b6f2a0c4e5d1029cc06f48a92"
expected = f"00000000000000000000000000000000:{nt_hash}"
creds = Credentials("test_user", nt_hash, SecretType.NT_HASH)
actual = format_password(creds)
assert expected == actual
def test_invalid_secret_type():
creds = Credentials("test_user", "secret", "Bogus_Secret")
with pytest.raises(ValueError):
format_password(creds)