diff --git a/monkey/infection_monkey/exploit/zerologon.py b/monkey/infection_monkey/exploit/zerologon.py index a882b17de..f05983d92 100644 --- a/monkey/infection_monkey/exploit/zerologon.py +++ b/monkey/infection_monkey/exploit/zerologon.py @@ -276,6 +276,8 @@ class ZerologonExploiter(HostExploiter): ) def add_extracted_creds_to_exploit_info(self, user: str, lmhash: str, nthash: str) -> None: + # TODO exploit_info["credentials"] is discontinued, + # refactor to send a credential telemetry self.exploit_info["credentials"].update( { user: { diff --git a/monkey/monkey_island/cc/models/__init__.py b/monkey/monkey_island/cc/models/__init__.py index cab95ae18..c293ae2e7 100644 --- a/monkey/monkey_island/cc/models/__init__.py +++ b/monkey/monkey_island/cc/models/__init__.py @@ -3,8 +3,8 @@ from .command_control_channel import CommandControlChannel # Order of importing matters here, for registering the embedded and referenced documents before # using them. from .config import Config -from .creds import Creds from .monkey import Monkey from .monkey_ttl import MonkeyTtl from .pba_results import PbaResults from monkey_island.cc.models.report.report import Report +from .stolen_credentials import StolenCredentials diff --git a/monkey/monkey_island/cc/models/creds.py b/monkey/monkey_island/cc/models/creds.py deleted file mode 100644 index d0861846d..000000000 --- a/monkey/monkey_island/cc/models/creds.py +++ /dev/null @@ -1,10 +0,0 @@ -from mongoengine import EmbeddedDocument - - -class Creds(EmbeddedDocument): - """ - TODO get an example of this data, and make it strict - """ - - meta = {"strict": False} - pass diff --git a/monkey/monkey_island/cc/models/monkey.py b/monkey/monkey_island/cc/models/monkey.py index af17e45a2..c7fe734b6 100644 --- a/monkey/monkey_island/cc/models/monkey.py +++ b/monkey/monkey_island/cc/models/monkey.py @@ -38,7 +38,6 @@ class Monkey(Document): # SCHEMA guid = StringField(required=True) config = EmbeddedDocumentField("Config") - creds = ListField(EmbeddedDocumentField("Creds")) dead = BooleanField() description = StringField() hostname = StringField() diff --git a/monkey/monkey_island/cc/models/stolen_credentials.py b/monkey/monkey_island/cc/models/stolen_credentials.py new file mode 100644 index 000000000..fea6068bd --- /dev/null +++ b/monkey/monkey_island/cc/models/stolen_credentials.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from mongoengine import Document, ListField, ReferenceField + +from monkey_island.cc.models import Monkey +from monkey_island.cc.services.telemetry.processing.credentials import Credentials + + +class StolenCredentials(Document): + """ + This class has 2 main section: + * The schema section defines the DB fields in the document. This is the data of the + object. + * The logic section defines complex questions we can ask about a single document which + are asked multiple + times, somewhat like an API. + """ + + # SCHEMA + monkey = ReferenceField(Monkey) + identities = ListField() + secrets = ListField() + + @staticmethod + def from_credentials(credentials: Credentials) -> StolenCredentials: + stolen_creds = StolenCredentials() + + stolen_creds.secrets = [secret["credential_type"] for secret in credentials.secrets] + stolen_creds.identities = credentials.identities + stolen_creds.monkey = Monkey.get_single_monkey_by_guid(credentials.monkey_guid).id + return stolen_creds diff --git a/monkey/monkey_island/cc/models/telemetries/telemetry_dal.py b/monkey/monkey_island/cc/models/telemetries/telemetry_dal.py index d6425238f..a46242419 100644 --- a/monkey/monkey_island/cc/models/telemetries/telemetry_dal.py +++ b/monkey/monkey_island/cc/models/telemetries/telemetry_dal.py @@ -5,23 +5,9 @@ from typing import List from monkey_island.cc.database import mongo from monkey_island.cc.models import CommandControlChannel from monkey_island.cc.models.telemetries.telemetry import Telemetry -from monkey_island.cc.server_utils.encryption import ( - FieldNotFoundError, - MimikatzResultsEncryptor, - SensitiveField, - decrypt_dict, - encrypt_dict, -) - -sensitive_fields = [SensitiveField("data.credentials", MimikatzResultsEncryptor)] def save_telemetry(telemetry_dict: dict): - try: - telemetry_dict = encrypt_dict(sensitive_fields, telemetry_dict) - except FieldNotFoundError: - pass # Not all telemetries require encryption - cc_channel = CommandControlChannel( src=telemetry_dict["command_control_channel"]["src"], dst=telemetry_dict["command_control_channel"]["dst"], @@ -35,14 +21,5 @@ def save_telemetry(telemetry_dict: dict): ).save() -# A lot of codebase is using queries for telemetry collection and document field encryption is -# not yet implemented in mongoengine. To avoid big time investment, queries are used for now. def get_telemetry_by_query(query: dict, output_fields=None) -> List[dict]: - telemetries = mongo.db.telemetry.find(query, output_fields) - decrypted_list = [] - for telemetry in telemetries: - try: - decrypted_list.append(decrypt_dict(sensitive_fields, telemetry)) - except FieldNotFoundError: - decrypted_list.append(telemetry) - return decrypted_list + return mongo.db.telemetry.find(query, output_fields) diff --git a/monkey/monkey_island/cc/resources/monkey.py b/monkey/monkey_island/cc/resources/monkey.py index ae8493398..b32ecbb83 100644 --- a/monkey/monkey_island/cc/resources/monkey.py +++ b/monkey/monkey_island/cc/resources/monkey.py @@ -69,7 +69,6 @@ class Monkey(flask_restful.Resource): def post(self, **kw): with agent_killing_mutex: monkey_json = json.loads(request.data) - monkey_json["creds"] = [] monkey_json["dead"] = False if "keepalive" in monkey_json: monkey_json["keepalive"] = dateutil.parser.parse(monkey_json["keepalive"]) @@ -163,8 +162,6 @@ class Monkey(flask_restful.Resource): EdgeService.update_all_dst_nodes( old_dst_node_id=node_id, new_dst_node_id=new_monkey_id ) - for creds in existing_node["creds"]: - NodeService.add_credentials_to_monkey(new_monkey_id, creds) mongo.db.node.remove({"_id": node_id}) return {"id": new_monkey_id} diff --git a/monkey/monkey_island/cc/resources/telemetry.py b/monkey/monkey_island/cc/resources/telemetry.py index 1158e82f0..3358788f3 100644 --- a/monkey/monkey_island/cc/resources/telemetry.py +++ b/monkey/monkey_island/cc/resources/telemetry.py @@ -6,10 +6,9 @@ import dateutil import flask_restful from flask import request -from common.common_consts.telem_categories import TelemCategoryEnum from monkey_island.cc.database import mongo from monkey_island.cc.models.monkey import Monkey -from monkey_island.cc.models.telemetries import get_telemetry_by_query, save_telemetry +from monkey_island.cc.models.telemetries import get_telemetry_by_query from monkey_island.cc.resources.auth.auth import jwt_required from monkey_island.cc.resources.blackbox.utils.telem_store import TestTelemStore from monkey_island.cc.services.node import NodeService @@ -61,8 +60,6 @@ class Telemetry(flask_restful.Resource): process_telemetry(telemetry_json) - save_telemetry(telemetry_json) - return {}, 201 @staticmethod @@ -80,10 +77,5 @@ class Telemetry(flask_restful.Resource): monkey_label = telem_monkey_guid x["monkey"] = monkey_label objects.append(x) - if x["telem_category"] == TelemCategoryEnum.SYSTEM_INFO and "credentials" in x["data"]: - for user in x["data"]["credentials"]: - if -1 != user.find(","): - new_user = user.replace(",", ".") - x["data"]["credentials"][new_user] = x["data"]["credentials"].pop(user) return objects diff --git a/monkey/monkey_island/cc/server_utils/encryption/__init__.py b/monkey/monkey_island/cc/server_utils/encryption/__init__.py index 16ac78cbe..4cfe67fe2 100644 --- a/monkey/monkey_island/cc/server_utils/encryption/__init__.py +++ b/monkey/monkey_island/cc/server_utils/encryption/__init__.py @@ -23,5 +23,4 @@ from .dict_encryptor import ( FieldNotFoundError, ) from .field_encryptors.i_field_encryptor import IFieldEncryptor -from .field_encryptors.mimikatz_results_encryptor import MimikatzResultsEncryptor from .field_encryptors.string_list_encryptor import StringListEncryptor diff --git a/monkey/monkey_island/cc/server_utils/encryption/field_encryptors/__init__.py b/monkey/monkey_island/cc/server_utils/encryption/field_encryptors/__init__.py index 7c938d25b..1ceedf768 100644 --- a/monkey/monkey_island/cc/server_utils/encryption/field_encryptors/__init__.py +++ b/monkey/monkey_island/cc/server_utils/encryption/field_encryptors/__init__.py @@ -1,3 +1,2 @@ from .i_field_encryptor import IFieldEncryptor -from .mimikatz_results_encryptor import MimikatzResultsEncryptor from .string_list_encryptor import StringListEncryptor diff --git a/monkey/monkey_island/cc/server_utils/encryption/field_encryptors/mimikatz_results_encryptor.py b/monkey/monkey_island/cc/server_utils/encryption/field_encryptors/mimikatz_results_encryptor.py deleted file mode 100644 index 31f597e60..000000000 --- a/monkey/monkey_island/cc/server_utils/encryption/field_encryptors/mimikatz_results_encryptor.py +++ /dev/null @@ -1,29 +0,0 @@ -import logging - -from ..data_store_encryptor import get_datastore_encryptor -from . import IFieldEncryptor - -logger = logging.getLogger(__name__) - - -class MimikatzResultsEncryptor(IFieldEncryptor): - - secret_types = ["password", "ntlm_hash", "lm_hash"] - - @staticmethod - def encrypt(results: dict) -> dict: - for _, credentials in results.items(): - for secret_type in MimikatzResultsEncryptor.secret_types: - credentials[secret_type] = get_datastore_encryptor().encrypt( - credentials[secret_type] - ) - return results - - @staticmethod - def decrypt(results: dict) -> dict: - for _, credentials in results.items(): - for secret_type in MimikatzResultsEncryptor.secret_types: - credentials[secret_type] = get_datastore_encryptor().decrypt( - credentials[secret_type] - ) - return results diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py index c842436dd..81cd7ad69 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py @@ -1,7 +1,7 @@ from common.utils.attack_utils import ScanStatus -from monkey_island.cc.database import mongo +from monkey_island.cc.models import StolenCredentials from monkey_island.cc.services.attack.technique_reports import AttackTechnique -from monkey_island.cc.services.reporting.report import ReportService +from monkey_island.cc.services.reporting.stolen_credentials import get_stolen_creds class T1003(AttackTechnique): @@ -14,29 +14,10 @@ class T1003(AttackTechnique): scanned_msg = "" used_msg = "Monkey successfully obtained some credentials from systems on the network." - query = { - "$or": [ - { - "telem_category": "system_info", - "$and": [ - {"data.credentials": {"$exists": True}}, - {"data.credentials": {"$gt": {}}}, - ], - }, # $gt: {} checks if field is not an empty object - { - "telem_category": "exploit", - "$and": [ - {"data.info.credentials": {"$exists": True}}, - {"data.info.credentials": {"$gt": {}}}, - ], - }, - ] - } - @staticmethod def get_report_data(): def get_technique_status_and_data(): - if mongo.db.telemetry.count_documents(T1003.query): + if list(StolenCredentials.objects()): status = ScanStatus.USED.value else: status = ScanStatus.UNSCANNED.value @@ -47,6 +28,5 @@ class T1003(AttackTechnique): data.update(T1003.get_message_and_status(status)) data.update(T1003.get_mitigation_by_status(status)) - data["stolen_creds"] = ReportService.get_stolen_creds() - data["stolen_creds"].extend(ReportService.get_ssh_keys()) + data["stolen_creds"] = get_stolen_creds() return data diff --git a/monkey/monkey_island/cc/services/node.py b/monkey/monkey_island/cc/services/node.py index 79c3408bf..74fb1b091 100644 --- a/monkey/monkey_island/cc/services/node.py +++ b/monkey/monkey_island/cc/services/node.py @@ -202,7 +202,6 @@ class NodeService: "ip_addresses": [ip_address], "domain_name": domain_name, "exploited": False, - "creds": [], "os": {"type": "unknown", "version": "unknown"}, } ) @@ -318,14 +317,6 @@ class NodeService: def is_monkey_finished_running(): return NodeService.is_any_monkey_exists() and not NodeService.is_any_monkey_alive() - @staticmethod - def add_credentials_to_monkey(monkey_id, creds): - mongo.db.monkey.update({"_id": monkey_id}, {"$push": {"creds": creds}}) - - @staticmethod - def add_credentials_to_node(node_id, creds): - mongo.db.node.update({"_id": node_id}, {"$push": {"creds": creds}}) - @staticmethod def get_node_or_monkey_by_ip(ip_address): node = NodeService.get_node_by_ip(ip_address) diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index 8d93d8062..3ac0c0364 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -16,7 +16,6 @@ from common.network.segmentation_utils import get_ip_in_src_and_not_in_dst from monkey_island.cc.database import mongo from monkey_island.cc.models import Monkey from monkey_island.cc.models.report import get_report, save_report -from monkey_island.cc.models.telemetries import get_telemetry_by_query from monkey_island.cc.services.config import ConfigService from monkey_island.cc.services.configuration.utils import ( get_config_network_segments_as_subnet_groups, @@ -26,22 +25,21 @@ from monkey_island.cc.services.reporting.exploitations.manual_exploitation impor from monkey_island.cc.services.reporting.exploitations.monkey_exploitation import ( get_monkey_exploited, ) -from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_descriptor_enum import ( # noqa: E501 - ExploiterDescriptorEnum, -) -from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.cred_exploit import ( # noqa: E501 - CredentialType, -) -from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import ( # noqa: E501 - ExploiterReportInfo, -) from monkey_island.cc.services.reporting.pth_report import PTHReportService from monkey_island.cc.services.reporting.report_exporter_manager import ReportExporterManager from monkey_island.cc.services.reporting.report_generation_synchronisation import ( safe_generate_regular_report, ) +from monkey_island.cc.services.reporting.stolen_credentials import ( + extract_ssh_keys, + get_stolen_creds, +) from monkey_island.cc.services.utils.network_utils import get_subnets, local_ip_addresses +from .issue_processing.exploit_processing.exploiter_descriptor_enum import ExploiterDescriptorEnum +from .issue_processing.exploit_processing.processors.cred_exploit import CredentialType +from .issue_processing.exploit_processing.processors.exploit import ExploiterReportInfo + logger = logging.getLogger(__name__) @@ -133,104 +131,6 @@ class ReportService: nodes = nodes_without_monkeys + nodes_with_monkeys return nodes - @staticmethod - def get_stolen_creds(): - creds = [] - - stolen_system_info_creds = ReportService._get_credentials_from_system_info_telems() - creds.extend(stolen_system_info_creds) - - stolen_exploit_creds = ReportService._get_credentials_from_exploit_telems() - creds.extend(stolen_exploit_creds) - - logger.info("Stolen creds generated for reporting") - return creds - - @staticmethod - def _get_credentials_from_system_info_telems(): - formatted_creds = [] - for telem in get_telemetry_by_query( - {"telem_category": "system_info", "data.credentials": {"$exists": True}}, - {"data.credentials": 1, "monkey_guid": 1}, - ): - creds = telem["data"]["credentials"] - origin = NodeService.get_monkey_by_guid(telem["monkey_guid"])["hostname"] - formatted_creds.extend(ReportService._format_creds_for_reporting(telem, creds, origin)) - return formatted_creds - - @staticmethod - def _get_credentials_from_exploit_telems(): - formatted_creds = [] - for telem in mongo.db.telemetry.find( - {"telem_category": "exploit", "data.info.credentials": {"$exists": True}}, - {"data.info.credentials": 1, "data.machine": 1, "monkey_guid": 1}, - ): - creds = telem["data"]["info"]["credentials"] - domain_name = telem["data"]["machine"]["domain_name"] - ip = telem["data"]["machine"]["ip_addr"] - origin = domain_name if domain_name else ip - formatted_creds.extend(ReportService._format_creds_for_reporting(telem, creds, origin)) - return formatted_creds - - @staticmethod - def _format_creds_for_reporting(telem, monkey_creds, origin): - creds = [] - CRED_TYPE_DICT = { - "password": "Clear Password", - "lm_hash": "LM hash", - "ntlm_hash": "NTLM hash", - } - if len(monkey_creds) == 0: - return [] - - for user in monkey_creds: - for cred_type in CRED_TYPE_DICT: - if cred_type not in monkey_creds[user] or not monkey_creds[user][cred_type]: - continue - username = ( - monkey_creds[user]["username"] if "username" in monkey_creds[user] else user - ) - cred_row = { - "username": username, - "type": CRED_TYPE_DICT[cred_type], - "origin": origin, - } - if cred_row not in creds: - creds.append(cred_row) - return creds - - @staticmethod - def get_ssh_keys(): - """ - Return private ssh keys found as credentials - :return: List of credentials - """ - creds = [] - for telem in mongo.db.telemetry.find( - {"telem_category": "system_info", "data.ssh_info": {"$exists": True}}, - {"data.ssh_info": 1, "monkey_guid": 1}, - ): - origin = NodeService.get_monkey_by_guid(telem["monkey_guid"])["hostname"] - if telem["data"]["ssh_info"]: - # Pick out all ssh keys not yet included in creds - ssh_keys = [ - { - "username": key_pair["name"], - "type": "Clear SSH private key", - "origin": origin, - } - for key_pair in telem["data"]["ssh_info"] - if key_pair["private_key"] - and { - "username": key_pair["name"], - "type": "Clear SSH private key", - "origin": origin, - } - not in creds - ] - creds.extend(ssh_keys) - return creds - @staticmethod def process_exploit(exploit) -> ExploiterReportInfo: exploiter_type = exploit["data"]["exploiter"] @@ -564,6 +464,7 @@ class ReportService: issue_set = ReportService.get_issue_set(issues, config_users, config_passwords) cross_segment_issues = ReportService.get_cross_segment_issues() monkey_latest_modify_time = Monkey.get_latest_modifytime() + stolen_creds = get_stolen_creds() scanned_nodes = ReportService.get_scanned() exploited_cnt = len(get_monkey_exploited()) @@ -585,8 +486,8 @@ class ReportService: "glance": { "scanned": scanned_nodes, "exploited_cnt": exploited_cnt, - "stolen_creds": ReportService.get_stolen_creds(), - "ssh_keys": ReportService.get_ssh_keys(), + "stolen_creds": stolen_creds, + "ssh_keys": extract_ssh_keys(stolen_creds), "strong_users": PTHReportService.get_strong_users_on_crit_details(), }, "recommendations": {"issues": issues, "domain_issues": domain_issues}, diff --git a/monkey/monkey_island/cc/services/reporting/stolen_credentials.py b/monkey/monkey_island/cc/services/reporting/stolen_credentials.py new file mode 100644 index 000000000..a1f596ad5 --- /dev/null +++ b/monkey/monkey_island/cc/services/reporting/stolen_credentials.py @@ -0,0 +1,52 @@ +import logging +from typing import Mapping, Sequence + +from common.common_consts.credential_component_type import CredentialComponentType +from monkey_island.cc.models import StolenCredentials + +logger = logging.getLogger(__name__) + + +def get_stolen_creds() -> Sequence[Mapping]: + stolen_creds = _fetch_from_db() + stolen_creds = _format_creds_for_reporting(stolen_creds) + + logger.info("Stolen creds generated for reporting") + return stolen_creds + + +def extract_ssh_keys(credentials: Sequence[Mapping]) -> Sequence[Mapping]: + return [c for c in credentials if c["_type"] == CredentialComponentType.SSH_KEYPAIR.name] + + +def _fetch_from_db() -> Sequence[StolenCredentials]: + return list(StolenCredentials.objects()) + + +def _format_creds_for_reporting(credentials: Sequence[StolenCredentials]): + formatted_creds = [] + cred_type_dict = { + CredentialComponentType.PASSWORD.name: "Clear Password", + CredentialComponentType.LM_HASH.name: "LM hash", + CredentialComponentType.NT_HASH.name: "NTLM hash", + CredentialComponentType.SSH_KEYPAIR.name: "Clear SSH private key", + } + + for cred in credentials: + for secret_type in cred.secrets: + if secret_type not in cred_type_dict: + continue + username = _get_username(cred) + cred_row = { + "username": username, + "_type": secret_type, + "type": cred_type_dict[secret_type], + "origin": cred.monkey.hostname, + } + if cred_row not in formatted_creds: + formatted_creds.append(cred_row) + return formatted_creds + + +def _get_username(credentials: StolenCredentials) -> str: + return credentials.identities[0]["username"] if credentials.identities else "" 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 index 9df47f91d..5c6d15631 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/credentials/credentials_parser.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/credentials/credentials_parser.py @@ -3,6 +3,7 @@ from itertools import chain from typing import Mapping from common.common_consts.credential_component_type import CredentialComponentType +from monkey_island.cc.models import StolenCredentials from .credentials import Credentials from .identities.username_processor import process_username @@ -29,6 +30,12 @@ def parse_credentials(telemetry_dict: Mapping): ] for credential in credentials: + _store_in_db(credential) for cred_comp in chain(credential.identities, credential.secrets): credential_type = CredentialComponentType[cred_comp["credential_type"]] CREDENTIAL_COMPONENT_PROCESSORS[credential_type](cred_comp, credential) + + +def _store_in_db(credentials: Credentials): + stolen_cred_doc = StolenCredentials.from_credentials(credentials) + stolen_cred_doc.save() diff --git a/monkey/monkey_island/cc/services/telemetry/processing/exploit.py b/monkey/monkey_island/cc/services/telemetry/processing/exploit.py index a867267d0..d035dedd3 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/exploit.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/exploit.py @@ -4,7 +4,6 @@ import dateutil 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 from monkey_island.cc.services.edge.displayed_edge import EdgeService from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.telemetry.processing.utils import ( @@ -20,7 +19,6 @@ def process_exploit_telemetry(telemetry_json): edge = get_edge_by_scan_or_exploit_telemetry(telemetry_json) update_network_with_exploit(edge, telemetry_json) update_node_credentials_from_successful_attempts(edge, telemetry_json) - add_exploit_extracted_creds_to_config(telemetry_json) check_machine_exploited( current_monkey=Monkey.get_single_monkey_by_guid(telemetry_json["monkey_guid"]), @@ -31,19 +29,6 @@ def process_exploit_telemetry(telemetry_json): ) -def add_exploit_extracted_creds_to_config(telemetry_json): - if "credentials" in telemetry_json["data"]["info"]: - creds = telemetry_json["data"]["info"]["credentials"] - for user in creds: - ConfigService.creds_add_username(creds[user]["username"]) - if "password" in creds[user] and creds[user]["password"]: - ConfigService.creds_add_password(creds[user]["password"]) - if "lm_hash" in creds[user] and creds[user]["lm_hash"]: - ConfigService.creds_add_lm_hash(creds[user]["lm_hash"]) - if "ntlm_hash" in creds[user] and creds[user]["ntlm_hash"]: - ConfigService.creds_add_ntlm_hash(creds[user]["ntlm_hash"]) - - def update_node_credentials_from_successful_attempts(edge: EdgeService, telemetry_json): for attempt in telemetry_json["data"]["attempts"]: if attempt["result"]: diff --git a/monkey/monkey_island/cc/services/telemetry/processing/processing.py b/monkey/monkey_island/cc/services/telemetry/processing/processing.py index abea5dc38..709097ee0 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/processing.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/processing.py @@ -1,9 +1,11 @@ import logging from common.common_consts.telem_categories import TelemCategoryEnum +from monkey_island.cc.models.telemetries import save_telemetry from monkey_island.cc.services.telemetry.processing.aws_info import process_aws_telemetry -from monkey_island.cc.services.telemetry.processing.credentials.credentials_parser import\ - parse_credentials +from monkey_island.cc.services.telemetry.processing.credentials.credentials_parser import ( + parse_credentials, +) from monkey_island.cc.services.telemetry.processing.exploit import process_exploit_telemetry from monkey_island.cc.services.telemetry.processing.post_breach import process_post_breach_telemetry from monkey_island.cc.services.telemetry.processing.scan import process_scan_telemetry @@ -25,6 +27,10 @@ TELEMETRY_CATEGORY_TO_PROCESSING_FUNC = { TelemCategoryEnum.TUNNEL: process_tunnel_telemetry, } +# Don't save credential telemetries in telemetries collection. +# Credentials are stored in StolenCredentials documents +UNSAVED_TELEMETRIES = [TelemCategoryEnum.CREDENTIALS] + def process_telemetry(telemetry_json): try: @@ -33,6 +39,10 @@ def process_telemetry(telemetry_json): TELEMETRY_CATEGORY_TO_PROCESSING_FUNC[telem_category](telemetry_json) else: logger.info("Got unknown type of telemetry: %s" % telem_category) + + if telem_category not in UNSAVED_TELEMETRIES: + save_telemetry(telemetry_json) + except Exception as ex: logger.error( "Exception caught while processing telemetry. Info: {}".format(ex), exc_info=True diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index 932879fea..f058a3069 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -556,7 +556,7 @@ class ReportPageComponent extends AuthComponent {