From a09f2861691cc559d6c6b956646c7cac8a6c33f5 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 11 Feb 2021 13:48:22 -0500 Subject: [PATCH 1/9] cc: add `data_dir` property to EnvironmentConfig --- monkey/monkey_island/cc/consts.py | 2 ++ .../cc/environment/environment_config.py | 25 +++++++++++++------ .../cc/environment/environment_singleton.py | 3 +++ .../cc/environment/test_environment_config.py | 23 ++++++++++++----- .../environment/server_config_data_dir.json | 7 ++++++ 5 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 monkey/monkey_island/cc/testing/environment/server_config_data_dir.json diff --git a/monkey/monkey_island/cc/consts.py b/monkey/monkey_island/cc/consts.py index c12a42731b9..5a0e6958192 100644 --- a/monkey/monkey_island/cc/consts.py +++ b/monkey/monkey_island/cc/consts.py @@ -16,3 +16,5 @@ DEFAULT_LOGGER_CONFIG_PATH = os.path.join( MONKEY_ISLAND_ABS_PATH, "cc", "island_logger_default_config.json" ) + +DEFAULT_DATA_DIR = os.path.join(MONKEY_ISLAND_ABS_PATH, "cc") diff --git a/monkey/monkey_island/cc/environment/environment_config.py b/monkey/monkey_island/cc/environment/environment_config.py index aec1a777f83..e0ce248508e 100644 --- a/monkey/monkey_island/cc/environment/environment_config.py +++ b/monkey/monkey_island/cc/environment/environment_config.py @@ -6,6 +6,7 @@ from typing import Dict, List import monkey_island.cc.environment.server_config_generator as server_config_generator +from monkey_island.cc.consts import DEFAULT_DATA_DIR from monkey_island.cc.environment.user_creds import UserCreds from monkey_island.cc.resources.auth.auth_user import User from monkey_island.cc.resources.auth.user_store import UserStore @@ -18,6 +19,7 @@ def __init__(self, file_path): self.deployment = None self.user_creds = None self.aws = None + self.data_dir = None self._load_from_file(self._server_config_path) @@ -26,7 +28,7 @@ def _load_from_file(self, file_path): if not Path(file_path).is_file(): server_config_generator.create_default_config_file(file_path) - with open(file_path, 'r') as f: + with open(file_path, "r") as f: config_content = f.read() self._load_from_json(config_content) @@ -37,22 +39,29 @@ def _load_from_json(self, config_json: str) -> EnvironmentConfig: def _load_from_dict(self, dict_data: Dict): user_creds = UserCreds.get_from_dict(dict_data) - aws = dict_data['aws'] if 'aws' in dict_data else None + aws = dict_data["aws"] if "aws" in dict_data else None + data_dir = ( + dict_data["data_dir"] if "data_dir" in dict_data else DEFAULT_DATA_DIR + ) - self.server_config = dict_data['server_config'] - self.deployment = dict_data['deployment'] + self.server_config = dict_data["server_config"] + self.deployment = dict_data["deployment"] self.user_creds = user_creds self.aws = aws + self.data_dir = data_dir def save_to_file(self): - with open(self._server_config_path, 'w') as f: + with open(self._server_config_path, "w") as f: f.write(json.dumps(self.to_dict(), indent=2)) def to_dict(self) -> Dict: - config_dict = {'server_config': self.server_config, - 'deployment': self.deployment} + config_dict = { + "server_config": self.server_config, + "deployment": self.deployment, + "data_dir": self.data_dir, + } if self.aws: - config_dict.update({'aws': self.aws}) + config_dict.update({"aws": self.aws}) config_dict.update(self.user_creds.to_dict()) return config_dict diff --git a/monkey/monkey_island/cc/environment/environment_singleton.py b/monkey/monkey_island/cc/environment/environment_singleton.py index a0dda44fbc7..ce68b84a5af 100644 --- a/monkey/monkey_island/cc/environment/environment_singleton.py +++ b/monkey/monkey_island/cc/environment/environment_singleton.py @@ -22,6 +22,7 @@ } env = None +config = None def set_env(env_type: str, env_config: EnvironmentConfig): @@ -41,6 +42,8 @@ def set_to_standard(): def initialize_from_file(file_path): + global config + try: config = EnvironmentConfig(file_path) diff --git a/monkey/monkey_island/cc/environment/test_environment_config.py b/monkey/monkey_island/cc/environment/test_environment_config.py index 477172adf66..986f958bfee 100644 --- a/monkey/monkey_island/cc/environment/test_environment_config.py +++ b/monkey/monkey_island/cc/environment/test_environment_config.py @@ -4,7 +4,7 @@ import pytest -from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH +from monkey_island.cc.consts import DEFAULT_DATA_DIR, MONKEY_ISLAND_ABS_PATH from monkey_island.cc.environment.environment_config import EnvironmentConfig from monkey_island.cc.environment.user_creds import UserCreds @@ -22,6 +22,7 @@ STANDARD_WITH_CREDENTIALS = os.path.join( TEST_RESOURCES_DIR, "server_config_standard_with_credentials.json" ) +DATA_DIR = os.path.join(TEST_RESOURCES_DIR, "server_config_data_dir.json") @pytest.fixture @@ -32,28 +33,31 @@ def config_file(tmpdir): def test_get_with_credentials(): config_dict = EnvironmentConfig(WITH_CREDENTIALS).to_dict() - assert len(config_dict.keys()) == 4 + assert len(config_dict.keys()) == 5 assert config_dict["server_config"] == "password" assert config_dict["deployment"] == "develop" assert config_dict["user"] == "test" assert config_dict["password_hash"] == "abcdef" + assert config_dict["data_dir"] == DEFAULT_DATA_DIR def test_get_with_no_credentials(): config_dict = EnvironmentConfig(NO_CREDENTIALS).to_dict() - assert len(config_dict.keys()) == 2 + assert len(config_dict.keys()) == 3 assert config_dict["server_config"] == "password" assert config_dict["deployment"] == "develop" + assert config_dict["data_dir"] == DEFAULT_DATA_DIR def test_get_with_partial_credentials(): config_dict = EnvironmentConfig(PARTIAL_CREDENTIALS).to_dict() - assert len(config_dict.keys()) == 3 + assert len(config_dict.keys()) == 4 assert config_dict["server_config"] == "password" assert config_dict["deployment"] == "develop" assert config_dict["user"] == "test" + assert config_dict["data_dir"] == DEFAULT_DATA_DIR def test_save_to_file(config_file): @@ -66,12 +70,13 @@ def test_save_to_file(config_file): with open(config_file, "r") as f: from_file = json.load(f) - assert len(from_file.keys()) == 5 + assert len(from_file.keys()) == 6 assert from_file["server_config"] == "standard" assert from_file["deployment"] == "develop" assert from_file["user"] == "test" assert from_file["password_hash"] == "abcdef" assert from_file["aws"] == "test_aws" + assert from_file["data_dir"] == DEFAULT_DATA_DIR def test_add_user(config_file): @@ -87,7 +92,7 @@ def test_add_user(config_file): with open(config_file, "r") as f: from_file = json.load(f) - assert len(from_file.keys()) == 4 + assert len(from_file.keys()) == 5 assert from_file["user"] == new_user assert from_file["password_hash"] == new_password_hash @@ -112,3 +117,9 @@ def test_generate_default_file(config_file): assert environment_config.user_creds.username == "" assert environment_config.user_creds.password_hash == "" assert environment_config.aws is None + assert environment_config.data_dir == DEFAULT_DATA_DIR + + +def test_data_dir(): + environment_config = EnvironmentConfig(DATA_DIR) + assert environment_config.data_dir == "/test/data/dir" diff --git a/monkey/monkey_island/cc/testing/environment/server_config_data_dir.json b/monkey/monkey_island/cc/testing/environment/server_config_data_dir.json new file mode 100644 index 00000000000..b9d6845f3ad --- /dev/null +++ b/monkey/monkey_island/cc/testing/environment/server_config_data_dir.json @@ -0,0 +1,7 @@ +{ + "server_config": "password", + "deployment": "develop", + "user": "test", + "password_hash": "abcdef", + "data_dir": "/test/data/dir" +} From bc141361a2e89a9f60c77d380571d06130b1bde4 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 11 Feb 2021 20:16:31 -0500 Subject: [PATCH 2/9] cc: allow encryptor to store key file in variable locations --- monkey/monkey_island/cc/encryptor.py | 38 +++++++++++-------- monkey/monkey_island/cc/main.py | 2 + .../technique_report_tools.py | 4 +- monkey/monkey_island/cc/services/config.py | 20 +++++----- .../services/telemetry/processing/exploit.py | 2 +- .../telemetry/processing/system_info.py | 2 +- monkey/monkey_island/cc/test_encryptor.py | 29 ++++++++++++++ monkey/monkey_island/cc/testing/mongo_key.bin | 2 + 8 files changed, 69 insertions(+), 30 deletions(-) create mode 100644 monkey/monkey_island/cc/test_encryptor.py create mode 100644 monkey/monkey_island/cc/testing/mongo_key.bin diff --git a/monkey/monkey_island/cc/encryptor.py b/monkey/monkey_island/cc/encryptor.py index cf1f02081c1..acb83814ffd 100644 --- a/monkey/monkey_island/cc/encryptor.py +++ b/monkey/monkey_island/cc/encryptor.py @@ -5,33 +5,32 @@ from Crypto import Random # noqa: DOU133 from Crypto.Cipher import AES # noqa: DOU133 -from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH - __author__ = "itay.mizeretz" +_encryptor = None + class Encryptor: _BLOCK_SIZE = 32 - _DB_PASSWORD_FILENAME = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc/mongo_key.bin') + _PASSWORD_FILENAME = "mongo_key.bin" - def __init__(self): - self._load_key() + def __init__(self, data_dir): + password_file = os.path.join(data_dir, self._PASSWORD_FILENAME) - def _init_key(self): + if os.path.exists(password_file): + self._load_existing_key(password_file) + else: + self._init_key(password_file) + + def _init_key(self, password_file): self._cipher_key = Random.new().read(self._BLOCK_SIZE) - with open(self._DB_PASSWORD_FILENAME, 'wb') as f: + with open(password_file, 'wb') as f: f.write(self._cipher_key) - def _load_existing_key(self): - with open(self._DB_PASSWORD_FILENAME, 'rb') as f: + def _load_existing_key(self, password_file): + with open(password_file, 'rb') as f: self._cipher_key = f.read() - def _load_key(self): - if os.path.exists(self._DB_PASSWORD_FILENAME): - self._load_existing_key() - else: - self._init_key() - def _pad(self, message): return message + (self._BLOCK_SIZE - (len(message) % self._BLOCK_SIZE)) * chr( self._BLOCK_SIZE - (len(message) % self._BLOCK_SIZE)) @@ -51,4 +50,11 @@ def dec(self, enc_message): return self._unpad(cipher.decrypt(enc_message[AES.block_size:]).decode()) -encryptor = Encryptor() +def initialize_encryptor(data_dir): + global _encryptor + + _encryptor = Encryptor(data_dir) + + +def encryptor(): + return _encryptor diff --git a/monkey/monkey_island/cc/main.py b/monkey/monkey_island/cc/main.py index 2a029218cb5..0af9066de5b 100644 --- a/monkey/monkey_island/cc/main.py +++ b/monkey/monkey_island/cc/main.py @@ -24,6 +24,7 @@ BootloaderHttpServer # noqa: E402 from monkey_island.cc.database import get_db_version # noqa: E402 from monkey_island.cc.database import is_db_server_up # noqa: E402 +from monkey_island.cc.encryptor import initialize_encryptor # noqa: E402 from monkey_island.cc.network_utils import local_ip_addresses # noqa: E402 from monkey_island.cc.resources.monkey_download import \ MonkeyDownload # noqa: E402 @@ -37,6 +38,7 @@ def main(should_setup_only=False, server_config_filename=DEFAULT_SERVER_CONFIG_PATH): logger.info("Starting bootloader server") env_singleton.initialize_from_file(server_config_filename) + initialize_encryptor(env_singleton.config.data_dir) mongo_url = os.environ.get('MONGO_URL', env_singleton.env.get_mongo_url()) bootloader_server_thread = Thread(target=BootloaderHttpServer(mongo_url).serve_forever, daemon=True) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index 80bfb952daa..0afe579b2d4 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -29,7 +29,7 @@ def censor_password(password, plain_chars=3, secret_chars=5): """ if not password: return "" - password = encryptor.dec(password) + password = encryptor().dec(password) return password[0:plain_chars] + '*' * secret_chars @@ -42,5 +42,5 @@ def censor_hash(hash_, plain_chars=5): """ if not hash_: return "" - hash_ = encryptor.dec(hash_) + hash_ = encryptor().dec(hash_) return hash_[0: plain_chars] + ' ...' diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index 10ce690c0ea..c83faf55ae3 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -66,7 +66,7 @@ def get_config_value(config_key_as_arr, is_initial_config=False, should_decrypt= config = config[config_key_part] if should_decrypt: if config_key_as_arr in ENCRYPTED_CONFIG_ARRAYS: - config = [encryptor.dec(x) for x in config] + config = [encryptor().dec(x) for x in config] return config @staticmethod @@ -103,7 +103,7 @@ def add_item_to_config_set_if_dont_exist(item_key, item_value, should_encrypt): if item_value in items_from_config: return if should_encrypt: - item_value = encryptor.enc(item_value) + item_value = encryptor().enc(item_value) mongo.db.config.update( {'name': 'newconfig'}, {'$addToSet': {item_key: item_value}}, @@ -288,9 +288,9 @@ def decrypt_flat_config(flat_config, is_island=False): if flat_config[key] and isinstance(flat_config[key][0], dict) and 'public_key' in flat_config[key][0]: flat_config[key] = [ConfigService.decrypt_ssh_key_pair(item) for item in flat_config[key]] else: - flat_config[key] = [encryptor.dec(item) for item in flat_config[key]] + flat_config[key] = [encryptor().dec(item) for item in flat_config[key]] else: - flat_config[key] = encryptor.dec(flat_config[key]) + flat_config[key] = encryptor().dec(flat_config[key]) return flat_config @staticmethod @@ -311,19 +311,19 @@ def _encrypt_or_decrypt_config(config, is_decrypt=False): config_arr[i] = ConfigService.decrypt_ssh_key_pair(config_arr[i]) if is_decrypt else \ ConfigService.decrypt_ssh_key_pair(config_arr[i], True) else: - config_arr[i] = encryptor.dec(config_arr[i]) if is_decrypt else encryptor.enc(config_arr[i]) + config_arr[i] = encryptor().dec(config_arr[i]) if is_decrypt else encryptor().enc(config_arr[i]) else: parent_config_arr[config_arr_as_array[-1]] = \ - encryptor.dec(config_arr) if is_decrypt else encryptor.enc(config_arr) + encryptor().dec(config_arr) if is_decrypt else encryptor().enc(config_arr) @staticmethod def decrypt_ssh_key_pair(pair, encrypt=False): if encrypt: - pair['public_key'] = encryptor.enc(pair['public_key']) - pair['private_key'] = encryptor.enc(pair['private_key']) + pair['public_key'] = encryptor().enc(pair['public_key']) + pair['private_key'] = encryptor().enc(pair['private_key']) else: - pair['public_key'] = encryptor.dec(pair['public_key']) - pair['private_key'] = encryptor.dec(pair['private_key']) + pair['public_key'] = encryptor().dec(pair['public_key']) + pair['private_key'] = encryptor().dec(pair['private_key']) return pair @staticmethod diff --git a/monkey/monkey_island/cc/services/telemetry/processing/exploit.py b/monkey/monkey_island/cc/services/telemetry/processing/exploit.py index e67b4182a37..eed13ffe3ea 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/exploit.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/exploit.py @@ -53,4 +53,4 @@ def encrypt_exploit_creds(telemetry_json): for field in ['password', 'lm_hash', 'ntlm_hash']: credential = attempts[i][field] if len(credential) > 0: - attempts[i][field] = encryptor.enc(credential) + attempts[i][field] = encryptor().enc(credential) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/system_info.py b/monkey/monkey_island/cc/services/telemetry/processing/system_info.py index 88eb9285cbe..5ebfdde0ee2 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/system_info.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/system_info.py @@ -63,7 +63,7 @@ def encrypt_system_info_ssh_keys(ssh_info): for idx, user in enumerate(ssh_info): for field in ['public_key', 'private_key', 'known_hosts']: if ssh_info[idx][field]: - ssh_info[idx][field] = encryptor.enc(ssh_info[idx][field]) + ssh_info[idx][field] = encryptor().enc(ssh_info[idx][field]) def process_credential_info(telemetry_json): diff --git a/monkey/monkey_island/cc/test_encryptor.py b/monkey/monkey_island/cc/test_encryptor.py new file mode 100644 index 00000000000..599eb63bef1 --- /dev/null +++ b/monkey/monkey_island/cc/test_encryptor.py @@ -0,0 +1,29 @@ +import os + +from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH +from monkey_island.cc.encryptor import initialize_encryptor, encryptor + + +TEST_DATA_DIR = os.path.join(MONKEY_ISLAND_ABS_PATH, "cc", "testing") +PASSWORD_FILENAME = "mongo_key.bin" + +PLAINTEXT = "Hello, Monkey!" +CYPHERTEXT = "vKgvD6SjRyIh1dh2AM/rnTa0NI/vjfwnbZLbMocWtE4e42WJmSUz2ordtbQrH1Fq" + + +def test_aes_cbc_encryption(): + initialize_encryptor(TEST_DATA_DIR) + + assert encryptor().enc(PLAINTEXT) != PLAINTEXT + + +def test_aes_cbc_decryption(): + initialize_encryptor(TEST_DATA_DIR) + + assert encryptor().dec(CYPHERTEXT) == PLAINTEXT + + +def test_create_new_password_file(tmpdir): + initialize_encryptor(tmpdir) + + assert os.path.isfile(os.path.join(tmpdir, PASSWORD_FILENAME)) diff --git a/monkey/monkey_island/cc/testing/mongo_key.bin b/monkey/monkey_island/cc/testing/mongo_key.bin new file mode 100644 index 00000000000..6b8091efb87 --- /dev/null +++ b/monkey/monkey_island/cc/testing/mongo_key.bin @@ -0,0 +1,2 @@ ++ RO +)ꝞT|RS&C \ No newline at end of file From c99349ff9d93b6b06cb4d21c5ab573b52d5eaa30 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 11 Feb 2021 20:17:22 -0500 Subject: [PATCH 3/9] cc: format encryptor.py with black --- monkey/monkey_island/cc/encryptor.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/monkey/monkey_island/cc/encryptor.py b/monkey/monkey_island/cc/encryptor.py index acb83814ffd..5ef89c35355 100644 --- a/monkey/monkey_island/cc/encryptor.py +++ b/monkey/monkey_island/cc/encryptor.py @@ -24,30 +24,33 @@ def __init__(self, data_dir): def _init_key(self, password_file): self._cipher_key = Random.new().read(self._BLOCK_SIZE) - with open(password_file, 'wb') as f: + with open(password_file, "wb") as f: f.write(self._cipher_key) def _load_existing_key(self, password_file): - with open(password_file, 'rb') as f: + with open(password_file, "rb") as f: self._cipher_key = f.read() def _pad(self, message): return message + (self._BLOCK_SIZE - (len(message) % self._BLOCK_SIZE)) * chr( - self._BLOCK_SIZE - (len(message) % self._BLOCK_SIZE)) + self._BLOCK_SIZE - (len(message) % self._BLOCK_SIZE) + ) def _unpad(self, message: str): - return message[0:-ord(message[len(message) - 1])] + return message[0 : -ord(message[len(message) - 1])] def enc(self, message: str): cipher_iv = Random.new().read(AES.block_size) cipher = AES.new(self._cipher_key, AES.MODE_CBC, cipher_iv) - return base64.b64encode(cipher_iv + cipher.encrypt(self._pad(message).encode())).decode() + return base64.b64encode( + cipher_iv + cipher.encrypt(self._pad(message).encode()) + ).decode() def dec(self, enc_message): enc_message = base64.b64decode(enc_message) - cipher_iv = enc_message[0:AES.block_size] + cipher_iv = enc_message[0 : AES.block_size] cipher = AES.new(self._cipher_key, AES.MODE_CBC, cipher_iv) - return self._unpad(cipher.decrypt(enc_message[AES.block_size:]).decode()) + return self._unpad(cipher.decrypt(enc_message[AES.block_size :]).decode()) def initialize_encryptor(data_dir): From d04e5f35e68066bd3e5e34413f51b5f2767a1bf0 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Tue, 16 Feb 2021 10:59:35 -0500 Subject: [PATCH 4/9] cc: expanduser in data_dir path in Encryptor --- monkey/monkey_island/cc/encryptor.py | 4 +++- monkey/monkey_island/cc/test_encryptor.py | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/encryptor.py b/monkey/monkey_island/cc/encryptor.py index 5ef89c35355..816c252e8be 100644 --- a/monkey/monkey_island/cc/encryptor.py +++ b/monkey/monkey_island/cc/encryptor.py @@ -15,7 +15,9 @@ class Encryptor: _PASSWORD_FILENAME = "mongo_key.bin" def __init__(self, data_dir): - password_file = os.path.join(data_dir, self._PASSWORD_FILENAME) + password_file = os.path.expanduser( + os.path.join(data_dir, self._PASSWORD_FILENAME) + ) if os.path.exists(password_file): self._load_existing_key(password_file) diff --git a/monkey/monkey_island/cc/test_encryptor.py b/monkey/monkey_island/cc/test_encryptor.py index 599eb63bef1..9e2c7ec0f5b 100644 --- a/monkey/monkey_island/cc/test_encryptor.py +++ b/monkey/monkey_island/cc/test_encryptor.py @@ -27,3 +27,11 @@ def test_create_new_password_file(tmpdir): initialize_encryptor(tmpdir) assert os.path.isfile(os.path.join(tmpdir, PASSWORD_FILENAME)) + + +def test_expand_home(monkeypatch, tmpdir): + monkeypatch.setenv("HOME", str(tmpdir)) + + initialize_encryptor("~/") + + assert os.path.isfile(os.path.join(tmpdir, "mongo_key.bin")) From 2d1b84c417d8f5282d1b69b6d5cd14c8ab2d5b1e Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 25 Feb 2021 06:36:20 -0500 Subject: [PATCH 5/9] cc: rename encryptor() -> get_encryptor() --- monkey/monkey_island/cc/encryptor.py | 2 +- .../technique_report_tools.py | 6 ++--- monkey/monkey_island/cc/services/config.py | 22 +++++++++---------- .../services/telemetry/processing/exploit.py | 4 ++-- .../telemetry/processing/system_info.py | 4 ++-- monkey/monkey_island/cc/test_encryptor.py | 6 ++--- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/monkey/monkey_island/cc/encryptor.py b/monkey/monkey_island/cc/encryptor.py index 816c252e8be..0cf440c5488 100644 --- a/monkey/monkey_island/cc/encryptor.py +++ b/monkey/monkey_island/cc/encryptor.py @@ -61,5 +61,5 @@ def initialize_encryptor(data_dir): _encryptor = Encryptor(data_dir) -def encryptor(): +def get_encryptor(): return _encryptor diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py index 0afe579b2d4..22236cd62e6 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/technique_report_tools.py @@ -1,4 +1,4 @@ -from monkey_island.cc.encryptor import encryptor +from monkey_island.cc.encryptor import get_encryptor def parse_creds(attempt): @@ -29,7 +29,7 @@ def censor_password(password, plain_chars=3, secret_chars=5): """ if not password: return "" - password = encryptor().dec(password) + password = get_encryptor().dec(password) return password[0:plain_chars] + '*' * secret_chars @@ -42,5 +42,5 @@ def censor_hash(hash_, plain_chars=5): """ if not hash_: return "" - hash_ = encryptor().dec(hash_) + hash_ = get_encryptor().dec(hash_) return hash_[0: plain_chars] + ' ...' diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index c83faf55ae3..e77d594873a 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -8,7 +8,7 @@ import monkey_island.cc.environment.environment_singleton as env_singleton import monkey_island.cc.services.post_breach_files from monkey_island.cc.database import mongo -from monkey_island.cc.encryptor import encryptor +from monkey_island.cc.encryptor import get_encryptor from monkey_island.cc.network_utils import local_ip_addresses from monkey_island.cc.services.config_schema.config_schema import SCHEMA @@ -66,7 +66,7 @@ def get_config_value(config_key_as_arr, is_initial_config=False, should_decrypt= config = config[config_key_part] if should_decrypt: if config_key_as_arr in ENCRYPTED_CONFIG_ARRAYS: - config = [encryptor().dec(x) for x in config] + config = [get_encryptor().dec(x) for x in config] return config @staticmethod @@ -103,7 +103,7 @@ def add_item_to_config_set_if_dont_exist(item_key, item_value, should_encrypt): if item_value in items_from_config: return if should_encrypt: - item_value = encryptor().enc(item_value) + item_value = get_encryptor().enc(item_value) mongo.db.config.update( {'name': 'newconfig'}, {'$addToSet': {item_key: item_value}}, @@ -288,9 +288,9 @@ def decrypt_flat_config(flat_config, is_island=False): if flat_config[key] and isinstance(flat_config[key][0], dict) and 'public_key' in flat_config[key][0]: flat_config[key] = [ConfigService.decrypt_ssh_key_pair(item) for item in flat_config[key]] else: - flat_config[key] = [encryptor().dec(item) for item in flat_config[key]] + flat_config[key] = [get_encryptor().dec(item) for item in flat_config[key]] else: - flat_config[key] = encryptor().dec(flat_config[key]) + flat_config[key] = get_encryptor().dec(flat_config[key]) return flat_config @staticmethod @@ -311,19 +311,19 @@ def _encrypt_or_decrypt_config(config, is_decrypt=False): config_arr[i] = ConfigService.decrypt_ssh_key_pair(config_arr[i]) if is_decrypt else \ ConfigService.decrypt_ssh_key_pair(config_arr[i], True) else: - config_arr[i] = encryptor().dec(config_arr[i]) if is_decrypt else encryptor().enc(config_arr[i]) + config_arr[i] = get_encryptor().dec(config_arr[i]) if is_decrypt else get_encryptor().enc(config_arr[i]) else: parent_config_arr[config_arr_as_array[-1]] = \ - encryptor().dec(config_arr) if is_decrypt else encryptor().enc(config_arr) + get_encryptor().dec(config_arr) if is_decrypt else get_encryptor().enc(config_arr) @staticmethod def decrypt_ssh_key_pair(pair, encrypt=False): if encrypt: - pair['public_key'] = encryptor().enc(pair['public_key']) - pair['private_key'] = encryptor().enc(pair['private_key']) + pair['public_key'] = get_encryptor().enc(pair['public_key']) + pair['private_key'] = get_encryptor().enc(pair['private_key']) else: - pair['public_key'] = encryptor().dec(pair['public_key']) - pair['private_key'] = encryptor().dec(pair['private_key']) + pair['public_key'] = get_encryptor().dec(pair['public_key']) + pair['private_key'] = get_encryptor().dec(pair['private_key']) return pair @staticmethod diff --git a/monkey/monkey_island/cc/services/telemetry/processing/exploit.py b/monkey/monkey_island/cc/services/telemetry/processing/exploit.py index eed13ffe3ea..03492ee966d 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/exploit.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/exploit.py @@ -2,7 +2,7 @@ import dateutil -from monkey_island.cc.encryptor import encryptor +from monkey_island.cc.encryptor import get_encryptor from monkey_island.cc.models import Monkey from monkey_island.cc.services.edge.displayed_edge import EdgeService from monkey_island.cc.services.node import NodeService @@ -53,4 +53,4 @@ def encrypt_exploit_creds(telemetry_json): for field in ['password', 'lm_hash', 'ntlm_hash']: credential = attempts[i][field] if len(credential) > 0: - attempts[i][field] = encryptor().enc(credential) + attempts[i][field] = get_encryptor().enc(credential) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/system_info.py b/monkey/monkey_island/cc/services/telemetry/processing/system_info.py index 5ebfdde0ee2..1c1a873e916 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/system_info.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/system_info.py @@ -1,6 +1,6 @@ import logging -from monkey_island.cc.encryptor import encryptor +from monkey_island.cc.encryptor import get_encryptor from monkey_island.cc.services.config import ConfigService from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.telemetry.processing.system_info_collectors.system_info_telemetry_dispatcher import \ @@ -63,7 +63,7 @@ def encrypt_system_info_ssh_keys(ssh_info): for idx, user in enumerate(ssh_info): for field in ['public_key', 'private_key', 'known_hosts']: if ssh_info[idx][field]: - ssh_info[idx][field] = encryptor().enc(ssh_info[idx][field]) + ssh_info[idx][field] = get_encryptor().enc(ssh_info[idx][field]) def process_credential_info(telemetry_json): diff --git a/monkey/monkey_island/cc/test_encryptor.py b/monkey/monkey_island/cc/test_encryptor.py index 9e2c7ec0f5b..ebb9be0a12a 100644 --- a/monkey/monkey_island/cc/test_encryptor.py +++ b/monkey/monkey_island/cc/test_encryptor.py @@ -1,7 +1,7 @@ import os from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH -from monkey_island.cc.encryptor import initialize_encryptor, encryptor +from monkey_island.cc.encryptor import initialize_encryptor, get_encryptor TEST_DATA_DIR = os.path.join(MONKEY_ISLAND_ABS_PATH, "cc", "testing") @@ -14,13 +14,13 @@ def test_aes_cbc_encryption(): initialize_encryptor(TEST_DATA_DIR) - assert encryptor().enc(PLAINTEXT) != PLAINTEXT + assert get_encryptor().enc(PLAINTEXT) != PLAINTEXT def test_aes_cbc_decryption(): initialize_encryptor(TEST_DATA_DIR) - assert encryptor().dec(CYPHERTEXT) == PLAINTEXT + assert get_encryptor().dec(CYPHERTEXT) == PLAINTEXT def test_create_new_password_file(tmpdir): From 4c9cd3ebe4cf6987df12d9d950d6181d23144611 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 25 Feb 2021 06:41:12 -0500 Subject: [PATCH 6/9] cc: rename DATA_DIR constant in test to WITH_DATA_DIR --- .../monkey_island/cc/environment/test_environment_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/environment/test_environment_config.py b/monkey/monkey_island/cc/environment/test_environment_config.py index 986f958bfee..41c333b5b87 100644 --- a/monkey/monkey_island/cc/environment/test_environment_config.py +++ b/monkey/monkey_island/cc/environment/test_environment_config.py @@ -22,7 +22,7 @@ STANDARD_WITH_CREDENTIALS = os.path.join( TEST_RESOURCES_DIR, "server_config_standard_with_credentials.json" ) -DATA_DIR = os.path.join(TEST_RESOURCES_DIR, "server_config_data_dir.json") +WITH_DATA_DIR = os.path.join(TEST_RESOURCES_DIR, "server_config_data_dir.json") @pytest.fixture @@ -121,5 +121,5 @@ def test_generate_default_file(config_file): def test_data_dir(): - environment_config = EnvironmentConfig(DATA_DIR) + environment_config = EnvironmentConfig(WITH_DATA_DIR) assert environment_config.data_dir == "/test/data/dir" From 64b94313353d85906e9d7eea65408acc44182e4a Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 25 Feb 2021 06:44:34 -0500 Subject: [PATCH 7/9] cc: rename data_dir parameter in encryptor to password_file_dir --- monkey/monkey_island/cc/encryptor.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monkey/monkey_island/cc/encryptor.py b/monkey/monkey_island/cc/encryptor.py index 0cf440c5488..fd9791db381 100644 --- a/monkey/monkey_island/cc/encryptor.py +++ b/monkey/monkey_island/cc/encryptor.py @@ -14,9 +14,9 @@ class Encryptor: _BLOCK_SIZE = 32 _PASSWORD_FILENAME = "mongo_key.bin" - def __init__(self, data_dir): + def __init__(self, password_file_dir): password_file = os.path.expanduser( - os.path.join(data_dir, self._PASSWORD_FILENAME) + os.path.join(password_file_dir, self._PASSWORD_FILENAME) ) if os.path.exists(password_file): @@ -55,10 +55,10 @@ def dec(self, enc_message): return self._unpad(cipher.decrypt(enc_message[AES.block_size :]).decode()) -def initialize_encryptor(data_dir): +def initialize_encryptor(password_file_dir): global _encryptor - _encryptor = Encryptor(data_dir) + _encryptor = Encryptor(password_file_dir) def get_encryptor(): From c900694a175604d5405d296a410663322b1559da Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 25 Feb 2021 06:51:03 -0500 Subject: [PATCH 8/9] cc: add encrypt/decrypt test --- monkey/monkey_island/cc/test_encryptor.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/monkey/monkey_island/cc/test_encryptor.py b/monkey/monkey_island/cc/test_encryptor.py index ebb9be0a12a..6348265c5e4 100644 --- a/monkey/monkey_island/cc/test_encryptor.py +++ b/monkey/monkey_island/cc/test_encryptor.py @@ -23,6 +23,12 @@ def test_aes_cbc_decryption(): assert get_encryptor().dec(CYPHERTEXT) == PLAINTEXT +def test_aes_cbc_enc_dec(): + initialize_encryptor(TEST_DATA_DIR) + + assert get_encryptor().dec(get_encryptor().enc(PLAINTEXT)) == PLAINTEXT + + def test_create_new_password_file(tmpdir): initialize_encryptor(tmpdir) From 90acc46b5a4178b742747c17fd4a783f8fb73b4f Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 25 Feb 2021 07:02:00 -0500 Subject: [PATCH 9/9] cc: rename server_config_data_dir.json -> server_config_with_data_dir.json --- monkey/monkey_island/cc/environment/test_environment_config.py | 2 +- ...er_config_data_dir.json => server_config_with_data_dir.json} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename monkey/monkey_island/cc/testing/environment/{server_config_data_dir.json => server_config_with_data_dir.json} (100%) diff --git a/monkey/monkey_island/cc/environment/test_environment_config.py b/monkey/monkey_island/cc/environment/test_environment_config.py index 41c333b5b87..abb73d842b8 100644 --- a/monkey/monkey_island/cc/environment/test_environment_config.py +++ b/monkey/monkey_island/cc/environment/test_environment_config.py @@ -22,7 +22,7 @@ STANDARD_WITH_CREDENTIALS = os.path.join( TEST_RESOURCES_DIR, "server_config_standard_with_credentials.json" ) -WITH_DATA_DIR = os.path.join(TEST_RESOURCES_DIR, "server_config_data_dir.json") +WITH_DATA_DIR = os.path.join(TEST_RESOURCES_DIR, "server_config_with_data_dir.json") @pytest.fixture diff --git a/monkey/monkey_island/cc/testing/environment/server_config_data_dir.json b/monkey/monkey_island/cc/testing/environment/server_config_with_data_dir.json similarity index 100% rename from monkey/monkey_island/cc/testing/environment/server_config_data_dir.json rename to monkey/monkey_island/cc/testing/environment/server_config_with_data_dir.json