IndicatorMaliciousRatioCalculation

Return indicators appears in resolved incidents, and resolved incident ids. This automation runs using the default Limited User role, unless you explicitly change the permissions. For more information, see the section about permissions here: - For Cortex XSOAR 6 see https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/6.x/Cortex-XSOAR-Playbook-Design-Guide/Automations - For Cortex XSOAR 8 Cloud see https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/8/Cortex-XSOAR-Cloud-Documentation/Create-a-script - For Cortex XSOAR 8.7 On-prem see https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/8.7/Cortex-XSOAR-On-prem-Documentation/Create-a-script

python · Common Scripts

Source

import hashlib
import json
import traceback

import demistomock as demisto
from CommonServerPython import *
from dateutil import parser  # type: ignore[import]

from CommonServerUserPython import *


def get_incident_labels_map(labels):
    if labels is None:
        return {}
    labels_map = {}

    for label in labels:
        label_type = label["type"].lower()
        labels_map[label_type] = label["value"]
    return labels_map


def hash_object(str_list_dict):
    if str_list_dict == "" or str_list_dict is None:
        return str_list_dict
    if (type(str_list_dict)) is dict:
        return {k_v[0]: hash_object(k_v[1]) for k_v in iter(str_list_dict.items())}
    if isinstance(str_list_dict, list):
        return [hash_object(x) for x in str_list_dict]

    if isinstance(str_list_dict, str):
        str_value = str_list_dict.encode("utf-8")
    else:
        str_value = (str(str_list_dict)).encode("utf-8")
    return hashlib.md5(str_value).hexdigest()  # guardrails-disable-line  # nosec


def get_indicator_data(indicator):
    return {
        k: v
        for k, v in list(indicator.items())
        if k in ["indicator_type", "firstSeen", "lastSeen", "investigationIDs", "manualScore", "id", "score", "value"]
    }


def get_incident_data(incident):
    result = {k: v for k, v in list(incident.items()) if k in ["id", "type", "occurred", "CustomFields", "labels"]}
    result["labels"] = hash_object(get_incident_labels_map(result.get("labels")))
    result["CustomFields"] = hash_object(result.get("CustomFields"))
    return result


def parse_datetime(datetime_str):
    try:
        return parser.parse(datetime_str).isoformat()
    except Exception:
        return datetime_str


def build_query_for_incidents_search(base_query, from_date):
    if from_date:
        return f'{base_query} created:>="{parse_datetime(from_date)}"'
    else:
        return base_query


def indicator_malicious_ratio_calculation(args):
    appears_in_min_num_of_incidents = int(args.get("appearsInMinNumberOfIncidents"))
    max_incidents = int(args.get("maxIncidents"))
    max_indicators = int(args.get("maxIndicators"))
    base_query = args.get("query")
    max_results = int(args["maxDisplayResults"])
    generate_file_result = args["fileResult"] == "yes"
    from_date = args.get("fromDate", "")

    query = build_query_for_incidents_search(base_query, from_date)
    res = demisto.executeCommand("findIndicators", {"query": base_query, "size": max_indicators})
    indicators = res[0]["Contents"]
    indicators_result = list(map(get_indicator_data, indicators))
    res = demisto.executeCommand("SearchIncidentsV2", {"query": query.replace("incident.", ""), "size": max_incidents})
    incidents = []
    if res[0].get("Contents") and res[0].get("Contents", [{}])[0].get("Contents"):
        incidents = res[0].get("Contents", [{}])[0].get("Contents", {}).get("data")

    if incidents:
        incidents_result = list(map(get_incident_data, incidents))
        resolved_incident_ids = {x["id"] for x in incidents_result}
        non_resolved_id = set()  # type: Any
        for i in indicators_result:
            resolved = [x for x in i["investigationIDs"] if x in resolved_incident_ids]
            non_resolved_id = non_resolved_id.union(set(i["investigationIDs"]).difference(set(resolved)))
            resolved_count = len(resolved)
            total_count = len(i["investigationIDs"])
            i["resolved_incidents_count"] = resolved_count
            i["total_incidents_count"] = total_count
            i["malicious_ratio"] = float(resolved_count) / total_count

        non_resolved_incidents = []
        if non_resolved_id:
            res = demisto.executeCommand(
                "SearchIncidentsV2", {"query": " or ".join([f"id:{x}" for x in non_resolved_id]), "size": max_incidents}
            )
            if res[0].get("Contents") and res[0].get("Contents", [{}])[0].get("Contents"):
                non_resolved_incidents = res[0].get("Contents", [{}])[0].get("Contents", {}).get("data")
            if non_resolved_incidents:
                non_resolved_incidents = list(map(get_incident_data, non_resolved_incidents))
        else:
            non_resolved_incidents = []

        indicators_result = [x for x in indicators_result if x["total_incidents_count"] >= appears_in_min_num_of_incidents]
        indicators_result.sort(key=lambda x: x["malicious_ratio"], reverse=True)

        results = CommandResults(
            outputs_prefix="IndicatorMaliciousRatioCalculation",
            outputs=indicators_result,
            readable_output=tableToMarkdown(
                "Indicators Malicious Ratio",
                indicators_result[:max_results],
                headers=["value", "indicator_type", "malicious_ratio", "total_incidents_count", "score", "lastSeen"],
            ),
        )

        if generate_file_result:
            for i in indicators_result:
                i["value"] = hash_object(i["value"])

            results = fileResult(
                "MaliciousRatio.json",
                json.dumps(
                    {
                        "resolved_incidents": incidents_result,
                        "non_resolved_incidents": non_resolved_incidents,
                        "indicators": indicators_result,
                    }
                ),
            )
        return results
    else:
        return "No resolved incidents found"


""" MAIN FUNCTION """


def main():
    try:
        return_results(indicator_malicious_ratio_calculation(demisto.args()))
    except Exception as ex:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(f"Failed to execute IndicatorMaliciousRatioCalculation. Error: {ex}")


""" ENTRY POINT """

if __name__ in ("__main__", "__builtin__", "builtins"):
    main()

README

Returns indicators that appear under resolved incidents, and resolved incident IDs.

Script Data


Name Description
Script Type python
Tags ml
Cortex XSOAR Version 5.0.0

Inputs


Argument Name Description
maxIncidents The maximum number of incidents to query.
maxIndicators The maximum number of indicators to query.
appearsInMinNumberOfIncidents The indicator that appears in the minimum number of incidents.
query The query to fetch the indicators from. The incident which are “bad”.
maxDisplayResults The maximum number of results (indicators) to display as output.
fileResult The generate file result.
fromDate The start date by which to filter incidents.

Outputs


There are no outputs for this script.