forked from p15670423/monkey
Merge pull request #2301 from guardicore/2180-credentials-event-encoding
2180 credentials event encoding
This commit is contained in:
commit
ae073de766
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue