encrypt credentials in config+telemetry

This commit is contained in:
Itay Mizeretz 2018-02-13 16:34:37 +02:00
parent 29e85100d2
commit 06a2e4f18d
3 changed files with 170 additions and 98 deletions

View File

@ -18,6 +18,6 @@ class MonkeyConfiguration(flask_restful.Resource):
if config_json.has_key('reset'): if config_json.has_key('reset'):
ConfigService.reset_config() ConfigService.reset_config()
else: else:
ConfigService.update_config(config_json) ConfigService.update_config(config_json, should_encrypt=True)
return self.get() return self.get()

View File

@ -11,6 +11,7 @@ from cc.database import mongo
from cc.services.config import ConfigService from cc.services.config import ConfigService
from cc.services.edge import EdgeService from cc.services.edge import EdgeService
from cc.services.node import NodeService from cc.services.node import NodeService
from cc.encryptor import encryptor
__author__ = 'Barak' __author__ = 'Barak'
@ -121,6 +122,8 @@ class Telemetry(flask_restful.Resource):
if new_exploit['result']: if new_exploit['result']:
EdgeService.set_edge_exploited(edge) EdgeService.set_edge_exploited(edge)
Telemetry.encrypt_exploit_creds(telemetry_json)
for attempt in telemetry_json['data']['attempts']: for attempt in telemetry_json['data']['attempts']:
if attempt['result']: if attempt['result']:
found_creds = {'user': attempt['user']} found_creds = {'user': attempt['user']}
@ -163,25 +166,49 @@ class Telemetry(flask_restful.Resource):
def process_system_info_telemetry(telemetry_json): def process_system_info_telemetry(telemetry_json):
if 'credentials' in telemetry_json['data']: if 'credentials' in telemetry_json['data']:
creds = telemetry_json['data']['credentials'] creds = telemetry_json['data']['credentials']
for user in creds: Telemetry.encrypt_system_info_creds(creds)
ConfigService.creds_add_username(user) Telemetry.add_system_info_creds_to_config(creds)
if 'password' in creds[user]: Telemetry.replace_user_dot_with_comma(creds)
ConfigService.creds_add_password(creds[user]['password'])
if 'lm_hash' in creds[user]:
ConfigService.creds_add_lm_hash(creds[user]['lm_hash'])
if 'ntlm_hash' in creds[user]:
ConfigService.creds_add_ntlm_hash(creds[user]['ntlm_hash'])
for user in creds:
if -1 != user.find('.'):
new_user = user.replace('.', ',')
creds[new_user] = creds.pop(user)
@staticmethod @staticmethod
def process_trace_telemetry(telemetry_json): def process_trace_telemetry(telemetry_json):
# Nothing to do # Nothing to do
return return
@staticmethod
def replace_user_dot_with_comma(creds):
for user in creds:
if -1 != user.find('.'):
new_user = user.replace('.', ',')
creds[new_user] = creds.pop(user)
@staticmethod
def encrypt_system_info_creds(creds):
for user in creds:
for field in ['password', 'lm_hash', 'ntlm_hash']:
if field in creds[user]:
creds[user][field] = encryptor.enc(creds[user][field])
@staticmethod
def add_system_info_creds_to_config(creds):
for user in creds:
ConfigService.creds_add_username(user)
if 'password' in creds[user]:
ConfigService.creds_add_password(creds[user]['password'])
if 'lm_hash' in creds[user]:
ConfigService.creds_add_lm_hash(creds[user]['lm_hash'])
if 'ntlm_hash' in creds[user]:
ConfigService.creds_add_ntlm_hash(creds[user]['ntlm_hash'])
@staticmethod
def encrypt_exploit_creds(telemetry_json):
attempts = telemetry_json['data']['attempts']
for i in range(len(attempts)):
for field in ['password', 'lm_hash', 'ntlm_hash']:
credential = attempts[i][field]
if len(credential) > 0:
attempts[i][field] = encryptor.enc(credential)
TELEM_PROCESS_DICT = \ TELEM_PROCESS_DICT = \
{ {

View File

@ -1,6 +1,9 @@
from cc.database import mongo import copy
from jsonschema import Draft4Validator, validators from jsonschema import Draft4Validator, validators
from cc.database import mongo
from cc.encryptor import encryptor
from cc.island_config import ISLAND_PORT from cc.island_config import ISLAND_PORT
from cc.utils import local_ip_addresses from cc.utils import local_ip_addresses
@ -17,60 +20,60 @@ SCHEMA = {
"type": "string", "type": "string",
"anyOf": [ "anyOf": [
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"SmbExploiter" "SmbExploiter"
], ],
"title": "SMB Exploiter" "title": "SMB Exploiter"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"WmiExploiter" "WmiExploiter"
], ],
"title": "WMI Exploiter" "title": "WMI Exploiter"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"RdpExploiter" "RdpExploiter"
], ],
"title": "RDP Exploiter (UNSAFE)" "title": "RDP Exploiter (UNSAFE)"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"Ms08_067_Exploiter" "Ms08_067_Exploiter"
], ],
"title": "MS08-067 Exploiter (UNSAFE)" "title": "MS08-067 Exploiter (UNSAFE)"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"SSHExploiter" "SSHExploiter"
], ],
"title": "SSH Exploiter" "title": "SSH Exploiter"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"ShellShockExploiter" "ShellShockExploiter"
], ],
"title": "ShellShock Exploiter" "title": "ShellShock Exploiter"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"SambaCryExploiter" "SambaCryExploiter"
], ],
"title": "SambaCry Exploiter" "title": "SambaCry Exploiter"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"ElasticGroovyExploiter" "ElasticGroovyExploiter"
], ],
"title": "ElasticGroovy Exploiter" "title": "ElasticGroovy Exploiter"
}, },
] ]
}, },
@ -79,46 +82,46 @@ SCHEMA = {
"type": "string", "type": "string",
"anyOf": [ "anyOf": [
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"SMBFinger" "SMBFinger"
], ],
"title": "SMBFinger" "title": "SMBFinger"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"SSHFinger" "SSHFinger"
], ],
"title": "SSHFinger" "title": "SSHFinger"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"PingScanner" "PingScanner"
], ],
"title": "PingScanner" "title": "PingScanner"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"HTTPFinger" "HTTPFinger"
], ],
"title": "HTTPFinger" "title": "HTTPFinger"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"MySQLFinger" "MySQLFinger"
], ],
"title": "MySQLFinger" "title": "MySQLFinger"
}, },
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
"ElasticFinger" "ElasticFinger"
], ],
"title": "ElasticFinger" "title": "ElasticFinger"
} }
] ]
} }
@ -794,29 +797,42 @@ SCHEMA = {
} }
} }
ENCRYPTED_CONFIG_ARRAYS = \
[
['basic', 'credentials', 'exploit_password_list'],
['internal', 'exploits', 'exploit_lm_hash_list'],
['internal', 'exploits', 'exploit_ntlm_hash_list']
]
class ConfigService: class ConfigService:
default_config = None
def __init__(self): def __init__(self):
pass pass
@staticmethod @staticmethod
def get_config(is_initial_config=False): def get_config(is_initial_config=False, should_decrypt=True):
config = mongo.db.config.find_one({'name': 'initial' if is_initial_config else 'newconfig'}) or {} config = mongo.db.config.find_one({'name': 'initial' if is_initial_config else 'newconfig'}) or {}
for field in ('name', '_id'): for field in ('name', '_id'):
config.pop(field, None) config.pop(field, None)
if should_decrypt and len(config) > 0:
ConfigService.decrypt_config(config)
return config return config
@staticmethod @staticmethod
def get_config_value(config_key_as_arr, is_initial_config=False): def get_config_value(config_key_as_arr, is_initial_config=False, should_decrypt=True):
config_key = reduce(lambda x, y: x+'.'+y, config_key_as_arr) config_key = reduce(lambda x, y: x + '.' + y, config_key_as_arr)
config = mongo.db.config.find_one({'name': 'initial' if is_initial_config else 'newconfig'}, {config_key: 1}) config = mongo.db.config.find_one({'name': 'initial' if is_initial_config else 'newconfig'}, {config_key: 1})
for config_key_part in config_key_as_arr: for config_key_part in config_key_as_arr:
config = config[config_key_part] config = config[config_key_part]
if should_decrypt and (config_key_as_arr in ENCRYPTED_CONFIG_ARRAYS):
config = [encryptor.dec(x) for x in config]
return config return config
@staticmethod @staticmethod
def get_flat_config(is_initial_config=False): def get_flat_config(is_initial_config=False, should_decrypt=True):
config_json = ConfigService.get_config(is_initial_config) config_json = ConfigService.get_config(is_initial_config, should_decrypt)
flat_config_json = {} flat_config_json = {}
for i in config_json: for i in config_json:
for j in config_json[i]: for j in config_json[i]:
@ -860,27 +876,38 @@ class ConfigService:
ConfigService.add_item_to_config_set('internal.exploits.exploit_ntlm_hash_list', ntlm_hash) ConfigService.add_item_to_config_set('internal.exploits.exploit_ntlm_hash_list', ntlm_hash)
@staticmethod @staticmethod
def update_config(config_json): def update_config(config_json, should_encrypt):
if should_encrypt:
ConfigService.encrypt_config(config_json)
mongo.db.config.update({'name': 'newconfig'}, {"$set": config_json}, upsert=True) mongo.db.config.update({'name': 'newconfig'}, {"$set": config_json}, upsert=True)
@staticmethod @staticmethod
def get_default_config(): def init_default_config():
defaultValidatingDraft4Validator = ConfigService._extend_config_with_default(Draft4Validator) if ConfigService.default_config is None:
config = {} defaultValidatingDraft4Validator = ConfigService._extend_config_with_default(Draft4Validator)
defaultValidatingDraft4Validator(SCHEMA).validate(config) config = {}
defaultValidatingDraft4Validator(SCHEMA).validate(config)
ConfigService.default_config = config
@staticmethod
def get_default_config(should_decrypt=True):
ConfigService.init_default_config()
config = copy.deepcopy(ConfigService.default_config)
if not should_decrypt:
ConfigService.encrypt_config(config)
return config return config
@staticmethod @staticmethod
def init_config(): def init_config():
if ConfigService.get_config() != {}: if ConfigService.get_config(should_decrypt=False) != {}:
return return
ConfigService.reset_config() ConfigService.reset_config()
@staticmethod @staticmethod
def reset_config(): def reset_config():
config = ConfigService.get_default_config() config = ConfigService.get_default_config(should_decrypt=False)
ConfigService.set_server_ips_in_config(config) ConfigService.set_server_ips_in_config(config)
ConfigService.update_config(config) ConfigService.update_config(config, should_encrypt=False)
@staticmethod @staticmethod
def set_server_ips_in_config(config): def set_server_ips_in_config(config):
@ -922,3 +949,21 @@ class ConfigService:
return validators.extend( return validators.extend(
validator_class, {"properties": set_defaults}, validator_class, {"properties": set_defaults},
) )
@staticmethod
def decrypt_config(config):
ConfigService._encrypt_config(config, True)
@staticmethod
def encrypt_config(config):
ConfigService._encrypt_config(config, False)
@staticmethod
def _encrypt_config(config, is_decrypt=False):
for config_arr_as_array in ENCRYPTED_CONFIG_ARRAYS:
config_arr = config
for config_key_part in config_arr_as_array:
config_arr = config_arr[config_key_part]
for i in range(len(config_arr)):
config_arr[i] = encryptor.dec(config_arr[i]) if is_decrypt else encryptor.enc(config_arr[i])