CVSSCalculator

This script calculates the CVSS Base Score, Temporal Score, and Environmental Score using either the CVSS 3.0 or CVSS 3.1 calculator according to https://www.first.org/cvss/ calculation documentation.

python · Common Scripts

Source

import math
from typing import Any

import demistomock as demisto
from CommonServerPython import *


def round_up(n):
    if n is None:
        return None
    int_input = int(n * 100000)
    if (int_input % 10000) == 00:
        return int_input / 100000.0
    else:
        return math.floor((int_input / 10000) + 1) / 10.0


def main():
    args = demisto.args()
    version = args.get("version", "3.1")
    vector_string = f"CVSS:{version}/"

    values_map_options: dict[str, dict[str, dict[str, Any]]] = {
        "3.0": {
            "AV": {
                "X": None,
                "N": 0.85,
                "A": 0.62,
                "L": 0.55,
                "P": 0.2,
            },
            "AC": {"X": None, "L": 0.77, "H": 0.44},
            "PR": {"X": None, "N": 0.85, "L": {"C": 0.68, "U": 0.62}, "H": {"C": 0.5, "U": 0.27}},
            "UI": {"X": None, "N": 0.85, "R": 0.62},
            "CIA": {
                "X": None,
                "N": 0,
                "H": 0.56,
                "L": 0.22,
            },
            "E": {"X": 1, "H": 1, "F": 0.97, "P": 0.94, "U": 0.91},
            "RL": {"X": 1, "U": 1, "W": 0.97, "T": 0.96, "O": 0.95},
            "RC": {"X": 1, "C": 1, "R": 0.96, "U": 0.92},
            "CIAR": {"X": 1, "H": 1.5, "M": 1, "L": 0.5},
        },
        "3.1": {
            "AV": {
                "X": None,
                "N": 0.85,
                "A": 0.62,
                "L": 0.55,
                "P": 0.2,
            },
            "AC": {"X": None, "L": 0.77, "H": 0.44},
            "PR": {"X": None, "N": 0.85, "L": {"C": 0.68, "U": 0.62}, "H": {"C": 0.5, "U": 0.27}},
            "UI": {"X": None, "N": 0.85, "R": 0.56},
            "CIA": {
                "X": None,
                "N": 0,
                "H": 0.56,
                "L": 0.22,
            },
            "E": {"X": 1, "H": 1, "F": 0.97, "P": 0.94, "U": 0.91},
            "RL": {"X": 1, "U": 1, "W": 0.97, "T": 0.96, "O": 0.95},
            "RC": {"X": 1, "C": 1, "R": 0.96, "U": 0.92},
            "CIAR": {"X": 1, "H": 1.5, "M": 1, "L": 0.5},
        },
    }
    version = args.get("version")
    values_map = values_map_options[version]

    value_list = []
    for k, v in args.items():
        if v != "X" and k != "version":
            value_list.append(f"{k}:{v}")
    vector_string += "/".join(value_list)

    ###########################################
    # Get all required values for calculations
    ###########################################
    confidentiality = values_map["CIA"][args.get("C")]
    modified_confidentiality = args.get("MC", "X")
    modified_confidentiality = confidentiality if modified_confidentiality == "X" else values_map["CIA"][modified_confidentiality]
    integrity = values_map["CIA"][args.get("I")]
    modified_integrity = args.get("MI", "X")
    modified_integrity = integrity if modified_integrity == "X" else values_map["CIA"][modified_integrity]
    availability = values_map["CIA"][args.get("A")]
    modified_availability = args.get("MA", "X")
    modified_availability = availability if modified_availability == "X" else values_map["CIA"][modified_availability]
    exploit_code_maturity = values_map["E"].get(args.get("E"), "X")
    scope_changed = args.get("S") == "C"
    modified_scope_changed = args.get("MS") == "C"
    atack_vector = values_map["AV"].get(args.get("AV"), 0)

    modified_attack_vector = args.get("MAV", "X")
    modified_attack_vector = atack_vector if modified_attack_vector == "X" else values_map["AV"].get(modified_attack_vector, 0)
    attack_complexity = values_map["AC"][args.get("AC")]
    modified_attack_complexity = args.get("MAC", "X")
    modified_attack_complexity = (
        attack_complexity if modified_attack_complexity == "X" else values_map["AC"][modified_attack_complexity]
    )

    privileges_required = values_map["PR"][args.get("PR")]
    if type(privileges_required) is dict:
        privileges_required = (
            privileges_required.get("C") if scope_changed or modified_scope_changed else privileges_required["U"]
        )
    modified_privileges_required = args.get("MPR", "X")
    if modified_privileges_required == "X":
        modified_privileges_required = privileges_required
    elif type(modified_privileges_required) is dict:
        modified_privileges_required = (
            modified_privileges_required["C"] if scope_changed or modified_scope_changed else modified_privileges_required["U"]
        )
    else:
        modified_privileges_required = values_map["PR"][modified_privileges_required]
    user_interaction = values_map["UI"][args.get("UI")]
    modified_user_interaction = args.get("MUI", "X")
    modified_user_interaction = (
        user_interaction if modified_user_interaction == "X" else values_map["UI"][modified_user_interaction]
    )
    remediation_level = values_map["RL"][args.get("RL", "X")]
    report_confidence = values_map["RC"][args.get("RC", "X")]
    confidentiality_requirement = values_map["CIAR"][args.get("CR", "X")]
    integrity_requirement = values_map["CIAR"][args.get("IR", "X")]
    availability_requirement = values_map["CIAR"][args.get("AR", "X")]

    ###########################################
    # Base Metric Equation calculations
    ###########################################

    # Impact Sub-Score
    iss = 0
    if version in ["3.0", "3.1"]:
        iss = 1 - ((1 - confidentiality) * (1 - integrity) * (1 - availability))

    # Impact
    impact = 0.0
    if version in ["3.0", "3.1"]:
        if not scope_changed:
            impact = 6.42 * iss
        else:
            impact = 7.52 * (iss - 0.029) - 3.25 * (iss - 0.02) ** 15

    # Exploitability
    exploitability = 0.0
    if version in ["3.0", "3.1"]:
        exploitability = 8.22 * atack_vector * attack_complexity * privileges_required * user_interaction

    # Base Score
    base_score = 0.0
    if version in ["3.0", "3.1"]:
        base_score = 0
        if impact > 0:
            multiplier = 1.0
            if scope_changed:
                multiplier = 1.08
            calculated_value = multiplier * (impact + exploitability)
            base_score = min(10.0, calculated_value)
            base_score = round_up(base_score)

    ###########################################
    # Temporal Metric calculations
    ###########################################
    temporal_score_roundup = 0.0
    if version in ["3.0", "3.1"]:
        temporal_score_roundup = base_score * exploit_code_maturity * remediation_level * report_confidence

    # Environmental Metrics
    modified_impact_sub_score = 0.0
    modified_impact = 0.0
    modified_exploitability = 0.0
    if version in ["3.0", "3.1"]:
        calculatedmodified_impact_sub_score = 1 - (
            (1 - confidentiality_requirement * modified_confidentiality)
            * (1 - integrity_requirement * modified_integrity)
            * (1 - availability_requirement * modified_availability)
        )
        modified_impact_sub_score = min(0.915, calculatedmodified_impact_sub_score)

    if version in ["3.0", "3.1"]:
        if modified_scope_changed:
            if version == "3.0":
                modified_impact = (
                    7.52 * (modified_impact_sub_score - 0.029) - 3.25 * (modified_impact_sub_score * 0.9731 - 0.02) ** 15
                )
            elif version == "3.1":
                modified_impact = (
                    7.52 * (modified_impact_sub_score - 0.029) - 3.25 * (modified_impact_sub_score * 0.9731 - 0.02) ** 13
                )
        else:
            modified_impact = 6.42 * modified_impact_sub_score
        modified_exploitability = (
            8.22 * modified_attack_vector * modified_attack_complexity * modified_privileges_required * modified_user_interaction
        )

    # Environmental Score
    environmental_score = 0.0
    if version in ["3.0", "3.1"]:
        environmental_score = 0
        if modified_impact > 0:
            exponential = 1.0
            if modified_scope_changed:
                exponential = 1.08
            calculated_value = exponential * (modified_impact + modified_exploitability)
            calculated_value = min(10, calculated_value)
            calculated_value = round_up(calculated_value)
            environmental_score = calculated_value * exploit_code_maturity * remediation_level * report_confidence
            environmental_score = round_up(environmental_score)

    # Round values
    iss = round_up(iss)
    impact = round_up(impact)
    exploitability = round_up(exploitability)
    base_score = round_up(base_score)
    temporal_score_roundup = round_up(temporal_score_roundup)
    modified_impact_sub_score = round_up(modified_impact_sub_score)
    modified_impact = round_up(modified_impact)
    modified_exploitability = round_up(modified_exploitability)
    environmental_score = round_up(environmental_score)

    entry = {
        "VectorString": vector_string,
        "Version": version,
        "ImpactSubScore": iss,
        "Impact": impact,
        "Exploitability": exploitability,
        "BaseScore": base_score,
        "TemporalScore": temporal_score_roundup,
        "ModifiedImpactSubScore": modified_impact_sub_score,
        "ModifiedImpact": modified_impact,
        "ModifiedExploitability": modified_exploitability,
        "EnvironmentalScore": environmental_score,
    }

    hrentry = {k: v for k, v in entry.items() if v}
    markdown = tableToMarkdown("CVSS Score:", hrentry)

    results = CommandResults(
        readable_output=markdown,
        outputs_prefix="",
        outputs_key_field="",
        outputs={"CVSS(val.VectorString === obj.VectorString && val.Version === obj.Version)": entry},
    )
    return results


if __name__ in ["__main__", "builtin", "builtins"]:
    res = main()
    return_results(res)

README

This script calculates the CVSS Base Score, Temporal Score, and Environmental Score using either the CVSS 3.0 or CVSS 3.1 calculator according to https://www.first.org/cvss/ calculation documentation.

Script Data


Name Description
Script Type python3
Cortex XSOAR Version 5.0.0

Inputs


Argument Name Description
version The CVSS version to use for scoring. Can be “3.1” or “3.0”. Default is “3.1”.
AV Attack Vector. Can be “N”, “A”, “L”, or “P”.
AC Attack Complexity. Can be “L” or “H”.
PR Privileges Required. Can be “N”, “L”, or “H”.
UI User Interaction. Can be “N” or “R”.
S Scope. Can be “U” or “C”.
C Confidentiality. Can be “H”, “L”, or “N”.
I Integrity. Can be “H”, “L”, or “N”.
A Availability. Can be “H”, “L”, or “N”.
E Exploit Code Maturity. Can be “X”, “H”, “F”, “P”, or “U”. Default is “X”.
RL Remediation Level. Can be “X”, “U”, “W”, “T”, or “O”. Default is “X”.
RC Report Confidence. Can be “X”, “C”, “R”, or “U”. Default is “X”.
CR Confidentiality Requirement. Can be “X”, “H”, “M”, or “L”. Default is “X”.
IR Integrity Requirement. Can be “X”, “H”, “M”, or “L”. Default is “X”.
AR Availability Requirement. Can be “X”, “H”, “M”, or “L”. Default is “X”.
MAV Modified Attack Vector. Can be “X”, “N”, “A”, “L”, or “P”. Default is “X”.
MAC Modified Attack Complexity. Can be “X”, “L”, or “N”. Default is “X”.
MPR Modified Privileges Required. Can be “X”, “N”, “L”, or “H”. Default is “X”.
MUI Modified User Interaction. Can be “X”, “N”, or “R”. Default is “X”.
MS Modified Scope. Can be “X”, “U”, or “C”. Default is “X”.
MC Modified Confidentiality. Can be “X”, “N”, “L”, or “H”. Default is “X”.
MI Modified Integrity. Can be “X”, “N”, “L”, or “H”. Default is “X”.
MA Modified Availability. Can be “X”, “N”, “L”, or “H”. Default is “X”.

Outputs


Path Description Type
CVSS.VectorString Text notation of the score. string
CVSS.ImpactSubScore Impact sub-score. number
CVSS.Impact Impact Score. number
CVSS.Exploitability Exploitability score. number
CVSS.BaseScore Base score. number
CVSS.TemporalScore Temporal score. number
CVSS.ModifiedImpactSubScore Modified impact sub-score. number
CVSS.ModifiedImpact Modified impact. number
CVSS.ModifiedExploitability Modified exploitability score. number
CVSS.EnvironmentalScore Environmental score. number
CVSS.Version Version of CVSS used in the calculation. number