Merge pull request #2301 from guardicore/2180-credentials-event-encoding

2180 credentials event encoding
This commit is contained in:
Mike Salvatore 2022-09-16 08:35:45 -04:00 committed by GitHub
commit ae073de766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 62 additions and 23 deletions

View File

@ -3,5 +3,6 @@ from .nt_hash import NTHash
from .password import Password
from .ssh_keypair import SSHKeypair
from .username import Username
from .encoding import get_plaintext, SecretEncodingConfig
from .credentials import Credentials

View File

@ -2,22 +2,14 @@ from __future__ import annotations
from typing import Optional, Union
from pydantic import SecretBytes, SecretStr
from ..base_models import InfectionMonkeyBaseModel, InfectionMonkeyModelConfig
from . import LMHash, NTHash, Password, SSHKeypair, Username
from .encoding import SecretEncodingConfig
Secret = Union[Password, LMHash, NTHash, SSHKeypair]
Identity = Username
def get_plaintext(secret: Union[SecretStr, SecretBytes, None, str]) -> Optional[str]:
if isinstance(secret, (SecretStr, SecretBytes)):
return secret.get_secret_value()
else:
return secret
class Credentials(InfectionMonkeyBaseModel):
"""Represents a credential pair (an identity and a secret)"""
@ -27,9 +19,5 @@ class Credentials(InfectionMonkeyBaseModel):
secret: Optional[Secret]
"""Secret part of credentials, like a password or a hash"""
class Config(InfectionMonkeyModelConfig):
json_encoders = {
# This makes secrets dumpable to json, but not loggable
SecretStr: get_plaintext,
SecretBytes: get_plaintext,
}
class Config(SecretEncodingConfig, InfectionMonkeyModelConfig):
pass

View File

@ -0,0 +1,20 @@
from __future__ import annotations
from typing import Optional, Union
from pydantic import SecretBytes, SecretStr
def get_plaintext(secret: Union[SecretStr, SecretBytes, None, str]) -> Optional[str]:
if isinstance(secret, (SecretStr, SecretBytes)):
return secret.get_secret_value()
else:
return secret
class SecretEncodingConfig:
json_encoders = {
# This makes secrets dumpable to json, but not loggable
SecretStr: get_plaintext,
SecretBytes: get_plaintext,
}

View File

@ -2,8 +2,10 @@ from typing import Sequence
from pydantic import Field
from common.base_models import InfectionMonkeyModelConfig
from common.credentials import Credentials
from ..credentials.encoding import SecretEncodingConfig
from . import AbstractAgentEvent
@ -16,3 +18,6 @@ class CredentialsStolenEvent(AbstractAgentEvent):
"""
stolen_credentials: Sequence[Credentials] = Field(default_factory=list)
class Config(SecretEncodingConfig, InfectionMonkeyModelConfig):
pass

View File

@ -6,7 +6,7 @@ from typing import Sequence, Tuple
import pymssql
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT
from common.credentials.credentials import get_plaintext
from common.credentials import get_plaintext
from common.utils.exceptions import FailedExploitationError
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_agent_dst_path

View File

@ -11,7 +11,7 @@ from pypsrp.powershell import PowerShell, RunspacePool
from typing_extensions import Protocol
from urllib3 import connectionpool
from common.credentials.credentials import get_plaintext
from common.credentials import get_plaintext
from infection_monkey.exploit.powershell_utils.auth_options import AuthOptions
from infection_monkey.exploit.powershell_utils.credentials import Credentials, SecretType

View File

@ -4,7 +4,7 @@ from impacket.dcerpc.v5 import scmr, transport
from impacket.dcerpc.v5.scmr import DCERPCSessionError
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT
from common.credentials.credentials import get_plaintext
from common.credentials import get_plaintext
from common.utils.attack_utils import ScanStatus, UsageEnum
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_agent_dst_path

View File

@ -6,7 +6,7 @@ import paramiko
from common import OperatingSystem
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT, MEDIUM_REQUEST_TIMEOUT
from common.credentials.credentials import get_plaintext
from common.credentials import get_plaintext
from common.utils import Timer
from common.utils.attack_utils import ScanStatus
from common.utils.exceptions import FailedExploitationError

View File

@ -10,7 +10,7 @@ from impacket.smb3structs import SMB2_DIALECT_002, SMB2_DIALECT_21
from impacket.smbconnection import SMB_DIALECT, SMBConnection
from pydantic import SecretStr
from common.credentials.credentials import get_plaintext
from common.credentials import get_plaintext
from common.utils.attack_utils import ScanStatus
from infection_monkey.network.tools import get_interface_to_target
from infection_monkey.telemetry.attack.t1105_telem import T1105Telem

View File

@ -5,7 +5,7 @@ import traceback
from impacket.dcerpc.v5.rpcrt import DCERPCException
from common.credentials.credentials import get_plaintext
from common.credentials import get_plaintext
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.helpers import get_agent_dst_path
from infection_monkey.exploit.tools.smb_tools import SmbTools

View File

@ -16,8 +16,7 @@ from tests.data_for_tests.propagation_credentials import (
)
from common.base_models import InfectionMonkeyBaseModel
from common.credentials import Credentials
from common.credentials.credentials import get_plaintext
from common.credentials import Credentials, get_plaintext
@pytest.mark.parametrize(

View File

@ -0,0 +1,26 @@
from tests.data_for_tests.propagation_credentials import (
CREDENTIALS,
PLAINTEXT_LM_HASH,
PLAINTEXT_NT_HASH,
PLAINTEXT_PASSWORD,
PLAINTEXT_PRIVATE_KEY,
)
from tests.unit_tests.monkey_island.cc.models.test_agent import AGENT_ID
from common.events import CredentialsStolenEvent
TEST_EVENT = CredentialsStolenEvent(stolen_credentials=CREDENTIALS, source=AGENT_ID)
def test_credentials_stolen_event_serialization_json():
serialized_event = TEST_EVENT.json()
assert PLAINTEXT_PASSWORD in serialized_event
assert PLAINTEXT_LM_HASH in serialized_event
assert PLAINTEXT_NT_HASH in serialized_event
assert PLAINTEXT_PRIVATE_KEY in serialized_event
def test_credential_stolen_event_deserialization_json():
serialized_event = TEST_EVENT.json()
deserialized_event = CredentialsStolenEvent.parse_raw(serialized_event)
assert deserialized_event == TEST_EVENT