diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials.py new file mode 100644 index 000000000..fa772d1fd --- /dev/null +++ b/monkey/monkey_island/cc/services/telemetry/processing/credentials.py @@ -0,0 +1,7 @@ +from monkey_island.cc.services.telemetry.processing.credentials.credentials_parser import ( + parse_credentials, +) + + +def process_credentials_telemetry(telemetry: dict): + parse_credentials(telemetry) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/system_info_collectors/__init__.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/__init__.py similarity index 100% rename from monkey/monkey_island/cc/services/telemetry/processing/system_info_collectors/__init__.py rename to monkey/monkey_island/cc/services/telemetry/processing/credentials/__init__.py diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials/credentials_parser.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/credentials_parser.py new file mode 100644 index 000000000..af022b678 --- /dev/null +++ b/monkey/monkey_island/cc/services/telemetry/processing/credentials/credentials_parser.py @@ -0,0 +1,39 @@ +import logging + +from infection_monkey.i_puppet import CredentialType + +from .identities.username_processor import process_username +from .secrets.lm_hash_processor import process_lm_hash +from .secrets.nt_hash_processor import process_nt_hash +from .secrets.password_processor import process_password +from .secrets.ssh_key_processor import process_ssh_key + +logger = logging.getLogger(__name__) + +SECRET_PROCESSORS = { + CredentialType.PASSWORD: process_password, + CredentialType.NT_HASH: process_nt_hash, + CredentialType.LM_HASH: process_lm_hash, + CredentialType.SSH_KEYPAIR: process_ssh_key, +} + +IDENTITY_PROCESSORS = { + CredentialType.USERNAME: process_username, +} + + +def parse_credentials(credentials: dict): + for credential in credentials["credentials"]: + if is_ssh_keypair(credentials): + IDENTITY_PROCESSORS[CredentialType.SSH_KEYPAIR](credential, credentials["monkey_guid"]) + else: + for identity in credential["identities"]: + IDENTITY_PROCESSORS[identity["type"]](identity) + for secret in credential["secrets"]: + SECRET_PROCESSORS[secret["type"]](secret) + + +def is_ssh_keypair(credentials: dict) -> bool: + return bool( + filter(credentials["secrets"], lambda secret: secret["type"] == CredentialType.SSH_KEYPAIR) + ) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials/identities/__init__.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/identities/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials/identities/username_processor.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/identities/username_processor.py new file mode 100644 index 000000000..c13af4d67 --- /dev/null +++ b/monkey/monkey_island/cc/services/telemetry/processing/credentials/identities/username_processor.py @@ -0,0 +1,2 @@ +def process_username(): + pass diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/__init__.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/lm_hash_processor.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/lm_hash_processor.py new file mode 100644 index 000000000..4cc4c28e3 --- /dev/null +++ b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/lm_hash_processor.py @@ -0,0 +1,5 @@ +from monkey_island.cc.services.config import ConfigService + + +def process_lm_hash(lm_hash: dict): + ConfigService.creds_add_ntlm_hash(lm_hash["lm_hash"]) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/nt_hash_processor.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/nt_hash_processor.py new file mode 100644 index 000000000..e29e2eef0 --- /dev/null +++ b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/nt_hash_processor.py @@ -0,0 +1,5 @@ +from monkey_island.cc.services.config import ConfigService + + +def process_nt_hash(nt_hash: dict): + ConfigService.creds_add_ntlm_hash(nt_hash["nt_hash"]) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/password_processor.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/password_processor.py new file mode 100644 index 000000000..6d3331db6 --- /dev/null +++ b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/password_processor.py @@ -0,0 +1,5 @@ +from monkey_island.cc.services.config import ConfigService + + +def process_password(password: dict): + ConfigService.creds_add_password(password["password"]) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/ssh_key_processor.py b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/ssh_key_processor.py new file mode 100644 index 000000000..df0557115 --- /dev/null +++ b/monkey/monkey_island/cc/services/telemetry/processing/credentials/secrets/ssh_key_processor.py @@ -0,0 +1,40 @@ +from common.common_consts.credentials_type import CredentialsType +from monkey_island.cc.models import Monkey +from monkey_island.cc.server_utils.encryption import get_datastore_encryptor +from monkey_island.cc.services.config import ConfigService + + +class SSHKeyProcessingError(ValueError): + def __init__(self, msg=""): + self.msg = f"Error while processing ssh keypair: {msg}" + super().__init__(self.msg) + + +def process_ssh_key(credentials: dict, monkey_guid: str): + if len(credentials["identities"]) != 1: + raise SSHKeyProcessingError( + f'SSH credentials have {len(credentials["identities"])}' f" users associated with it!" + ) + + for ssh_key in credentials["secrets"]: + if not ssh_key["type"] == CredentialsType.SSH_KEYPAIR: + raise SSHKeyProcessingError("SSH credentials contain secrets that are not keypairs") + + if not ssh_key["public_key"] or not ssh_key["private_key"]: + raise SSHKeyProcessingError("Private or public key missing!") + + # TODO SSH key should be associated with IP that monkey exploited + ip = Monkey.get_single_monkey_by_guid(monkey_guid).ip_addresses[0] + username = credentials["identities"][0]["username"] + + ConfigService.ssh_add_keys( + user=username, + public_key=ssh_key["public_key"], + private_key=ssh_key["private_key"], + ip=ip, + ) + + +def encrypt_system_info_ssh_keys(ssh_key: dict): + for field in ["public_key", "private_key"]: + ssh_key[field] = get_datastore_encryptor().encrypt(ssh_key[field])