diff --git a/requirements.txt b/requirements.txt index 7ec6baa1..bfb0d49d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,8 @@ mkdocstrings mkdocstrings-python mkdocs-print-site-plugin dataclasses-json +thefuzz==0.20.0 pandas~=2.1.2 scikit-learn~=1.3.2 jsonschema~=4.19.2 -networkx~=3.1 \ No newline at end of file +networkx~=3.1 diff --git a/src/analyze_csv.py b/src/analyze_csv.py deleted file mode 100644 index 21c22a5a..00000000 --- a/src/analyze_csv.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python -""" -This module provides a script for analyzing an SSVC tree csv file. - -```shell -usage: analyze_csv.py [-h] [--outcol OUTCOL] [--permutation] csvfile - -Analyze an SSVC tree csv file - -positional arguments: - csvfile the csv file to analyze - -options: - -h, --help show this help message and exit - --outcol OUTCOL the name of the outcome column - --permutation use permutation importance instead of drop column importance -``` - -Example: - Given a `test.csv` file like this: - ```csv - row,Exploitation,Exposure,Automatable,Human Impact,Priority - 1,none,small,no,low,defer - 2,none,small,no,medium,defer - 3,none,small,no,high,scheduled - ... - ``` - Analyze the csv file: - ```shell - $ python analyze_csv.py test.csv - - Feature Importance after Dropping Each Feature in test.csv - feature feature_importance - 0 exploitation_ 0.347222 - 1 human_impact_ 0.291667 - 2 automatable_ 0.180556 - 3 exposure_ 0.166667 - ``` - - Higher values imply more important features. - """ - -import argparse -import sys - -import pandas as pd -import re -from sklearn.tree import DecisionTreeClassifier -import sklearn.inspection -from sklearn.base import clone - - -def _col_norm(c: str) -> str: - """ - Normalize a column name - - Args: - c: the column name to normalize - - Returns: - the normalized column name - """ - new_col = re.sub("[^0-9a-zA-Z]+", "_", c) - new_col = new_col.lower() - return new_col - - -def _imp_df(column_names: list, importances: list) -> pd.DataFrame: - """ - Create a dataframe of feature importances - - Args: - column_names: the names of the columns - importances: the feature importances - - Returns: - a dataframe of feature importances - """ - df = ( - pd.DataFrame({"feature": column_names, "feature_importance": importances}) - .sort_values("feature_importance", ascending=False) - .reset_index(drop=True) - ) - return df - - -def _drop_col_feat_imp( - model: DecisionTreeClassifier, - X_train: pd.DataFrame, - y_train: pd.DataFrame, - random_state: int = 99, -) -> pd.DataFrame: - # based on https://gist.github.com/erykml/6854134220276b1a50862aa486a44192#file-drop_col_feat_imp-py - # clone the model to have the exact same specification as the one initially trained - model_clone = clone(model) - # set random_state for comparability - model_clone.random_state = random_state - # training and scoring the benchmark model - model_clone.fit(X_train, y_train) - benchmark_score = model_clone.score(X_train, y_train) - # list for storing feature importances - importances = [] - - # iterating over all columns and storing feature importance (difference between benchmark and new model) - for col in X_train.columns: - model_clone = clone(model) - model_clone.random_state = random_state - model_clone.fit(X_train.drop(col, axis=1), y_train) - drop_col_score = model_clone.score(X_train.drop(col, axis=1), y_train) - importances.append(benchmark_score - drop_col_score) - - importances_df = _imp_df(X_train.columns, importances) - return importances_df - - -def _split_data(df: pd.DataFrame, target: str) -> (pd.DataFrame, pd.DataFrame): - """ - Split a dataframe into features and target - - Args: - df: the dataframe to split - target: the name of the target column - - Returns: - a tuple of (features, target) - """ - - # construct feature list - features = [c for c in df.columns if c != target] - y = df[target] - X = df[features] - return X, y - - -def _clean_table(df: pd.DataFrame) -> pd.DataFrame: - """ - Clean up a dataframe, normalizing column names and dropping columns we don't need - - Args: - df: the dataframe to clean - - Returns: - the cleaned dataframe - """ - # normalize data - df = df.rename(columns=_col_norm) - # drop columns we don't need - drop_cols = [ - "row", - ] - df = df.drop(columns=drop_cols, errors="ignore") - return df - - -def _perm_feat_imp(model, x, y): - model.random_state = 99 - model.fit(x, y) - # analyze tree - results = sklearn.inspection.permutation_importance(model, x, y) - imp = results["importances_mean"] - - imp = _imp_df(x.columns, imp) - return imp - - -def _parse_args(args) -> argparse.Namespace: - # parse command line - parser = argparse.ArgumentParser(description="Analyze an SSVC tree csv file") - parser.add_argument( - "csvfile", metavar="csvfile", type=str, help="the csv file to analyze" - ) - parser.add_argument( - "--outcol", - dest="outcol", - type=str, - help="the name of the outcome column", - default="priority", - ) - # use permutation or drop column importance? - # default is drop column - parser.add_argument( - "--permutation", - dest="permutation", - action="store_true", - help="use permutation importance instead of drop column importance", - default=False, - ) - return parser.parse_args(args) - - -def main(): - args = _parse_args(sys.argv[1:]) - - # read csv - df = pd.read_csv(args.csvfile) - df = _clean_table(df) - - # check for target column - target = args.outcol - if target not in df.columns: - print( - f"Column '{target}' not found in {list(df.columns)}.\nPlease specify --outcol= and try again." - ) - exit(1) - - X, y = _split_data(df, target) - - # turn features into ordinals - # this assumes that every column is an ordinal label - # and that the ordinals are sorted in ascending order - cols = [] - for c in X.columns: - newcol = f"{c}_" - cols.append(newcol) - codes = list(enumerate(X[c].unique())) - mapper = {v: k for (k, v) in codes} - X[newcol] = X[c].replace(mapper) - X2 = X[cols] - - # construct tree - dt = DecisionTreeClassifier(random_state=99, criterion="entropy") - - if args.permutation: - imp = _perm_feat_imp(dt, X2, y) - print(f"Feature Permutation Importance for {args.csvfile}") - else: - # drop columns and re-run - imp = _drop_col_feat_imp(dt, X2, y) - print(f"Drop Column Feature Importance for {args.csvfile}") - - print(imp) - - -if __name__ == "__main__": - main() diff --git a/src/ssvc/__init__.py b/src/ssvc/__init__.py index 03989558..87d6fd03 100644 --- a/src/ssvc/__init__.py +++ b/src/ssvc/__init__.py @@ -1,14 +1,15 @@ -#!/usr/bin/env python -''' -file: __init__.py -author: adh -created_at: 9/20/23 10:36 AM -''' - - -def main(): - pass - - -if __name__ == '__main__': - main() +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University +""" +Provides SSVC modules. +""" diff --git a/src/ssvc/decision_points/base.py b/src/ssvc/decision_points/base.py index 5c7de2ce..3e1d32ba 100644 --- a/src/ssvc/decision_points/base.py +++ b/src/ssvc/decision_points/base.py @@ -23,14 +23,41 @@ from dataclasses_json import dataclass_json -from ssvc._mixins import _Base, _Commented, _Keyed, _Namespaced, _Versioned +from ssvc._mixins import _Base, _Keyed, _Namespaced, _Versioned logger = logging.getLogger(__name__) +_RDP = {} REGISTERED_DECISION_POINTS = [] +def register(dp): + """ + Register a decision point. + """ + global _RDP + + key = (dp.namespace, dp.name, dp.key, dp.version) + + if key in _RDP: + logger.warning(f"Duplicate decision point {key}") + + _RDP[key] = dp + REGISTERED_DECISION_POINTS.append(dp) + + +def _reset_registered(): + """ + Reset the registered decision points. + """ + global _RDP + global REGISTERED_DECISION_POINTS + + _RDP = {} + REGISTERED_DECISION_POINTS = [] + + @dataclass_json @dataclass(kw_only=True) class SsvcDecisionPointValue(_Base, _Keyed): @@ -38,8 +65,6 @@ class SsvcDecisionPointValue(_Base, _Keyed): Models a single value option for a decision point. """ - pass - @dataclass_json @dataclass(kw_only=True) @@ -62,9 +87,7 @@ def __iter__(self): return iter(self.values) def __post_init__(self): - global REGISTERED_DECISION_POINTS - - REGISTERED_DECISION_POINTS.append(self) + register(self) if isinstance(self.values[0], dict): self.values = tuple( diff --git a/src/ssvc/decision_points/cvss/__init__.py b/src/ssvc/decision_points/cvss/__init__.py index afae4312..a9bc6dd9 100644 --- a/src/ssvc/decision_points/cvss/__init__.py +++ b/src/ssvc/decision_points/cvss/__init__.py @@ -1,14 +1,16 @@ -#!/usr/bin/env python +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + """ -file: __init__.py -author: adh -created_at: 9/20/23 12:39 PM +Provides SSVC decision points modeling CVSS metrics. """ - - -def main(): - pass - - -if __name__ == "__main__": - main() diff --git a/src/ssvc/decision_points/cvss/_not_defined.py b/src/ssvc/decision_points/cvss/_not_defined.py new file mode 100644 index 00000000..96ff8f22 --- /dev/null +++ b/src/ssvc/decision_points/cvss/_not_defined.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +""" +Provides a generic Not Define decision point value for CVSS decision points. +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue + + +NOT_DEFINED_ND = SsvcDecisionPointValue( + name="Not Defined", + key="ND", + description="This metric value is not defined. See CVSS documentation for details.", +) + +NOT_DEFINED_X = SsvcDecisionPointValue( + name="Not Defined", + key="X", + description="This metric value is not defined. See CVSS documentation for details.", +) diff --git a/src/ssvc/decision_points/cvss/attack_complexity.py b/src/ssvc/decision_points/cvss/attack_complexity.py index 42cce10e..b679d524 100644 --- a/src/ssvc/decision_points/cvss/attack_complexity.py +++ b/src/ssvc/decision_points/cvss/attack_complexity.py @@ -17,6 +17,7 @@ from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _HIGH_3 = SsvcDecisionPointValue( name="High", @@ -99,11 +100,49 @@ Defines LOW and HIGH values for CVSS Attack Complexity. """ +LOW_4 = SsvcDecisionPointValue( + name="Low", + key="L", + description="The attacker must take no measurable action to exploit the vulnerability. The attack requires no " + "target-specific circumvention to exploit the vulnerability. An attacker can expect repeatable " + "success against the vulnerable system. ", +) + +HIGH_4 = SsvcDecisionPointValue( + name="High", + key="H", + description="The successful attack depends on the evasion or circumvention of security-enhancing " + "techniques in place that would otherwise hinder the attack. These include: Evasion of exploit " + "mitigation techniques. The attacker must have additional methods available to bypass security " + "measures in place.", +) + +ATTACK_COMPLEXITY_3_0_1 = CvssDecisionPoint( + name="Attack Complexity", + description="This metric captures measurable actions that must be taken by the attacker to actively evade or " + "circumvent existing built-in security-enhancing conditions in order to obtain a working exploit. ", + key="AC", + version="3.0.1", + values=( + LOW_4, + HIGH_4, + ), +) +""" +Defines LOW and HIGH values for CVSS Attack Complexity. +""" + + +versions = [ + ACCESS_COMPLEXITY_1, + ACCESS_COMPLEXITY_2, + ATTACK_COMPLEXITY_3, + ATTACK_COMPLEXITY_3_0_1, +] + def main(): - print(ACCESS_COMPLEXITY_1.to_json(indent=2)) - print(ACCESS_COMPLEXITY_2.to_json(indent=2)) - print(ATTACK_COMPLEXITY_3.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/attack_requirements.py b/src/ssvc/decision_points/cvss/attack_requirements.py new file mode 100644 index 00000000..fd2348bd --- /dev/null +++ b/src/ssvc/decision_points/cvss/attack_requirements.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +""" +CVSS Attack Requirements +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + +_AT_NONE = SsvcDecisionPointValue( + name="None", + key="N", + description="The successful attack does not depend on the deployment and execution conditions of the vulnerable " + "system. The attacker can expect to be able to reach the vulnerability and execute the exploit under all or " + "most instances of the vulnerability.", +) + + +_PRESENT = SsvcDecisionPointValue( + name="Present", + key="P", + description="The successful attack depends on the presence of specific deployment and execution conditions of " + "the vulnerable system that enable the attack.", +) + +ATTACK_REQUIREMENTS_1 = CvssDecisionPoint( + name="Attack Requirements", + key="AT", + version="1.0.0", + description="This metric captures the prerequisite deployment and execution conditions or variables of the " + "vulnerable system that enable the attack.", + values=( + _AT_NONE, + _PRESENT, + ), +) + +versions = [ + ATTACK_REQUIREMENTS_1, +] + + +def main(): + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/attack_vector.py b/src/ssvc/decision_points/cvss/attack_vector.py index f9c22a46..fba9ac29 100644 --- a/src/ssvc/decision_points/cvss/attack_vector.py +++ b/src/ssvc/decision_points/cvss/attack_vector.py @@ -17,6 +17,7 @@ from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _REMOTE = SsvcDecisionPointValue( name="Remote", @@ -50,25 +51,21 @@ key="N", description="A vulnerability exploitable with network access means the vulnerable software is bound to the " "network stack and the attacker does not require local network access or local access. Such a " - "vulnerability is often termed 'remotely exploitable'. An example of a network attack is an RPC " - "buffer overflow.", + "vulnerability is often termed 'remotely exploitable'.", ) _ADJACENT = SsvcDecisionPointValue( name="Adjacent Network", key="A", description="A vulnerability exploitable with adjacent network access requires the attacker to have access to " - "either the broadcast or collision domain of the vulnerable software. Examples of local networks " - "include local IP subnet, Bluetooth, IEEE 802.11, and local Ethernet segment.", + "either the broadcast or collision domain of the vulnerable software.", ) _LOCAL_2 = SsvcDecisionPointValue( name="Local", key="L", description="A vulnerability exploitable with only local access requires the attacker to have either physical " - "access to the vulnerable system or a local (shell) account. Examples of locally exploitable " - "vulnerabilities are peripheral attacks such as Firewire/USB DMA attacks, and local privilege " - "escalations (e.g., sudo).", + "access to the vulnerable system or a local (shell) account.", ) @@ -120,9 +117,7 @@ key="P", description="A vulnerability exploitable with Physical access requires the attacker to physically touch or " "manipulate the vulnerable component. Physical interaction may be brief (e.g. evil maid attack [1]) " - "or persistent. An example of such an attack is a cold boot attack which allows an attacker to access " - "to disk encryption keys after gaining physical access to the system, or peripheral attacks such as " - "Firewire/USB Direct Memory Access attacks.", + "or persistent.", ) ATTACK_VECTOR_3 = CvssDecisionPoint( @@ -142,10 +137,68 @@ """ +# CVSS v4 Attack Vector +_NETWORK_3 = SsvcDecisionPointValue( + name="Network", + key="N", + description="The vulnerable system is bound to the network stack and the set of possible attackers extends beyond " + "the other options listed below, up to and including the entire Internet. Such a vulnerability is " + "often termed “remotely exploitable” and can be thought of as an attack being exploitable at the " + "protocol level one or more network hops away (e.g., across one or more routers).", +) + +_ADJACENT_3 = SsvcDecisionPointValue( + name="Adjacent", + key="A", + description="The vulnerable system is bound to a protocol stack, but the attack is limited at the protocol level " + "to a logically adjacent topology. This can mean an attack must be launched from the same shared " + "proximity (e.g., Bluetooth, NFC, or IEEE 802.11) or logical network (e.g., local IP subnet), or from " + "within a secure or otherwise limited administrative domain (e.g., MPLS, secure VPN within an " + "administrative network zone).", +) + +_LOCAL_4 = SsvcDecisionPointValue( + name="Local", + key="L", + description="The vulnerable system is not bound to the network stack and the attacker’s path is via " + "read/write/execute capabilities. Either: the attacker exploits the vulnerability by accessing the " + "target system locally (e.g., keyboard, console), or through terminal emulation (e.g., SSH); or the " + "attacker relies on User Interaction by another person to perform actions required to exploit the " + "vulnerability (e.g., using social engineering techniques to trick a legitimate user into opening a " + "malicious document).", +) + +_PHYSICAL_3 = SsvcDecisionPointValue( + name="Physical", + key="P", + description="The attack requires the attacker to physically touch or manipulate the vulnerable system. Physical " + "interaction may be brief (e.g., evil maid attack1) or persistent.", +) + +# updates descriptions of NETWORK, ADJACENT, LOCAL, and PHYSICAL values for CVSS Attack Vector +ATTACK_VECTOR_3_0_1 = CvssDecisionPoint( + name="Attack Vector", + description="This metric reflects the context by which vulnerability exploitation is possible. This metric value " + "(and consequently the resulting severity) will be larger the more remote (logically, and physically) " + "an attacker can be in order to exploit the vulnerable system. The assumption is that the number of " + "potential attackers for a vulnerability that could be exploited from across a network is larger than " + "the number of potential attackers that could exploit a vulnerability requiring physical access to a " + "device, and therefore warrants a greater severity.", + key="AV", + version="3.0.1", + values=( + _PHYSICAL_3, + _LOCAL_4, + _ADJACENT_3, + _NETWORK_3, + ), +) + +versions = [ACCESS_VECTOR_1, ACCESS_VECTOR_2, ATTACK_VECTOR_3, ATTACK_VECTOR_3_0_1] + + def main(): - print(ACCESS_VECTOR_1.to_json(indent=2)) - print(ACCESS_VECTOR_2.to_json(indent=2)) - print(ATTACK_VECTOR_3.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/authentication.py b/src/ssvc/decision_points/cvss/authentication.py index 3f269ad5..d4fa7fd7 100644 --- a/src/ssvc/decision_points/cvss/authentication.py +++ b/src/ssvc/decision_points/cvss/authentication.py @@ -3,8 +3,22 @@ Models the CVSS Authentication metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _AUTH_NONE = SsvcDecisionPointValue( name="None", @@ -66,9 +80,14 @@ """ +versions = [ + AUTHENTICATION_1, + AUTHENTICATION_2, +] + + def main(): - print(AUTHENTICATION_1.to_json(indent=2)) - print(AUTHENTICATION_2.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/availability_impact.py b/src/ssvc/decision_points/cvss/availability_impact.py index 7f7f7441..3312b80c 100644 --- a/src/ssvc/decision_points/cvss/availability_impact.py +++ b/src/ssvc/decision_points/cvss/availability_impact.py @@ -3,13 +3,29 @@ Models the CVSS Availability Impact metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _HIGH = SsvcDecisionPointValue( name="High", key="H", - description="There is total loss of availability, resulting in the attacker being able to fully deny access to resources in the impacted component; this loss is either sustained (while the attacker continues to deliver the attack) or persistent (the condition persists even after the attack has completed).", + description="There is total loss of availability, resulting in the attacker being able to fully deny access to " + "resources in the impacted component; this loss is either sustained (while the attacker continues to " + "deliver the attack) or persistent (the condition persists even after the attack has completed).", ) _LOW = SsvcDecisionPointValue( @@ -33,7 +49,9 @@ _PARTIAL = SsvcDecisionPointValue( name="Partial", key="P", - description="Considerable lag in or interruptions in resource availability. For example, a network-based flood attack that reduces available bandwidth to a web server farm to such an extent that only a small number of connections successfully complete.", + description="Considerable lag in or interruptions in resource availability. For example, a network-based flood " + "attack that reduces available bandwidth to a web server farm to such an extent that only a small " + "number of connections successfully complete.", ) _NONE_1 = SsvcDecisionPointValue( @@ -42,7 +60,8 @@ AVAILABILITY_IMPACT_1 = CvssDecisionPoint( name="Availability Impact", - description="This metric measures the impact on availability a successful exploit of the vulnerability will have on the target system.", + description="This metric measures the impact on availability a successful exploit of the vulnerability will have " + "on the target system.", key="A", version="1.0.0", values=( @@ -70,10 +89,49 @@ Updates None. Removes Partial and Complete. Adds Low and High values for CVSS Availability Impact. """ +_HIGH_2 = SsvcDecisionPointValue( + name="High", + key="H", + description="There is total loss of availability, resulting in the attacker being able to fully deny access to " + "resources in the impacted component; this loss is either sustained (while the attacker continues to " + "deliver the attack) or persistent (the condition persists even after the attack has completed).", +) + +_LOW_2 = SsvcDecisionPointValue( + name="Low", + key="L", + description="There is reduced performance or interruptions in resource availability. Even if repeated " + "exploitation of the vulnerability is possible, the attacker does not have the ability to completely " + "deny service to legitimate users. The resources in the Vulnerable System are either partially " + "available all of the time, or fully available only some of the time, but overall there is no direct, " + "serious consequence to the Vulnerable System.", +) + +_NONE_3 = SsvcDecisionPointValue( + name="None", + key="N", + description="There is no impact to availability within the Vulnerable System.", +) + + +AVAILABILITY_IMPACT_2_0_1 = CvssDecisionPoint( + name="Availability Impact", + description="This metric measures the impact to the availability of the impacted system resulting from a " + "successfully exploited vulnerability.", + key="A", + version="2.0.1", + values=( + _NONE_3, + _LOW_2, + _HIGH_2, + ), +) + +versions = [AVAILABILITY_IMPACT_1, AVAILABILITY_IMPACT_2, AVAILABILITY_IMPACT_2_0_1] + def main(): - print(AVAILABILITY_IMPACT_1.to_json(indent=2)) - print(AVAILABILITY_IMPACT_2.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/availability_requirement.py b/src/ssvc/decision_points/cvss/availability_requirement.py index 8d2b2e30..0e84929b 100644 --- a/src/ssvc/decision_points/cvss/availability_requirement.py +++ b/src/ssvc/decision_points/cvss/availability_requirement.py @@ -3,53 +3,121 @@ Models the CVSS Availability Requirement metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_ND, NOT_DEFINED_X from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs -_NOT_DEFINED = SsvcDecisionPointValue( - name="Not Defined", - key="ND", - description="Assigning this value to the metric will not influence the score. It is a signal to the equation to skip this metric.", -) _HIGH = SsvcDecisionPointValue( name="High", key="H", - description="Loss of availability is likely to have a catastrophic adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of availability is likely to have a catastrophic adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", ) _MEDIUM = SsvcDecisionPointValue( name="Medium", key="M", - description="Loss of availability is likely to have a serious adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of availability is likely to have a serious adverse effect on the organization or individuals " + "associated with the organization (e.g., employees, customers).", ) _LOW = SsvcDecisionPointValue( name="Low", key="L", - description="Loss of availability is likely to have only a limited adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of availability is likely to have only a limited adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", ) AVAILABILITY_REQUIREMENT_1 = CvssDecisionPoint( name="Availability Requirement", description="This metric measures the impact to the availability of a successfully exploited vulnerability.", - key="CR", + key="AR", version="1.0.0", values=( _LOW, _MEDIUM, _HIGH, - _NOT_DEFINED, + NOT_DEFINED_ND, ), ) """ Defines Low, Medium, High, and Not Defined values for CVSS Availability Requirement. """ +AVAILABILITY_REQUIREMENT_1_1 = CvssDecisionPoint( + name="Availability Requirement", + description="This metric measures the impact to the availability of a successfully exploited vulnerability.", + key="AR", + version="1.1.0", + values=( + _LOW, + _MEDIUM, + _HIGH, + NOT_DEFINED_X, + ), +) + + +_HIGH_2 = SsvcDecisionPointValue( + name="High", + key="H", + description="Loss of availability is likely to have a catastrophic adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +_MEDIUM_2 = SsvcDecisionPointValue( + name="Medium", + key="M", + description="Loss of availability is likely to have a serious adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +_LOW_2 = SsvcDecisionPointValue( + name="Low", + key="L", + description="Loss of availability is likely to have only a limited adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +AVAILABILITY_REQUIREMENT_1_1_1 = CvssDecisionPoint( + name="Availability Requirement", + description="This metric enables the consumer to customize the assessment depending on the importance of the " + "affected IT asset to the analyst’s organization, measured in terms of Availability.", + key="AR", + version="1.1.1", + values=( + _LOW_2, + _MEDIUM_2, + _HIGH_2, + NOT_DEFINED_X, + ), +) + +versions = [ + AVAILABILITY_REQUIREMENT_1, + AVAILABILITY_REQUIREMENT_1_1, + AVAILABILITY_REQUIREMENT_1_1_1, +] + def main(): - print(AVAILABILITY_REQUIREMENT_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/base.py b/src/ssvc/decision_points/cvss/base.py index a993e7e1..78aaf15f 100644 --- a/src/ssvc/decision_points/cvss/base.py +++ b/src/ssvc/decision_points/cvss/base.py @@ -4,6 +4,19 @@ """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from dataclasses import dataclass from dataclasses_json import dataclass_json diff --git a/src/ssvc/decision_points/cvss/collateral_damage_potential.py b/src/ssvc/decision_points/cvss/collateral_damage_potential.py index 01c7594d..5d309fbe 100644 --- a/src/ssvc/decision_points/cvss/collateral_damage_potential.py +++ b/src/ssvc/decision_points/cvss/collateral_damage_potential.py @@ -3,14 +3,24 @@ Models the CVSS Collateral Damage Potential metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_ND from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs -_NOT_DEFINED = SsvcDecisionPointValue( - name="Not Defined", - key="ND", - description="Assigning this value to the metric will not influence the score. It is a signal to the equation to skip this metric.", -) _MEDIUM_HIGH = SsvcDecisionPointValue( name="Medium-High", @@ -81,17 +91,18 @@ _LOW_MEDIUM, _MEDIUM_HIGH, _HIGH, - _NOT_DEFINED, + NOT_DEFINED_ND, ), ) """ Updates None description. Adds Low-Medium, Medium-High, and Not Defined value. """ +versions = [COLLATERAL_DAMAGE_POTENTIAL_1, COLLATERAL_DAMAGE_POTENTIAL_2] + def main(): - print(COLLATERAL_DAMAGE_POTENTIAL_1.to_json(indent=2)) - print(COLLATERAL_DAMAGE_POTENTIAL_2.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/confidentiality_impact.py b/src/ssvc/decision_points/cvss/confidentiality_impact.py index 1172cccc..91e63ac1 100644 --- a/src/ssvc/decision_points/cvss/confidentiality_impact.py +++ b/src/ssvc/decision_points/cvss/confidentiality_impact.py @@ -2,20 +2,39 @@ """ Models the CVSS Confidentiality Impact metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _HIGH = SsvcDecisionPointValue( name="High", key="H", - description="There is total loss of confidentiality, resulting in all resources within the impacted component being divulged to the attacker. Alternatively, access to only some restricted information is obtained, but the disclosed information presents a direct, serious impact. For example, an attacker steals the administrator's password, or private encryption keys of a web server.", + description="There is total loss of confidentiality, resulting in all resources within the impacted component " + "being divulged to the attacker. Alternatively, access to only some restricted information is " + "obtained, but the disclosed information presents a direct, serious impact. For example, an attacker " + "steals the administrator's password, or private encryption keys of a web server.", ) _LOW = SsvcDecisionPointValue( name="Low", key="L", - description="There is some loss of confidentiality. Access to some restricted information is obtained, but the attacker does not have control over what information is obtained, or the amount or kind of loss is constrained. The information disclosure does not cause a direct, serious loss to the impacted component.", + description="There is some loss of confidentiality. Access to some restricted information is obtained, " + "but the attacker does not have control over what information is obtained, or the amount or kind of " + "loss is constrained. The information disclosure does not cause a direct, serious loss to the " + "impacted component.", ) _CI_NONE_2 = SsvcDecisionPointValue( @@ -27,13 +46,17 @@ _COMPLETE = SsvcDecisionPointValue( name="Complete", key="C", - description="A total compromise of critical system information. A complete loss of system protection resulting in all critical system files being revealed. The attacker has sovereign control to read all of the system's data (memory, files, etc).", + description="A total compromise of critical system information. A complete loss of system protection resulting in " + "all critical system files being revealed. The attacker has sovereign control to read all of the " + "system's data (memory, files, etc).", ) _PARTIAL = SsvcDecisionPointValue( name="Partial", key="P", - description="There is considerable informational disclosure. Access to critical system files is possible. There is a loss of important information, but the attacker doesn't have control over what is obtainable or the scope of the loss is constrained.", + description="There is considerable informational disclosure. Access to critical system files is possible. There " + "is a loss of important information, but the attacker doesn't have control over what is obtainable or " + "the scope of the loss is constrained.", ) _CI_NONE = SsvcDecisionPointValue( @@ -44,7 +67,8 @@ CONFIDENTIALITY_IMPACT_1 = CvssDecisionPoint( name="Confidentiality Impact", - description="This metric measures the impact on confidentiality of a successful exploit of the vulnerability on the target system.", + description="This metric measures the impact on confidentiality of a successful exploit of the vulnerability on " + "the target system.", key="C", version="1.0.0", values=( @@ -59,7 +83,8 @@ CONFIDENTIALITY_IMPACT_2 = CvssDecisionPoint( name="Confidentiality Impact", - description="This metric measures the impact to the confidentiality of the information resources managed by a software component due to a successfully exploited vulnerability.", + description="This metric measures the impact to the confidentiality of the information resources managed by a " + "software component due to a successfully exploited vulnerability.", key="C", version="2.0.0", values=( @@ -73,9 +98,55 @@ """ +_HIGH_1 = SsvcDecisionPointValue( + name="High", + key="H", + description="There is total loss of confidentiality, resulting in all resources within the impacted component " + "being divulged to the attacker. Alternatively, access to only some restricted information is " + "obtained, but the disclosed information presents a direct, serious impact. For example, an attacker " + "steals the administrator's password, or private encryption keys of a web server.", +) + +_LOW_1 = SsvcDecisionPointValue( + name="Low", + key="L", + description="There is some loss of confidentiality. Access to some restricted information is obtained, " + "but the attacker does not have control over what information is obtained, or the amount or kind of " + "loss is constrained. The information disclosure does not cause a direct, serious loss to the " + "impacted component.", +) + +_CI_NONE_3 = SsvcDecisionPointValue( + name="None", + key="N", + description="There is no loss of confidentiality within the impacted component.", +) + +CONFIDENTIALITY_IMPACT_2_0_1 = CvssDecisionPoint( + name="Confidentiality Impact", + description="This metric measures the impact to the confidentiality of the information managed by the system due " + "to a successfully exploited vulnerability. Confidentiality refers to limiting information access " + "and disclosure to only authorized users, as well as preventing access by, or disclosure to, " + "unauthorized ones.", + key="C", + version="2.0.1", + values=( + _CI_NONE_3, + _LOW_1, + _HIGH_1, + ), +) + + +versions = [ + CONFIDENTIALITY_IMPACT_1, + CONFIDENTIALITY_IMPACT_2, + CONFIDENTIALITY_IMPACT_2_0_1, +] + + def main(): - print(CONFIDENTIALITY_IMPACT_1.to_json(indent=2)) - print(CONFIDENTIALITY_IMPACT_2.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/confidentiality_requirement.py b/src/ssvc/decision_points/cvss/confidentiality_requirement.py index 26e878fc..427cf6b3 100644 --- a/src/ssvc/decision_points/cvss/confidentiality_requirement.py +++ b/src/ssvc/decision_points/cvss/confidentiality_requirement.py @@ -3,31 +3,43 @@ Models the CVSS Confidentiality Requirement metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_ND, NOT_DEFINED_X from ssvc.decision_points.cvss.base import CvssDecisionPoint - -_NOT_DEFINED = SsvcDecisionPointValue( - name="Not Defined", - key="ND", - description="Assigning this value to the metric will not influence the score. It is a signal to the equation to skip this metric.", -) +from ssvc.decision_points.helpers import print_versions_and_diffs _HIGH = SsvcDecisionPointValue( name="High", key="H", - description="Loss of confidentiality is likely to have a catastrophic adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of confidentiality is likely to have a catastrophic adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", ) _MEDIUM = SsvcDecisionPointValue( name="Medium", key="M", - description="Loss of confidentiality is likely to have a serious adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of confidentiality is likely to have a serious adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", ) _LOW = SsvcDecisionPointValue( name="Low", key="L", - description="Loss of confidentiality is likely to have only a limited adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of confidentiality is likely to have only a limited adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", ) CONFIDENTIALITY_REQUIREMENT_1 = CvssDecisionPoint( @@ -39,16 +51,71 @@ _LOW, _MEDIUM, _HIGH, - _NOT_DEFINED, + NOT_DEFINED_ND, ), ) """ Defines Low, Medium, High, and Not Defined values for CVSS Confidentiality Requirement. """ +CONFIDENTIALITY_REQUIREMENT_1_1 = CvssDecisionPoint( + name="Confidentiality Requirement", + description="This metric measures the impact to the confidentiality of a successfully exploited vulnerability.", + key="CR", + version="1.1.0", + values=( + _LOW, + _MEDIUM, + _HIGH, + NOT_DEFINED_X, + ), +) + + +_HIGH_2 = SsvcDecisionPointValue( + name="High", + key="H", + description="Loss of confidentiality is likely to have a catastrophic adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +_MEDIUM_2 = SsvcDecisionPointValue( + name="Medium", + key="M", + description="Loss of confidentiality is likely to have a serious adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +_LOW_2 = SsvcDecisionPointValue( + name="Low", + key="L", + description="Loss of confidentiality is likely to have only a limited adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +CONFIDENTIALITY_REQUIREMENT_1_1_1 = CvssDecisionPoint( + name="Confidentiality Requirement", + description="This metric enables the consumer to customize the assessment depending on the importance of the " + "affected IT asset to the analyst’s organization, measured in terms of Confidentiality.", + key="CR", + version="1.1.1", + values=( + _LOW_2, + _MEDIUM_2, + _HIGH_2, + NOT_DEFINED_X, + ), +) + +versions = [ + CONFIDENTIALITY_REQUIREMENT_1, + CONFIDENTIALITY_REQUIREMENT_1_1, + CONFIDENTIALITY_REQUIREMENT_1_1_1, +] + def main(): - print(CONFIDENTIALITY_REQUIREMENT_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/eq_sets.py b/src/ssvc/decision_points/cvss/eq_sets.py new file mode 100644 index 00000000..aca56dde --- /dev/null +++ b/src/ssvc/decision_points/cvss/eq_sets.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python +""" +CVSS v4 Equivalence Sets +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss.base import CvssDecisionPoint + + +# EQ1 → AV/PR/UI with 3 levels specified in Table 24 +# Levels Constraints Highest Severity Vector(s) +# 0 AV:N and PR:N and UI:N AV:N/PR:N/UI:N +# 1 (AV:N or PR:N or UI:N) and not (AV:N and PR:N and UI:N) and not AV:P AV:A/PR:N/UI:N or AV:N/PR:L/UI:N or AV:N/PR:N:/UI:P +# 2 AV:P or not(AV:N or PR:N or UI:N) AV:P/PR:N/UI:N or AV:A/PR:L/UI:P +EQ1 = CvssDecisionPoint( + name="Equivalence Set 1", + key="EQ1", + description="AV/PR/UI with 3 levels specified in Table 24", + version="1.0.0", + values=[ + SsvcDecisionPointValue( + name="Low", + key="L", + description="2: AV:P or not(AV:N or PR:N or UI:N)", + ), + SsvcDecisionPointValue( + name="Medium", + key="M", + description="1: (AV:N or PR:N or UI:N) and not (AV:N and PR:N and UI:N) and not AV:P", + ), + SsvcDecisionPointValue( + name="High", + key="H", + description="0: AV:N and PR:N and UI:N", + ), + ], +) + +# EQ2 → AC/AT with 2 levels specified in Table 25 +# Levels Constraints Highest Severity Vector(s) +# 0 AC:L and AT:N AC:L/AT:N +# 1 not (AC:L and AT:N) AC:L/AT:P or AC:H/AT:N +EQ2 = CvssDecisionPoint( + name="Equivalence Set 2", + key="EQ2", + description="AC/AT with 2 levels specified in Table 25", + version="1.0.0", + values=[ + SsvcDecisionPointValue( + name="Low", + key="L", + description="1: not (AC:L and AT:N)", + ), + SsvcDecisionPointValue( + name="High", + key="H", + description="0: AC:L and AT:N", + ), + ], +) + + +# EQ3 → VC/VI/VA with 3 levels specified in Table 26 +# Levels Constraints Highest Severity Vector(s) +# 0 VC:H and VI:H VC:H/VI:H/VA:H +# 1 not (VC:H and VI:H) and (VC:H or VI:H or VA:H) VC:L/VI:H/VA:H or VC:H/VI:L/VA:H +# 2 not (VC:H or VI:H or VA:H) VC:L/VI:L/VA:L +EQ3 = CvssDecisionPoint( + name="Equivalence Set 3", + key="EQ3", + description="VC/VI/VA with 3 levels specified in Table 26", + version="1.0.0", + values=[ + SsvcDecisionPointValue( + name="Low", + key="L", + description="2: not (VC:H or VI:H or VA:H)", + ), + SsvcDecisionPointValue( + name="Medium", + key="M", + description="1: not (VC:H and VI:H) and (VC:H or VI:H or VA:H)", + ), + SsvcDecisionPointValue( + name="High", + key="H", + description="0: VC:H and VI:H", + ), + ], +) + + +# EQ4 → SC/SI/SA with 3 levels specified in Table 27 +# 0 MSI:S or MSA:S SC:H/SI:S/SA:S +# 1 not (MSI:S or MSA:S) and (SC:H or SI:H or SA:H) SC:H/SI:H/SA:H +# 2 not (MSI:S or MSA:S) and not (SC:H or SI:H or SA:H) SC:L/SI:L/SA:L +EQ4 = CvssDecisionPoint( + name="Equivalence Set 4", + key="EQ4", + description="SC/SI/SA with 3 levels specified in Table 27", + version="1.0.0", + values=[ + SsvcDecisionPointValue( + name="Low", + key="L", + description="2: not (MSI:S or MSA:S) and not (SC:H or SI:H or SA:H)", + ), + SsvcDecisionPointValue( + name="Medium", + key="M", + description="1: not (MSI:S or MSA:S) and (SC:H or SI:H or SA:H)", + ), + SsvcDecisionPointValue( + name="High", + key="H", + description="0: MSI:S or MSA:S", + ), + ], +) + + +# EQ5 → E with 3 levels specified in Table 28 +# 0 E:A E:A +# 1 E:P E:P +# 2 E:U E:U +EQ5 = CvssDecisionPoint( + name="Equivalence Set 5", + key="EQ5", + description="E with 3 levels specified in Table 28", + version="1.0.0", + values=[ + SsvcDecisionPointValue( + name="Low", + key="L", + description="2: E:U", + ), + SsvcDecisionPointValue( + name="Medium", + key="M", + description="1: E:P", + ), + SsvcDecisionPointValue( + name="High", + key="H", + description="0: E:A", + ), + ], +) + +# EQ6 → VC/VI/VA+CR/CI/CA with 2 levels specified in Table 29 +# 0 (CR:H and VC:H) or (IR:H and VI:H) or (AR:H and VA:H) VC:H/VI:H/VA:H/CR:H/IR:H/AR:H +# 1 not (CR:H and VC:H) and not (IR:H and VI:H) and not (AR:H and VA:H) VC:H/VI:H/VA:H/CR:M/IR:M/AR:M or VC:H/VI:H/VA:L/CR:M/IR:M/AR:H or VC:H/VI:L/VA:H/CR:M/IR:H/AR:M or VC:H/VI:L/VA:L/CR:M/IR:H/AR:H or VC:L/VI:H/VA:H/CR:H/IR:M/AR:M or VC:L/VI:H/VA:L/CR:H/IR:M/AR:H or VC:L/VI:L/VA:H/CR:H/IR:H/AR:M or VC:L/VI:L/VA:L/CR:H/IR:H/AR:H +EQ6 = CvssDecisionPoint( + name="Equivalence Set 6", + key="EQ6", + description="VC/VI/VA+CR/CI/CA with 2 levels specified in Table 29", + version="1.0.0", + values=[ + SsvcDecisionPointValue( + name="Low", + key="L", + description="1: not (CR:H and VC:H) and not (IR:H and VI:H) and not (AR:H and VA:H)", + ), + SsvcDecisionPointValue( + name="High", + key="H", + description="0: (CR:H and VC:H) or (IR:H and VI:H) or (AR:H and VA:H)", + ), + ], +) + + +def main(): + for dp in [EQ1, EQ2, EQ3, EQ4, EQ5, EQ6]: + print(dp.to_json(indent=2)) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/exploitability.py b/src/ssvc/decision_points/cvss/exploitability.py index 0bf3c661..06815614 100644 --- a/src/ssvc/decision_points/cvss/exploitability.py +++ b/src/ssvc/decision_points/cvss/exploitability.py @@ -3,35 +3,47 @@ Model the CVSS Exploitability and Exploit Code Maturity metrics as SSVC decision points. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_ND, NOT_DEFINED_X from ssvc.decision_points.cvss.base import CvssDecisionPoint - -_NOT_DEFINED_2 = SsvcDecisionPointValue( - name="Not Defined", - key="ND", - description="Assigning this value to the metric will not influence the score. It is a signal to a scoring equation to skip this metric.", -) - -_NOT_DEFINED_1 = SsvcDecisionPointValue( - name="Not Defined", key="ND", description="Not Defined" -) +from ssvc.decision_points.helpers import print_versions_and_diffs _HIGH_2 = SsvcDecisionPointValue( name="High", key="H", - description="Functional autonomous code exists, or no exploit is required (manual trigger) and details are widely available. Exploit code works in every situation, or is actively being delivered via an autonomous agent (such as a worm or virus). Network-connected systems are likely to encounter scanning or exploitation attempts. Exploit development has reached the level of reliable, widely-available, easy-to-use automated tools.", + description="Functional autonomous code exists, or no exploit is required (manual trigger) and details are widely " + "available. Exploit code works in every situation, or is actively being delivered via an autonomous " + "agent (such as a worm or virus). Network-connected systems are likely to encounter scanning or " + "exploitation attempts. Exploit development has reached the level of reliable, widely-available, " + "easy-to-use automated tools.", ) _FUNCTIONAL_2 = SsvcDecisionPointValue( name="Functional", key="F", - description="Functional exploit code is available. The code works in most situations where the vulnerability exists.", + description="Functional exploit code is available. The code works in most situations where the vulnerability " + "exists.", ) _PROOF_OF_CONCEPT_2 = SsvcDecisionPointValue( name="Proof-of-Concept", key="POC", - description="Proof-of-concept exploit code is available, or an attack demonstration is not practical for most systems. The code or technique is not functional in all situations and may require substantial modification by a skilled attacker.", + description="Proof-of-concept exploit code is available, or an attack demonstration is not practical for most " + "systems. The code or technique is not functional in all situations and may require substantial " + "modification by a skilled attacker.", ) _UNPROVEN_2 = SsvcDecisionPointValue( @@ -43,19 +55,25 @@ _HIGH = SsvcDecisionPointValue( name="High", key="H", - description="Either the vulnerability is exploitable by functional mobile autonomous code or no exploit is required (manual trigger) and the details for the manual technique are widely available. The code works in every situation where the vulnerability is exploitable and/or is actively being delivered via a mobile autonomous agent (a worm or virus).", + description="Either the vulnerability is exploitable by functional mobile autonomous code or no exploit is " + "required (manual trigger) and the details for the manual technique are widely available. The code " + "works in every situation where the vulnerability is exploitable and/or is actively being delivered " + "via a mobile autonomous agent (a worm or virus).", ) _FUNCTIONAL = SsvcDecisionPointValue( name="Functional", key="F", - description="Functional exploit code is available. The code works in most situations where the vulnerability is exploitable.", + description="Functional exploit code is available. The code works in most situations where the vulnerability is " + "exploitable.", ) _PROOF_OF_CONCEPT = SsvcDecisionPointValue( name="Proof of Concept", key="P", - description="Proof of concept exploit code or an attack demonstration that is not practically applicable to deployed systems is available. The code or technique is not functional in all situations and may require substantial hand tuning by a skilled attacker for use against deployed systems.", + description="Proof of concept exploit code or an attack demonstration that is not practically applicable to " + "deployed systems is available. The code or technique is not functional in all situations and may " + "require substantial hand tuning by a skilled attacker for use against deployed systems.", ) _UNPROVEN = SsvcDecisionPointValue( @@ -66,7 +84,8 @@ EXPLOITABILITY_1 = CvssDecisionPoint( name="Exploitability", - description="This metric measures the current state of exploit technique or code availability and suggests a likelihood of exploitation.", + description="This metric measures the current state of exploit technique or code availability and suggests a " + "likelihood of exploitation.", key="E", version="1.0.0", values=( @@ -82,7 +101,8 @@ EXPLOITABILITY_1_1 = CvssDecisionPoint( name="Exploitability", - description="This metric measures the current state of exploit technique or code availability and suggests a likelihood of exploitation.", + description="This metric measures the current state of exploit technique or code availability and suggests a " + "likelihood of exploitation.", key="E", version="1.1.0", values=( @@ -90,7 +110,7 @@ _PROOF_OF_CONCEPT, _FUNCTIONAL, _HIGH, - _NOT_DEFINED_1, + NOT_DEFINED_ND, ), ) """ @@ -98,20 +118,18 @@ """ -# TODO is it correct to inherit the version from Exploitability? -# TODO Or is it better for Exploit Code Maturity to reset to 1.0.0? - -EXPLOIT_CODE_MATURITY_1_1_1 = CvssDecisionPoint( +EXPLOIT_CODE_MATURITY_1_2 = CvssDecisionPoint( name="Exploit Code Maturity", - description="measures the likelihood of the vulnerability being attacked, and is typically based on the current state of exploit techniques, exploit code availability, or active, 'in-the-wild' exploitation", + description="measures the likelihood of the vulnerability being attacked, and is typically based on the current " + "state of exploit techniques, exploit code availability, or active, 'in-the-wild' exploitation", key="E", - version="1.1.1", + version="1.2.0", values=( _UNPROVEN_2, _PROOF_OF_CONCEPT_2, _FUNCTIONAL_2, _HIGH_2, - _NOT_DEFINED_2, + NOT_DEFINED_X, ), ) """ @@ -119,10 +137,56 @@ """ +_ATTACKED = SsvcDecisionPointValue( + name="Attacked", + key="A", + description="Based on available threat intelligence either of the following must apply: Attacks targeting " + "this vulnerability (attempted or successful) have been reported Solutions to simplify attempts " + "to exploit the vulnerability are publicly or privately available (such as exploit toolkits)", +) + +_PROOF_OF_CONCEPT_3 = SsvcDecisionPointValue( + name="Proof-of-Concept", + key="P", + description="Based on available threat intelligence each of the following must apply: Proof-of-concept exploit " + "code is publicly available No knowledge of reported attempts to exploit this vulnerability No " + "knowledge of publicly available solutions used to simplify attempts to exploit the vulnerability " + "(i.e., the “Attacked” value does not apply)", +) + +_UNREPORTED = SsvcDecisionPointValue( + name="Unreported", + key="U", + description="Based on available threat intelligence each of the following must apply: No knowledge of publicly " + "available proof-of-concept exploit code No knowledge of reported attempts to exploit this " + "vulnerability No knowledge of publicly available solutions used to simplify attempts to exploit " + "the vulnerability (i.e., neither the “POC” nor “Attacked” values apply)", +) + +EXPLOIT_MATURITY_2 = CvssDecisionPoint( + name="Exploit Maturity", + key="E", + description="This metric measures the likelihood of the vulnerability being attacked, and is based on the current " + "state of exploit techniques, exploit code availability, or active, “in-the-wild” exploitation.", + version="2.0.0", + values=( + _UNREPORTED, + _PROOF_OF_CONCEPT_3, + _ATTACKED, + NOT_DEFINED_X, + ), +) + +versions = [ + EXPLOITABILITY_1, + EXPLOITABILITY_1_1, + EXPLOIT_CODE_MATURITY_1_2, + EXPLOIT_MATURITY_2, +] + + def main(): - print(EXPLOITABILITY_1.to_json(indent=2)) - print(EXPLOITABILITY_1_1.to_json(indent=2)) - print(EXPLOIT_CODE_MATURITY_1_1_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/helpers.py b/src/ssvc/decision_points/cvss/helpers.py new file mode 100644 index 00000000..6e2e4ba9 --- /dev/null +++ b/src/ssvc/decision_points/cvss/helpers.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +""" +Provides helpers for working with CVSS decision points. +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from copy import deepcopy + +from ssvc.decision_points import SsvcDecisionPoint, SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_X + + +def _modify_3(dp: SsvcDecisionPoint): + _dp = deepcopy(dp) + _dp.name = "Modified " + _dp.name + _dp.key = "M" + _dp.key + + # if there is no value named "Not Defined" value, add it + nd = NOT_DEFINED_X + + values = list(_dp.values) + + names = [v.name for v in values] + if nd.name not in names: + values.append(nd) + _dp.values = tuple(values) + + return _dp + + +def modify_3(dp: SsvcDecisionPoint): + """ + Prepends "Modified " to the name and "M" to the key of the given object. Also adds a value of "Not Defined" to the + values list. + Args: + dp: the decision point object to modify + + Returns: + A modified copy of the given object + """ + + _dp = _modify_3(dp) + _dp.__post_init__() # call post-init to update the key & register + return _dp + + +def modify_4(dp: SsvcDecisionPoint): + """ + Modifies a CVSS v4 Base Metric decision point object. + + Args: + dp: the decision point object to modify + + Returns: + A modified copy of the given object + """ + + _dp = _modify_3(dp) + _dp = _modify_4(_dp) + _dp.__post_init__() # call post-init to update the key & register + + return _dp + + +def _modify_4(dp: SsvcDecisionPoint): + # note: + # this method was split out for testing purposes + # assumes you've already done the 3.0 modifications + + _dp = deepcopy(dp) + # Note: For MSC, MSI, and MSA, the lowest metric value is “Negligible” (N), not “None” (N). + if _dp.key in ["MSC", "MSI", "MSA"]: + for v in _dp.values: + if v.key == "N": + v.name = "Negligible" + v.description.replace(" no ", " negligible ") + break + + # Note: For MSI, There is also a highest severity level, Safety (S), in addition to the same values as the + # corresponding Base Metric (High, Medium, Low). + if _dp.key == "MSI": + _SAFETY = SsvcDecisionPointValue( + name="Safety", + key="S", + description="The Safety metric value measures the impact regarding the Safety of a human actor or " + "participant that can be predictably injured as a result of the vulnerability being exploited.", + ) + values = list(_dp.values) + values.append(_SAFETY) + _dp.values = tuple(values) + + return _dp + + +def main(): + pass + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/impact_bias.py b/src/ssvc/decision_points/cvss/impact_bias.py index 7ab5a993..744e3576 100644 --- a/src/ssvc/decision_points/cvss/impact_bias.py +++ b/src/ssvc/decision_points/cvss/impact_bias.py @@ -2,8 +2,22 @@ """ Model the CVSS Impact Bias as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _AVAILABILITY = SsvcDecisionPointValue( name="Availability", @@ -45,9 +59,13 @@ Defines Normal, Confidentiality, Integrity, and Availability values for CVSS Impact Bias. """ +versions = [ + IMPACT_BIAS_1, +] + def main(): - print(IMPACT_BIAS_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/integrity_impact.py b/src/ssvc/decision_points/cvss/integrity_impact.py index 33586f09..1a78dcd3 100644 --- a/src/ssvc/decision_points/cvss/integrity_impact.py +++ b/src/ssvc/decision_points/cvss/integrity_impact.py @@ -3,20 +3,36 @@ Models the CVSS Integrity Impact metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _II_HIGH = SsvcDecisionPointValue( name="High", key="H", - description="There is a total loss of integrity, or a complete loss of protection. For example, the attacker is able to modify any/all files protected by the impacted component. Alternatively, only some files can be modified, but malicious modification would present a direct, serious consequence to the impacted component.", + description="There is a total loss of integrity, or a complete loss of protection.", ) _II_LOW = SsvcDecisionPointValue( name="Low", key="L", - description="Modification of data is possible, but the attacker does not have control over the consequence of a modification, or the amount of modification is constrained. The data modification does not have a direct, serious impact on the impacted component.", + description="Modification of data is possible, but the attacker does not have control over the consequence of a " + "modification, or the amount of modification is constrained. The data modification does not have a " + "direct, serious impact on the impacted component.", ) _II_NONE_2 = SsvcDecisionPointValue( @@ -27,13 +43,17 @@ _COMPLETE = SsvcDecisionPointValue( name="Complete", key="C", - description="A total compromise of system integrity. There is a complete loss of system protection resulting in the entire system being compromised. The attacker has sovereign control to modify any system files.", + description="A total compromise of system integrity. There is a complete loss of system protection resulting in " + "the entire system being compromised. The attacker has sovereign control to modify any system files.", ) _PARTIAL = SsvcDecisionPointValue( name="Partial", key="P", - description="Considerable breach in integrity. Modification of critical system files or information is possible, but the attacker does not have control over what can be modified, or the scope of what the attacker can affect is constrained. For example, key system or program files may be overwritten or modified, but at random or in a limited context or scope.", + description="Considerable breach in integrity. Modification of critical system files or information is possible, " + "but the attacker does not have control over what can be modified, or the scope of what the attacker " + "can affect is constrained. For example, key system or program files may be overwritten or modified, " + "but at random or in a limited context or scope.", ) _II_NONE = SsvcDecisionPointValue( @@ -42,7 +62,8 @@ INTEGRITY_IMPACT_1 = CvssDecisionPoint( name="Integrity Impact", - description="This metric measures the impact on integrity a successful exploit of the vulnerability will have on the target system.", + description="This metric measures the impact on integrity a successful exploit of the vulnerability will have on " + "the target system.", key="I", version="1.0.0", values=( @@ -70,10 +91,45 @@ Updates None. Removes Partial and Complete. Adds Low and High values for CVSS Integrity Impact. """ +_II_HIGH_2 = SsvcDecisionPointValue( + name="High", + key="H", + description="There is a total loss of integrity, or a complete loss of protection.", +) + +_II_LOW_2 = SsvcDecisionPointValue( + name="Low", + key="L", + description="Modification of data is possible, but the attacker does not have control over the consequence of a " + "modification, or the amount of modification is limited. The data modification does not have a direct, " + "serious impact to the Vulnerable System.", +) + + +_II_NONE_3 = SsvcDecisionPointValue( + name="None", + key="N", + description="There is no loss of integrity within the Vulnerable System.", +) + + +INTEGRITY_IMPACT_2_0_1 = CvssDecisionPoint( + name="Integrity Impact", + description="This metric measures the impact to integrity of a successfully exploited vulnerability.", + key="I", + version="2.0.1", + values=( + _II_NONE_3, + _II_LOW_2, + _II_HIGH_2, + ), +) + +versions = [INTEGRITY_IMPACT_1, INTEGRITY_IMPACT_2, INTEGRITY_IMPACT_2_0_1] + def main(): - print(INTEGRITY_IMPACT_1.to_json(indent=2)) - print(INTEGRITY_IMPACT_2.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/integrity_requirement.py b/src/ssvc/decision_points/cvss/integrity_requirement.py index bed51253..a5c5eba5 100644 --- a/src/ssvc/decision_points/cvss/integrity_requirement.py +++ b/src/ssvc/decision_points/cvss/integrity_requirement.py @@ -3,52 +3,119 @@ Models the CVSS Integrity Requirement metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_ND, NOT_DEFINED_X from ssvc.decision_points.cvss.base import CvssDecisionPoint - -_NOT_DEFINED = SsvcDecisionPointValue( - name="Not Defined", - key="ND", - description="Assigning this value to the metric will not influence the score. It is a signal to the equation to skip this metric.", -) +from ssvc.decision_points.helpers import print_versions_and_diffs _HIGH = SsvcDecisionPointValue( name="High", key="H", - description="Loss of integrity is likely to have a catastrophic adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of integrity is likely to have a catastrophic adverse effect on the organization or individuals " + "associated with the organization (e.g., employees, customers).", ) _MEDIUM = SsvcDecisionPointValue( name="Medium", key="M", - description="Loss of integrity is likely to have a serious adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of integrity is likely to have a serious adverse effect on the organization or individuals " + "associated with the organization (e.g., employees, customers).", ) _LOW = SsvcDecisionPointValue( name="Low", key="L", - description="Loss of integrity is likely to have only a limited adverse effect on the organization or individuals associated with the organization (e.g., employees, customers).", + description="Loss of integrity is likely to have only a limited adverse effect on the organization or individuals " + "associated with the organization (e.g., employees, customers).", ) INTEGRITY_REQUIREMENT_1 = CvssDecisionPoint( name="Integrity Requirement", description="This metric measures the impact to the integrity of a successfully exploited vulnerability.", - key="CR", + key="IR", version="1.0.0", values=( _LOW, _MEDIUM, _HIGH, - _NOT_DEFINED, + NOT_DEFINED_ND, ), ) """ Defines Low, Medium, High, and Not Defined values for CVSS Integrity Requirement. """ +INTEGRITY_REQUIREMENT_1_1 = CvssDecisionPoint( + name="Integrity Requirement", + description="This metric measures the impact to the integrity of a successfully exploited vulnerability.", + key="IR", + version="1.1.0", + values=( + _LOW, + _MEDIUM, + _HIGH, + NOT_DEFINED_X, + ), +) + + +_HIGH_2 = SsvcDecisionPointValue( + name="High", + key="H", + description="Loss of integrity is likely to have a catastrophic adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +_MEDIUM_2 = SsvcDecisionPointValue( + name="Medium", + key="M", + description="Loss of integrity is likely to have a serious adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +_LOW_2 = SsvcDecisionPointValue( + name="Low", + key="L", + description="Loss of integrity is likely to have only a limited adverse effect on the organization or " + "individuals associated with the organization (e.g., employees, customers).", +) + +INTEGRITY_REQUIREMENT_1_1_1 = CvssDecisionPoint( + name="Integrity Requirement", + description="This metric enables the consumer to customize the assessment depending on the importance of the " + "affected IT asset to the analyst’s organization, measured in terms of Confidentiality.", + key="IR", + version="1.0.1", + values=( + _LOW_2, + _MEDIUM_2, + _HIGH_2, + NOT_DEFINED_X, + ), +) + +versions = [ + INTEGRITY_REQUIREMENT_1, + INTEGRITY_REQUIREMENT_1_1, + INTEGRITY_REQUIREMENT_1_1_1, +] + def main(): - print(INTEGRITY_REQUIREMENT_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/privileges_required.py b/src/ssvc/decision_points/cvss/privileges_required.py index 8c71f61b..62313e28 100644 --- a/src/ssvc/decision_points/cvss/privileges_required.py +++ b/src/ssvc/decision_points/cvss/privileges_required.py @@ -2,36 +2,59 @@ """ Models the CVSS Privileges Required metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _HIGH = SsvcDecisionPointValue( name="High", key="H", - description="The attacker is authorized with (i.e. requires) privileges that provide significant (e.g. administrative) control over the vulnerable component that could affect component-wide settings and files.", + description="The attacker is authorized with (i.e. requires) privileges that provide significant (e.g. " + "administrative) control over the vulnerable component that could affect component-wide settings and " + "files.", ) _LOW = SsvcDecisionPointValue( name="Low", key="L", - description="The attacker is authorized with (i.e. requires) privileges that provide basic user capabilities that could normally affect only settings and files owned by a user. Alternatively, an attacker with Low privileges may have the ability to cause an impact only to non-sensitive resources.", + description="The attacker is authorized with (i.e. requires) privileges that provide basic user capabilities that " + "could normally affect only settings and files owned by a user. Alternatively, an attacker with Low " + "privileges may have the ability to cause an impact only to non-sensitive resources.", ) _PR_NONE = SsvcDecisionPointValue( name="None", key="N", - description="The attacker is unauthorized prior to attack, and therefore does not require any access to settings or files to carry out an attack.", + description="The attacker is unauthorized prior to attack, and therefore does not require any access to settings " + "or files to carry out an attack.", ) + +# NOTE: values must be listed from "least bad" to "most bad" for sorting to work properly +# therefore High < Low < None PRIVILEGES_REQUIRED_1 = CvssDecisionPoint( name="Privileges Required", - description="This metric describes the level of privileges an attacker must possess before successfully exploiting the vulnerability.", + description="This metric describes the level of privileges an attacker must possess before successfully " + "exploiting the vulnerability.", key="PR", version="1.0.0", values=( - _PR_NONE, - _LOW, _HIGH, + _LOW, + _PR_NONE, ), ) """ @@ -39,8 +62,50 @@ """ +_PR_NONE_2 = SsvcDecisionPointValue( + name="None", + key="N", + description="The attacker is unauthorized prior to attack, and therefore does not require any access to settings " + "or files to carry out an attack.", +) + +_LOW_2 = SsvcDecisionPointValue( + name="Low", + key="L", + description="The attacker is authorized with (i.e., requires) privileges that provide basic capabilities that " + "are typically limited to settings and resources owned by a single low-privileged user. Alternatively, " + "an attacker with Low privileges has the ability to access only non-sensitive resources.", +) + +_HIGH_2 = SsvcDecisionPointValue( + name="High", + key="H", + description="The attacker is authorized with (i.e., requires) privileges that provide significant (e.g., " + "administrative) control over the vulnerable system allowing full access to the vulnerable system’s " + "settings and files.", +) + +PRIVILEGES_REQUIRED_1_0_1 = CvssDecisionPoint( + name="Privileges Required", + description="This metric describes the level of privileges an attacker must possess prior to successfully " + "exploiting the vulnerability. The method by which the attacker obtains privileged credentials " + "prior to the attack (e.g., free trial accounts), is outside the scope of this metric. Generally, " + "self-service provisioned accounts do not constitute a privilege requirement if the attacker can " + "grant themselves privileges as part of the attack.", + key="PR", + version="1.0.1", + values=( + _HIGH_2, + _LOW_2, + _PR_NONE_2, + ), +) + +versions = [PRIVILEGES_REQUIRED_1, PRIVILEGES_REQUIRED_1_0_1] + + def main(): - print(PRIVILEGES_REQUIRED_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/remediation_level.py b/src/ssvc/decision_points/cvss/remediation_level.py index ad3e6b0c..adc7a5a1 100644 --- a/src/ssvc/decision_points/cvss/remediation_level.py +++ b/src/ssvc/decision_points/cvss/remediation_level.py @@ -3,14 +3,24 @@ Models the CVSS Remediation Level metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_X from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs -_NOT_DEFINED = SsvcDecisionPointValue( - name="Not Defined", - key="ND", - description="Assigning this value to the metric will not influence the score. It is a signal to the equation to skip this metric.", -) _UNAVAILABLE = SsvcDecisionPointValue( name="Unavailable", @@ -21,19 +31,24 @@ _WORKAROUND = SsvcDecisionPointValue( name="Workaround", key="W", - description="There is an unofficial, non-vendor solution available. In some cases, users of the affected technology will create a patch of their own or provide steps to work around or otherwise mitigate against the vulnerability. When it is generally accepted that these unofficial fixes are adequate in plugging the hole for the mean time and no official remediation is available, this value can be set.", + description="There is an unofficial, non-vendor solution available. In some cases, users of the affected " + "technology will create a patch of their own or provide steps to work around or otherwise mitigate " + "against the vulnerability. When it is generally accepted that these unofficial fixes are adequate in " + "plugging the hole for the mean time and no official remediation is available, this value can be set.", ) _TEMPORARY_FIX = SsvcDecisionPointValue( name="Temporary Fix", key="TF", - description="There is an official but temporary fix available. This includes instances where the vendor issues a temporary hotfix, tool or official workaround.", + description="There is an official but temporary fix available. This includes instances where the vendor issues a " + "temporary hotfix, tool or official workaround.", ) _OFFICIAL_FIX = SsvcDecisionPointValue( name="Official Fix", key="OF", - description="A complete vendor solution is available. Either the vendor has issued the final, official patch which eliminates the vulnerability or an upgrade that is not vulnerable is available.", + description="A complete vendor solution is available. Either the vendor has issued the final, official patch " + "which eliminates the vulnerability or an upgrade that is not vulnerable is available.", ) REMEDIATION_LEVEL_1 = CvssDecisionPoint( @@ -62,17 +77,18 @@ _TEMPORARY_FIX, _WORKAROUND, _UNAVAILABLE, - _NOT_DEFINED, + NOT_DEFINED_X, ), ) """ Adds Not Defined to the CVSS Remediation Level decision point. """ +versions = [REMEDIATION_LEVEL_1, REMEDIATION_LEVEL_1_1] + def main(): - print(REMEDIATION_LEVEL_1.to_json(indent=2)) - print(REMEDIATION_LEVEL_1_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/report_confidence.py b/src/ssvc/decision_points/cvss/report_confidence.py index 9c4c0a35..7c87f076 100644 --- a/src/ssvc/decision_points/cvss/report_confidence.py +++ b/src/ssvc/decision_points/cvss/report_confidence.py @@ -3,54 +3,79 @@ Models the CVSS Report Confidence metric as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_ND, NOT_DEFINED_X from ssvc.decision_points.cvss.base import CvssDecisionPoint - -_NOT_DEFINED = SsvcDecisionPointValue( - name="Not Defined", - key="ND", - description="Assigning this value to the metric will not influence the score. It is a signal to the equation to skip this metric.", -) +from ssvc.decision_points.helpers import print_versions_and_diffs _CONFIRMED_2 = SsvcDecisionPointValue( name="Confirmed", key="C", - description="Detailed reports exist, or functional reproduction is possible (functional exploits may provide this). Source code is available to independently verify the assertions of the research, or the author or vendor of the affected code has confirmed the presence of the vulnerability.", + description="Detailed reports exist, or functional reproduction is possible (functional exploits may provide " + "this). Source code is available to independently verify the assertions of the research, " + "or the author or vendor of the affected code has confirmed the presence of the vulnerability.", ) _REASONABLE = SsvcDecisionPointValue( name="Reasonable", key="R", - description="Significant details are published, but researchers either do not have full confidence in the root cause, or do not have access to source code to fully confirm all of the interactions that may lead to the result. Reasonable confidence exists, however, that the bug is reproducible and at least one impact is able to be verified (proof-of-concept exploits may provide this). An example is a detailed write-up of research into a vulnerability with an explanation (possibly obfuscated or 'left as an exercise to the reader') that gives assurances on how to reproduce the results.", + description="Significant details are published, but researchers either do not have full confidence in the root " + "cause, or do not have access to source code to fully confirm all of the interactions that may lead " + "to the result. Reasonable confidence exists, however, that the bug is reproducible and at least one " + "impact is able to be verified (proof-of-concept exploits may provide this).", ) _UNKNOWN = SsvcDecisionPointValue( name="Unknown", key="U", - description="There are reports of impacts that indicate a vulnerability is present. The reports indicate that the cause of the vulnerability is unknown, or reports may differ on the cause or impacts of the vulnerability. Reporters are uncertain of the true nature of the vulnerability, and there is little confidence in the validity of the reports or whether a static Base score can be applied given the differences described. An example is a bug report which notes that an intermittent but non-reproducible crash occurs, with evidence of memory corruption suggesting that denial of service, or possible more serious impacts, may result.", + description="There are reports of impacts that indicate a vulnerability is present. The reports indicate that the " + "cause of the vulnerability is unknown, or reports may differ on the cause or impacts of the " + "vulnerability. Reporters are uncertain of the true nature of the vulnerability, and there is little " + "confidence in the validity of the reports or whether a static Base score can be applied given the " + "differences described.", ) _CONFIRMED = SsvcDecisionPointValue( name="Confirmed", key="C", - description="Vendor or author of the affected technology has acknowledged that the vulnerability exists. This value may also be set when existence of a vulnerability is confirmed with absolute confidence through some other event, such as publication of functional proof of concept exploit code or widespread exploitation.", + description="Vendor or author of the affected technology has acknowledged that the vulnerability exists. This " + "value may also be set when existence of a vulnerability is confirmed with absolute confidence " + "through some other event, such as publication of functional proof of concept exploit code or " + "widespread exploitation.", ) _UNCORROBORATED = SsvcDecisionPointValue( name="Uncorroborated", key="UR", - description="Multiple non-official sources; possibily including independent security companies or research organizations. At this point there may be conflicting technical details or some other lingering ambiguity.", + description="Multiple non-official sources; possibily including independent security companies or research " + "organizations. At this point there may be conflicting technical details or some other lingering " + "ambiguity.", ) _UNCONFIRMED = SsvcDecisionPointValue( name="Unconfirmed", key="UC", - description="A single unconfirmed source or possibly several conflicting reports. There is little confidence in the validity of the report. For example, a rumor that surfaces from the hacker underground.", + description="A single unconfirmed source or possibly several conflicting reports. There is little confidence in " + "the validity of the report.", ) REPORT_CONFIDENCE_1 = CvssDecisionPoint( name="Report Confidence", - description="This metric measures the degree of confidence in the existence of the vulnerability and the credibility of the known technical details.", + description="This metric measures the degree of confidence in the existence of the vulnerability and the " + "credibility of the known technical details.", key="RC", version="1.0.0", values=( @@ -65,14 +90,15 @@ REPORT_CONFIDENCE_1_1 = CvssDecisionPoint( name="Report Confidence", - description="This metric measures the degree of confidence in the existence of the vulnerability and the credibility of the known technical details.", + description="This metric measures the degree of confidence in the existence of the vulnerability and the " + "credibility of the known technical details.", key="RC", version="1.1.0", values=( _UNCONFIRMED, _UNCORROBORATED, _CONFIRMED, - _NOT_DEFINED, + NOT_DEFINED_ND, ), ) """ @@ -81,14 +107,15 @@ REPORT_CONFIDENCE_2 = CvssDecisionPoint( name="Report Confidence", - description="This metric measures the degree of confidence in the existence of the vulnerability and the credibility of the known technical details.", + description="This metric measures the degree of confidence in the existence of the vulnerability and the " + "credibility of the known technical details.", key="RC", version="2.0.0", values=( _UNKNOWN, _REASONABLE, _CONFIRMED_2, - _NOT_DEFINED, + NOT_DEFINED_X, ), ) """ @@ -96,10 +123,15 @@ """ +versions = [ + REPORT_CONFIDENCE_1, + REPORT_CONFIDENCE_1_1, + REPORT_CONFIDENCE_2, +] + + def main(): - print(REPORT_CONFIDENCE_1.to_json(indent=2)) - print(REPORT_CONFIDENCE_1_1.to_json(indent=2)) - print(REPORT_CONFIDENCE_2.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/scope.py b/src/ssvc/decision_points/cvss/scope.py index 5da298b8..b6cf95a8 100644 --- a/src/ssvc/decision_points/cvss/scope.py +++ b/src/ssvc/decision_points/cvss/scope.py @@ -3,24 +3,41 @@ Models CVSS Scope as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _CHANGED = SsvcDecisionPointValue( name="Changed", key="C", - description="An exploited vulnerability can affect resources beyond the authorization privileges intended by the vulnerable component. In this case the vulnerable component and the impacted component are different.", + description="An exploited vulnerability can affect resources beyond the authorization privileges intended by the " + "vulnerable component. In this case the vulnerable component and the impacted component are different.", ) _UNCHANGED = SsvcDecisionPointValue( name="Unchanged", key="U", - description="An exploited vulnerability can only affect resources managed by the same authority. In this case the vulnerable component and the impacted component are the same.", + description="An exploited vulnerability can only affect resources managed by the same authority. In this case the " + "vulnerable component and the impacted component are the same.", ) SCOPE_1 = CvssDecisionPoint( name="Scope", - description="the ability for a vulnerability in one software component to impact resources beyond its means, or privileges", + description="the ability for a vulnerability in one software component to impact resources beyond its means, " + "or privileges", key="S", version="1.0.0", values=( @@ -32,9 +49,13 @@ Defines Changed and Unchanged values for CVSS Scope. """ +versions = [ + SCOPE_1, +] + def main(): - print(SCOPE_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/subsequent_availability_impact.py b/src/ssvc/decision_points/cvss/subsequent_availability_impact.py new file mode 100644 index 00000000..927e9326 --- /dev/null +++ b/src/ssvc/decision_points/cvss/subsequent_availability_impact.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +""" +CVSS Subsequent system availability impact decision point. +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + +_SA_HIGH = SsvcDecisionPointValue( + name="High", + key="H", + description="There is a total loss of availability, resulting in the attacker being able to fully deny access to " + "resources in the Subsequent System; this loss is either sustained (while the attacker continues to " + "deliver the attack) or persistent (the condition persists even after the attack has completed).", +) + +_SA_LOW = SsvcDecisionPointValue( + name="Low", + key="L", + description="Performance is reduced or there are interruptions in resource availability. Even if repeated " + "exploitation of the vulnerability is possible, the attacker does not have the ability to completely " + "deny service to legitimate users.", +) + +_SA_NONE = SsvcDecisionPointValue( + name="None", + key="N", + description="There is no impact to availability within the Subsequent System or all availability impact is " + "constrained to the Vulnerable System.", +) + + +SUBSEQUENT_AVAILABILITY_IMPACT_1 = CvssDecisionPoint( + name="Subsequent Availability Impact", + description="This metric measures the impact on availability a successful exploit of the vulnerability will have " + "on the Subsequent System.", + key="SA", + version="1.0.0", + values=( + _SA_NONE, + _SA_LOW, + _SA_HIGH, + ), +) + +versions = [ + SUBSEQUENT_AVAILABILITY_IMPACT_1, +] + + +def main(): + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/subsequent_confidentiality_impact.py b/src/ssvc/decision_points/cvss/subsequent_confidentiality_impact.py new file mode 100644 index 00000000..a8bd1fc4 --- /dev/null +++ b/src/ssvc/decision_points/cvss/subsequent_confidentiality_impact.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +""" +CVSS Subsequent System Confidentiality Impact +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + +NEGLIGIBLE = SsvcDecisionPointValue( + name="Negligible", + key="N", + description="There is no loss of confidentiality within the Subsequent System or all confidentiality impact is " + "constrained to the Vulnerable System.", +) + +LOW = SsvcDecisionPointValue( + name="Low", + key="L", + description="There is some loss of confidentiality. Access to some restricted information is obtained, but the " + "attacker does not have control over what information is obtained, or the amount or kind of loss is " + "limited. The information disclosure does not cause a direct, serious loss to the Subsequent System.", +) + +HIGH = SsvcDecisionPointValue( + name="High", + key="H", + description="There is a total loss of confidentiality, resulting in all resources within the Subsequent System " + "being divulged to the attacker. Alternatively, access to only some restricted information is obtained, " + "but the disclosed information presents a direct, serious impact.", +) + +SUBSEQUENT_CONFIDENTIALITY_IMPACT_1 = CvssDecisionPoint( + name="Confidentiality Impact to the Subsequent System", + key="SC", + description="This metric measures the impact to the confidentiality of the information managed by the system due " + "to a successfully exploited vulnerability. Confidentiality refers to limiting information access and " + "disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized " + "ones. The resulting score is greatest when the loss to the system is highest.", + version="1.0.0", + values=( + NEGLIGIBLE, + LOW, + HIGH, + ), +) + +versions = [ + SUBSEQUENT_CONFIDENTIALITY_IMPACT_1, +] + + +def main(): + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/subsequent_integrity_impact.py b/src/ssvc/decision_points/cvss/subsequent_integrity_impact.py new file mode 100644 index 00000000..3d885aa2 --- /dev/null +++ b/src/ssvc/decision_points/cvss/subsequent_integrity_impact.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +""" +CVSS Subsequent System Integrity Impact Decision Point +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + +SI_HIGH = SsvcDecisionPointValue( + name="High", + key="H", + description="There is a total loss of integrity, or a complete loss of protection. For example, the attacker is able " + "to modify any/all files protected by the Subsequent System. Alternatively, only some files can be " + "modified, but malicious modification would present a direct, serious consequence to the Subsequent " + "System.", +) + +SI_LOW = SsvcDecisionPointValue( + name="Low", + key="L", + description="Modification of data is possible, but the attacker does not have control over the consequence of a " + "modification, or the amount of modification is limited. The data modification does not have a direct, " + "serious impact to the Subsequent System.", +) + +SI_NONE = SsvcDecisionPointValue( + name="None", + key="N", + description="There is no loss of integrity within the Subsequent System or all integrity impact is constrained to " + "the Vulnerable System.", +) + +SUBSEQUENT_INTEGRITY_IMPACT_1 = CvssDecisionPoint( + name="Integrity Impact to the Subsequent System", + key="SI", + description="This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity " + "refers to the trustworthiness and veracity of information. Integrity of a system is impacted when " + "an attacker causes unauthorized modification of system data. Integrity is also impacted when a " + "system user can repudiate critical actions taken in the context of the system (e.g. due to " + "insufficient logging). The resulting score is greatest when the consequence to the system is " + "highest.", + version="1.0.0", + values=( + SI_NONE, + SI_LOW, + SI_HIGH, + ), +) + +versions = [ + SUBSEQUENT_INTEGRITY_IMPACT_1, +] + + +def main(): + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/supplemental/__init__.py b/src/ssvc/decision_points/cvss/supplemental/__init__.py new file mode 100644 index 00000000..1c16ef64 --- /dev/null +++ b/src/ssvc/decision_points/cvss/supplemental/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +""" +Provides CVSS v4 Supplemental Metrics +""" diff --git a/src/ssvc/decision_points/cvss/supplemental/automatable.py b/src/ssvc/decision_points/cvss/supplemental/automatable.py new file mode 100644 index 00000000..aef2ae4f --- /dev/null +++ b/src/ssvc/decision_points/cvss/supplemental/automatable.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +""" +Provides the CVSS supplemental metric Automatable +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + + +AUTOMATABLE_1 = CvssDecisionPoint( + name="Automatable", + description='The "Automatable" metric captures the answer to the question "Can an attacker automate exploitation ' + 'events for this vulnerability across multiple targets?" based on steps 1-4 of the kill chain.', + key="AU", + version="1.0.0", + values=( + SsvcDecisionPointValue( + name="No", + key="N", + description="Attackers cannot reliably automate all 4 steps of the kill chain for this vulnerability for " + "some reason. These steps are reconnaissance, weaponization, delivery, and exploitation.", + ), + SsvcDecisionPointValue( + name="Yes", + key="Y", + description="Attackers can reliably automate all 4 steps of the kill chain. These steps are " + "reconnaissance, weaponization, delivery, and exploitation (e.g., the vulnerability is " + '"wormable").', + ), + ), +) + + +def main(): + versions = [ + AUTOMATABLE_1, + ] + + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/supplemental/provider_urgency.py b/src/ssvc/decision_points/cvss/supplemental/provider_urgency.py new file mode 100644 index 00000000..3f0176a6 --- /dev/null +++ b/src/ssvc/decision_points/cvss/supplemental/provider_urgency.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +""" +Provides the CVSS supplemental metric Provider Urgency as a SSVC decision point. +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_X +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + +PROVIDER_URGENCY_1 = CvssDecisionPoint( + name="Provider Urgency", + description="Many vendors currently provide supplemental severity ratings to consumers via product security " + "advisories. Other vendors publish Qualitative Severity Ratings from the CVSS Specification Document " + "in their advisories. To facilitate a standardized method to incorporate additional provider-supplied " + 'assessment, an optional "pass-through" Supplemental Metric called Provider Urgency is available.', + key="U", + version="1.0.0", + values=( + NOT_DEFINED_X, + # Red, Amber, Green, Clear + SsvcDecisionPointValue( + name="Red", + key="R", + description="Provider has assessed the impact of this vulnerability as having the highest urgency.", + ), + SsvcDecisionPointValue( + name="Amber", + key="A", + description="Provider has assessed the impact of this vulnerability as having a moderate urgency.", + ), + SsvcDecisionPointValue( + name="Green", + key="G", + description="Provider has assessed the impact of this vulnerability as having a reduced urgency.", + ), + SsvcDecisionPointValue( + name="Clear", + key="C", + description="Provider has assessed the impact of this vulnerability as having no urgency (Informational).", + ), + ), +) + + +def main(): + versions = [ + PROVIDER_URGENCY_1, + ] + + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/supplemental/recovery.py b/src/ssvc/decision_points/cvss/supplemental/recovery.py new file mode 100644 index 00000000..cc815c28 --- /dev/null +++ b/src/ssvc/decision_points/cvss/supplemental/recovery.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +""" +Provides the CVSS supplemental metric Recovery +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_X +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + + +RECOVERY_1 = CvssDecisionPoint( + name="Recovery", + description="The Recovery metric describes the resilience of a system to recover services, in terms of performance " + "and availability, after an attack has been performed.", + key="R", + version="1.0.0", + values=( + NOT_DEFINED_X, + SsvcDecisionPointValue( + name="Automatic", + key="A", + description="The system recovers services automatically after an attack has been performed.", + ), + SsvcDecisionPointValue( + name="User", + key="U", + description="The system requires manual intervention by the user to recover services, after an attack has " + "been performed.", + ), + SsvcDecisionPointValue( + name="Irrecoverable", + key="I", + description="The system services are irrecoverable by the user, after an attack has been performed.", + ), + ), +) + + +def main(): + versions = [ + RECOVERY_1, + ] + + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/supplemental/safety.py b/src/ssvc/decision_points/cvss/supplemental/safety.py new file mode 100644 index 00000000..807d677a --- /dev/null +++ b/src/ssvc/decision_points/cvss/supplemental/safety.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +""" +Provides CVSS v4 Supplemental Metric for Safety +""" + +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_X +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + +SAFETY_1 = CvssDecisionPoint( + name="Safety", + description="The Safety decision point is a measure of the potential for harm to humans or the environment.", + key="S", + version="1.0.0", + values=( + NOT_DEFINED_X, + # Present, Negligible + SsvcDecisionPointValue( + name="Present", + key="P", + description="Consequences of the vulnerability meet definition of IEC 61508 consequence categories of " + '"marginal," "critical," or "catastrophic."', + ), + SsvcDecisionPointValue( + name="Negligible", + key="N", + description="Consequences of the vulnerability meet definition of IEC 61508 consequence category " + '"negligible."', + ), + ), +) + + +def main(): + versions = [ + SAFETY_1, + ] + + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/supplemental/value_density.py b/src/ssvc/decision_points/cvss/supplemental/value_density.py new file mode 100644 index 00000000..35e61b7d --- /dev/null +++ b/src/ssvc/decision_points/cvss/supplemental/value_density.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +""" +Provides the CVSS supplemental metric Value Density +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_X +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + + +VALUE_DENSITY_1 = CvssDecisionPoint( + name="Value Density", + description="Value Density describes the resources that the attacker will gain control over with a single " + "exploitation event. It has two possible values, diffuse and concentrated.", + key="V", + version="1.0.0", + values=( + NOT_DEFINED_X, + SsvcDecisionPointValue( + name="Diffuse", + key="D", + description="The vulnerable system has limited resources. That is, the resources that the attacker will " + "gain control over with a single exploitation event are relatively small.", + ), + SsvcDecisionPointValue( + name="Concentrated", + key="C", + description="The vulnerable system is rich in resources. Heuristically, such systems are often the direct " + 'responsibility of "system operators" rather than users.', + ), + ), +) + + +def main(): + versions = [ + VALUE_DENSITY_1, + ] + + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/supplemental/vulnerability_response_effort.py b/src/ssvc/decision_points/cvss/supplemental/vulnerability_response_effort.py new file mode 100644 index 00000000..13f61107 --- /dev/null +++ b/src/ssvc/decision_points/cvss/supplemental/vulnerability_response_effort.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +""" +Provides the CVSS supplemental metric Vulnerability Response Effort. +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_X +from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs + + +VULNERABILITY_RESPONSE_EFFORT_1 = CvssDecisionPoint( + name="Vulnerability Response Effort", + description="The intention of the Vulnerability Response Effort metric is to provide supplemental information on " + "how difficult it is for consumers to provide an initial response to the impact of vulnerabilities for deployed " + "products and services in their infrastructure. The consumer can then take this additional information on effort " + "required into consideration when applying mitigations and/or scheduling remediation.", + key="RE", + version="1.0.0", + values=( + NOT_DEFINED_X, + SsvcDecisionPointValue( + name="Low", + key="L", + description="The effort required to respond to a vulnerability is low/trivial.", + ), + SsvcDecisionPointValue( + name="Moderate", + key="M", + description="The actions required to respond to a vulnerability require some effort on behalf of the " + "consumer and could cause minimal service impact to implement.", + ), + SsvcDecisionPointValue( + name="High", + key="H", + description="The actions required to respond to a vulnerability are significant and/or difficult, and may " + "possibly lead to an extended, scheduled service impact. This would need to be considered for scheduling " + "purposes including honoring any embargo on deployment of the selected response. Alternatively, response " + "to the vulnerability in the field is not possible remotely. The only resolution to the vulnerability " + "involves physical replacement (e.g. units deployed would have to be recalled for a depot level repair or " + "replacement).", + ), + ), +) + + +def main(): + versions = [ + VULNERABILITY_RESPONSE_EFFORT_1, + ] + + print_versions_and_diffs(versions) + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/decision_points/cvss/target_distribution.py b/src/ssvc/decision_points/cvss/target_distribution.py index ba0da97d..3601f07b 100644 --- a/src/ssvc/decision_points/cvss/target_distribution.py +++ b/src/ssvc/decision_points/cvss/target_distribution.py @@ -3,42 +3,58 @@ Models CVSS Target Distribution as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue +from ssvc.decision_points.cvss._not_defined import NOT_DEFINED_X from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs -_NOT_DEFINED = SsvcDecisionPointValue( - name="Not Defined", - key="ND", - description="This value is not defined in any specification, but is used in the CVSS v3.0 vector string when a value is required by the specification, but cannot be provided. This is a special case value and should be used sparingly.", -) _HIGH = SsvcDecisionPointValue( name="High", key="H", - description="Targets exist inside the environment on a considerable scale. Between 50% - 100% of the total environment is considered at risk.", + description="Targets exist inside the environment on a considerable scale. Between 50% - 100% of the total " + "environment is considered at risk.", ) _MEDIUM = SsvcDecisionPointValue( name="Medium", key="M", - description="Targets exist inside the environment, but on a medium scale. Between 16% - 49% of the total environment is at risk.", + description="Targets exist inside the environment, but on a medium scale. Between 16% - 49% of the total " + "environment is at risk.", ) _LOW = SsvcDecisionPointValue( name="Low", key="L", - description="Targets exist inside the environment, but on a small scale. Between 1% - 15% of the total environment is at risk.", + description="Targets exist inside the environment, but on a small scale. Between 1% - 15% of the total " + "environment is at risk.", ) _TD_NONE = SsvcDecisionPointValue( name="None", key="N", - description="No target systems exist, or targets are so highly specialized that they only exist in a laboratory setting. Effectively 0% of the environment is at risk.", + description="No target systems exist, or targets are so highly specialized that they only exist in a laboratory " + "setting. Effectively 0% of the environment is at risk.", ) TARGET_DISTRIBUTION_1 = CvssDecisionPoint( name="Target Distribution", - description="This metric measures the relative size of the field of target systems susceptible to the vulnerability. It is meant as an environment-specific indicator in order to approximate the percentage of systems within the environment that could be affected by the vulnerability.", + description="This metric measures the relative size of the field of target systems susceptible to the " + "vulnerability. It is meant as an environment-specific indicator in order to approximate the " + "percentage of systems within the environment that could be affected by the vulnerability.", key="TD", version="1.0.0", values=( @@ -54,7 +70,9 @@ TARGET_DISTRIBUTION_1_1 = CvssDecisionPoint( name="Target Distribution", - description="This metric measures the relative size of the field of target systems susceptible to the vulnerability. It is meant as an environment-specific indicator in order to approximate the percentage of systems within the environment that could be affected by the vulnerability.", + description="This metric measures the relative size of the field of target systems susceptible to the " + "vulnerability. It is meant as an environment-specific indicator in order to approximate the " + "percentage of systems within the environment that could be affected by the vulnerability.", key="TD", version="1.1.0", values=( @@ -62,17 +80,21 @@ _LOW, _MEDIUM, _HIGH, - _NOT_DEFINED, + NOT_DEFINED_X, ), ) """ Introduces Not Defined value. """ +versions = [ + TARGET_DISTRIBUTION_1, + TARGET_DISTRIBUTION_1_1, +] + def main(): - print(TARGET_DISTRIBUTION_1.to_json(indent=2)) - print(TARGET_DISTRIBUTION_1_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/decision_points/cvss/user_interaction.py b/src/ssvc/decision_points/cvss/user_interaction.py index 97000018..f5ce27e0 100644 --- a/src/ssvc/decision_points/cvss/user_interaction.py +++ b/src/ssvc/decision_points/cvss/user_interaction.py @@ -3,13 +3,28 @@ Models CVSS User Interaction as an SSVC decision point. """ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + from ssvc.decision_points.base import SsvcDecisionPointValue from ssvc.decision_points.cvss.base import CvssDecisionPoint +from ssvc.decision_points.helpers import print_versions_and_diffs _REQUIRED = SsvcDecisionPointValue( name="Required", key="R", - description="Successful exploitation of this vulnerability requires a user to take some action before the vulnerability can be exploited.", + description="Successful exploitation of this vulnerability requires a user to take some action before the " + "vulnerability can be exploited.", ) _UI_NONE = SsvcDecisionPointValue( @@ -21,21 +36,64 @@ USER_INTERACTION_1 = CvssDecisionPoint( name="User Interaction", - description="This metric captures the requirement for a user, other than the attacker, to participate in the successful compromise of the vulnerable component.", + description="This metric captures the requirement for a user, other than the attacker, to participate in the " + "successful compromise of the vulnerable component.", key="UI", version="1.0.0", values=( - _UI_NONE, _REQUIRED, + _UI_NONE, ), ) """ Defines None and Required values for CVSS User Interaction. """ +_UI_NONE_2 = SsvcDecisionPointValue( + name="None", + key="N", + description="The vulnerable system can be exploited without interaction from any human user, other than the " + "attacker.", +) + +_PASSIVE = SsvcDecisionPointValue( + name="Passive", + key="P", + description="Successful exploitation of this vulnerability requires limited interaction by the targeted user with " + "the vulnerable system and the attacker’s payload. These interactions would be considered involuntary " + "and do not require that the user actively subvert protections built into the vulnerable system.", +) + +_ACTIVE = SsvcDecisionPointValue( + name="Active", + key="A", + description="Successful exploitation of this vulnerability requires a targeted user to perform specific, " + "conscious interactions with the vulnerable system and the attacker’s payload, or the user’s " + "interactions would actively subvert protection mechanisms which would lead to exploitation of the " + "vulnerability.", +) + +USER_INTERACTION_2 = CvssDecisionPoint( + name="User Interaction", + key="UI", + description="This metric captures the requirement for a human user, other than the attacker, to participate " + "in the successful compromise of the vulnerable system. This metric determines whether the " + "vulnerability can be exploited solely at the will of the attacker, or whether a separate user " + "(or user-initiated process) must participate in some manner. The resulting score is greatest " + "when no user interaction is required.", + version="2.0.0", + values=( + _ACTIVE, + _PASSIVE, + _UI_NONE_2, + ), +) + +versions = [USER_INTERACTION_1, USER_INTERACTION_2] + def main(): - print(USER_INTERACTION_1.to_json(indent=2)) + print_versions_and_diffs(versions) if __name__ == "__main__": diff --git a/src/ssvc/dp_groups/__init__.py b/src/ssvc/dp_groups/__init__.py index a3a2a181..90a47e3a 100644 --- a/src/ssvc/dp_groups/__init__.py +++ b/src/ssvc/dp_groups/__init__.py @@ -1,14 +1,15 @@ -#!/usr/bin/env python +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University """ -file: __init__.py -author: adh -created_at: 9/20/23 4:47 PM +Provides Decision Point Group classes for SSVC. """ - - -def main(): - pass - - -if __name__ == "__main__": - main() diff --git a/src/ssvc/dp_groups/cvss/__init__.py b/src/ssvc/dp_groups/cvss/__init__.py index 41ce5469..7b9251b9 100644 --- a/src/ssvc/dp_groups/cvss/__init__.py +++ b/src/ssvc/dp_groups/cvss/__init__.py @@ -1,14 +1,14 @@ -#!/usr/bin/env python -""" -file: __init__.py -author: adh -created_at: 9/20/23 4:54 PM -""" - - -def main(): - pass - - -if __name__ == "__main__": - main() +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +"""Provides SSVC decision point groups representing CVSS versions.""" diff --git a/src/ssvc/dp_groups/cvss/collections.py b/src/ssvc/dp_groups/cvss/collections.py new file mode 100644 index 00000000..e7adf706 --- /dev/null +++ b/src/ssvc/dp_groups/cvss/collections.py @@ -0,0 +1,374 @@ +#!/usr/bin/env python +""" +Models CVSS vectors as SSVC decision point groups +""" +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +from ssvc.decision_points.cvss.attack_complexity import ( + ACCESS_COMPLEXITY_1, + ACCESS_COMPLEXITY_2, + ATTACK_COMPLEXITY_3, + ATTACK_COMPLEXITY_3_0_1, +) +from ssvc.decision_points.cvss.attack_requirements import ATTACK_REQUIREMENTS_1 +from ssvc.decision_points.cvss.attack_vector import ( + ACCESS_VECTOR_1, + ACCESS_VECTOR_2, + ATTACK_VECTOR_3, + ATTACK_VECTOR_3_0_1, +) +from ssvc.decision_points.cvss.authentication import AUTHENTICATION_1, AUTHENTICATION_2 +from ssvc.decision_points.cvss.availability_impact import ( + AVAILABILITY_IMPACT_1, + AVAILABILITY_IMPACT_2, + AVAILABILITY_IMPACT_2_0_1, +) +from ssvc.decision_points.cvss.availability_requirement import ( + AVAILABILITY_REQUIREMENT_1, + AVAILABILITY_REQUIREMENT_1_1, + AVAILABILITY_REQUIREMENT_1_1_1, +) +from ssvc.decision_points.cvss.collateral_damage_potential import ( + COLLATERAL_DAMAGE_POTENTIAL_1, + COLLATERAL_DAMAGE_POTENTIAL_2, +) +from ssvc.decision_points.cvss.confidentiality_impact import ( + CONFIDENTIALITY_IMPACT_1, + CONFIDENTIALITY_IMPACT_2, + CONFIDENTIALITY_IMPACT_2_0_1, +) +from ssvc.decision_points.cvss.confidentiality_requirement import ( + CONFIDENTIALITY_REQUIREMENT_1, + CONFIDENTIALITY_REQUIREMENT_1_1, + CONFIDENTIALITY_REQUIREMENT_1_1_1, +) +from ssvc.decision_points.cvss.eq_sets import EQ1, EQ2, EQ3, EQ4, EQ5, EQ6 +from ssvc.decision_points.cvss.exploitability import ( + EXPLOITABILITY_1, + EXPLOITABILITY_1_1, + EXPLOIT_CODE_MATURITY_1_2, + EXPLOIT_MATURITY_2, +) +from ssvc.decision_points.cvss.helpers import modify_3, modify_4 +from ssvc.decision_points.cvss.impact_bias import IMPACT_BIAS_1 +from ssvc.decision_points.cvss.integrity_impact import ( + INTEGRITY_IMPACT_1, + INTEGRITY_IMPACT_2, + INTEGRITY_IMPACT_2_0_1, +) +from ssvc.decision_points.cvss.integrity_requirement import ( + INTEGRITY_REQUIREMENT_1, + INTEGRITY_REQUIREMENT_1_1, + INTEGRITY_REQUIREMENT_1_1_1, +) +from ssvc.decision_points.cvss.privileges_required import ( + PRIVILEGES_REQUIRED_1, + PRIVILEGES_REQUIRED_1_0_1, +) +from ssvc.decision_points.cvss.remediation_level import ( + REMEDIATION_LEVEL_1, + REMEDIATION_LEVEL_1_1, +) +from ssvc.decision_points.cvss.report_confidence import ( + REPORT_CONFIDENCE_1, + REPORT_CONFIDENCE_1_1, + REPORT_CONFIDENCE_2, +) +from ssvc.decision_points.cvss.scope import SCOPE_1 as SCOPE +from ssvc.decision_points.cvss.subsequent_availability_impact import ( + SUBSEQUENT_AVAILABILITY_IMPACT_1, +) +from ssvc.decision_points.cvss.subsequent_confidentiality_impact import ( + SUBSEQUENT_CONFIDENTIALITY_IMPACT_1, +) +from ssvc.decision_points.cvss.subsequent_integrity_impact import ( + SUBSEQUENT_INTEGRITY_IMPACT_1, +) +from ssvc.decision_points.cvss.supplemental.automatable import AUTOMATABLE_1 +from ssvc.decision_points.cvss.supplemental.provider_urgency import PROVIDER_URGENCY_1 +from ssvc.decision_points.cvss.supplemental.recovery import RECOVERY_1 +from ssvc.decision_points.cvss.supplemental.safety import SAFETY_1 +from ssvc.decision_points.cvss.supplemental.value_density import VALUE_DENSITY_1 +from ssvc.decision_points.cvss.supplemental.vulnerability_response_effort import ( + VULNERABILITY_RESPONSE_EFFORT_1, +) +from ssvc.decision_points.cvss.target_distribution import ( + TARGET_DISTRIBUTION_1, + TARGET_DISTRIBUTION_1_1, +) +from ssvc.decision_points.cvss.user_interaction import ( + USER_INTERACTION_1, + USER_INTERACTION_2, +) +from ssvc.dp_groups.base import SsvcDecisionPointGroup + +# Instantiate the CVSS v1 decision point group +_BASE_1 = [ + ACCESS_VECTOR_1, + ACCESS_COMPLEXITY_1, + AUTHENTICATION_1, + CONFIDENTIALITY_IMPACT_1, + INTEGRITY_IMPACT_1, + AVAILABILITY_IMPACT_1, + IMPACT_BIAS_1, +] +_TEMPORAL_1 = [ + EXPLOITABILITY_1, + REMEDIATION_LEVEL_1, + REPORT_CONFIDENCE_1, +] +_ENVIRONMENTAL_1 = [ + COLLATERAL_DAMAGE_POTENTIAL_1, + TARGET_DISTRIBUTION_1, +] + +CVSSv1_B = SsvcDecisionPointGroup( + name="CVSS", + version="1.0", + description="CVSS v1 decision points", + decision_points=tuple(_BASE_1), +) + +CVSSv1_BT = SsvcDecisionPointGroup( + name="CVSS", + version="1.0", + description="CVSS v1 decision points", + decision_points=tuple(_BASE_1 + _TEMPORAL_1), +) + +CVSSv1_BTE = SsvcDecisionPointGroup( + name="CVSS", + version="1.0", + description="CVSS v1 decision points", + decision_points=tuple(_BASE_1 + _TEMPORAL_1 + _ENVIRONMENTAL_1), +) + +CVSSv1 = CVSSv1_BTE # convenience alias + +# CVSS v2 decision points + +_BASE_2 = [ + ACCESS_VECTOR_2, + ACCESS_COMPLEXITY_2, + AUTHENTICATION_2, + CONFIDENTIALITY_IMPACT_1, + INTEGRITY_IMPACT_1, + AVAILABILITY_IMPACT_1, +] +_TEMPORAL_2 = [ + EXPLOITABILITY_1_1, + REMEDIATION_LEVEL_1_1, + REPORT_CONFIDENCE_1_1, +] +_ENVIRONMENTAL_2 = [ + COLLATERAL_DAMAGE_POTENTIAL_2, + TARGET_DISTRIBUTION_1_1, + CONFIDENTIALITY_REQUIREMENT_1, + INTEGRITY_REQUIREMENT_1, + AVAILABILITY_REQUIREMENT_1, +] + +CVSSv2_B = SsvcDecisionPointGroup( + name="CVSS Version 2 Base Metrics", + description="Base metrics for CVSS v2", + version="2.0", + decision_points=tuple(_BASE_2), +) + +CVSSv2_BT = SsvcDecisionPointGroup( + name="CVSS Version 2 Base and Temporal Metrics", + description="Base and Temporal metrics for CVSS v2", + version="2.0", + decision_points=tuple(_BASE_2 + _TEMPORAL_2), +) + +CVSSv2_BTE = SsvcDecisionPointGroup( + name="CVSS Version 2 Base, Temporal, and Environmental Metrics", + description="Base, Temporal, and Environmental metrics for CVSS v2", + version="2.0", + decision_points=tuple(_BASE_2 + _TEMPORAL_2 + _ENVIRONMENTAL_2), +) + +CVSSv2 = CVSSv2_BTE # convenience alias + +# CVSS v3 decision points +_BASE_3 = [ + ATTACK_VECTOR_3, + ATTACK_COMPLEXITY_3, + PRIVILEGES_REQUIRED_1, + USER_INTERACTION_1, + SCOPE, + CONFIDENTIALITY_IMPACT_2, + INTEGRITY_IMPACT_2, + AVAILABILITY_IMPACT_2, +] +_TEMPORAL_3 = [ + EXPLOIT_CODE_MATURITY_1_2, + REMEDIATION_LEVEL_1_1, + REPORT_CONFIDENCE_2, +] + +_ENVIRONMENTAL_3 = [modify_3(dp) for dp in _BASE_3] +_ENVIRONMENTAL_3.extend( + [ + CONFIDENTIALITY_REQUIREMENT_1_1, + INTEGRITY_REQUIREMENT_1_1, + AVAILABILITY_REQUIREMENT_1_1, + ] +) + +CVSSv3_B = SsvcDecisionPointGroup( + name="CVSS Version 3 Base Metrics", + description="Base metrics for CVSS v3", + version="3.0", + decision_points=tuple(_BASE_3), +) + +CVSSv3_BT = SsvcDecisionPointGroup( + name="CVSS Version 3 Base and Temporal Metrics", + description="Base and Temporal metrics for CVSS v3", + version="3.0", + decision_points=tuple(_BASE_3 + _TEMPORAL_3), +) + +CVSSv3_BTE = SsvcDecisionPointGroup( + name="CVSS Version 3 Base, Temporal, and Environmental Metrics", + description="Base, Temporal, and Environmental metrics for CVSS v3", + version="3.0", + decision_points=tuple(_BASE_3 + _TEMPORAL_3 + _ENVIRONMENTAL_3), +) + +CVSSv3 = CVSSv3_BTE # convenience alias + +# CVSS v4 decision points + +_EXPLOITABILITY_4 = [ + ATTACK_VECTOR_3_0_1, + ATTACK_COMPLEXITY_3_0_1, + ATTACK_REQUIREMENTS_1, + PRIVILEGES_REQUIRED_1_0_1, + USER_INTERACTION_2, +] +_IMPACT_4 = [ + CONFIDENTIALITY_IMPACT_2_0_1, + INTEGRITY_IMPACT_2_0_1, + AVAILABILITY_IMPACT_2_0_1, + SUBSEQUENT_CONFIDENTIALITY_IMPACT_1, + SUBSEQUENT_INTEGRITY_IMPACT_1, + SUBSEQUENT_AVAILABILITY_IMPACT_1, +] +_BASE_4 = _EXPLOITABILITY_4 + _IMPACT_4 + +# note: CVSS v4 does more than just insert "modified" in front of the name and "M" in front of the key +_ENVIRONMENTAL_4 = [modify_4(dp) for dp in _BASE_4] +_ENVIRONMENTAL_4.extend( + [ + CONFIDENTIALITY_REQUIREMENT_1_1_1, + INTEGRITY_REQUIREMENT_1_1_1, + AVAILABILITY_REQUIREMENT_1_1_1, + ] +) +_THREAT_4 = [ + EXPLOIT_MATURITY_2, +] + +_SUPPLEMENTAL_4 = [ + SAFETY_1, + AUTOMATABLE_1, + PROVIDER_URGENCY_1, + RECOVERY_1, + VALUE_DENSITY_1, + VULNERABILITY_RESPONSE_EFFORT_1, +] +# CVSS-B Base metrics +CVSSv4_B = SsvcDecisionPointGroup( + name="CVSSv4 Base Metrics", + description="Base metrics for CVSS v4", + version="1.0.0", + decision_points=tuple(_BASE_4), +) + +# CVSS-BE Base and Environmental metrics +CVSSv4_BE = SsvcDecisionPointGroup( + name="CVSSv4 Base and Environmental Metrics", + description="Base and Environmental metrics for CVSS v4", + version="1.0.0", + decision_points=tuple(_BASE_4 + _ENVIRONMENTAL_4), +) + +# CVSS-BT Base and Threat metrics +CVSSv4_BT = SsvcDecisionPointGroup( + name="CVSSv4 Base and Threat Metrics", + description="Base and Threat metrics for CVSS v4", + version="1.0.0", + decision_points=tuple(_BASE_4 + _THREAT_4), +) + +# CVSS-BTE +CVSSv4_BTE = SsvcDecisionPointGroup( + name="CVSSv4 Base, Threat, and Environmental Metrics", + description="Base, Threat, and Environmental metrics for CVSS v4", + version="1.0.0", + decision_points=tuple(_BASE_4 + _THREAT_4 + _ENVIRONMENTAL_4), +) + +CVSSv4 = SsvcDecisionPointGroup( + name="CVSSv4", + description="All decision points for CVSS v4 (including supplemental metrics)", + version="1.0.0", + decision_points=tuple(_BASE_4 + _THREAT_4 + _ENVIRONMENTAL_4 + _SUPPLEMENTAL_4), +) + +CVSSv4_Equivalence_Sets = SsvcDecisionPointGroup( + name="CVSSv4 EQ Sets", + description="Equivalence Sets for CVSS v4", + version="1.0.0", + decision_points=( + EQ1, + EQ2, + EQ3, + EQ4, + EQ5, + EQ6, + ), +) + +CVSSv4_EQ = CVSSv4_Equivalence_Sets # convenience alias + + +def main(): + for group in [ + CVSSv1_B, + CVSSv1_BT, + CVSSv1_BTE, + CVSSv2_B, + CVSSv2_BT, + CVSSv2_BTE, + CVSSv3_B, + CVSSv3_BT, + CVSSv3_BTE, + CVSSv4_B, + CVSSv4_BE, + CVSSv4_BT, + CVSSv4_BTE, + CVSSv4_Equivalence_Sets, + CVSSv4, + ]: + print(f"## {group.name} v{group.version}") + print(group.to_json(indent=2)) + print() + + +if __name__ == "__main__": + main() diff --git a/src/ssvc/dp_groups/cvss/v1.py b/src/ssvc/dp_groups/cvss/v1.py deleted file mode 100644 index 041a9f2b..00000000 --- a/src/ssvc/dp_groups/cvss/v1.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -""" -file: v1 -author: adh -created_at: 9/20/23 12:39 PM -""" - -# Copyright (c) 2023 Carnegie Mellon University and Contributors. -# - see Contributors.md for a full list of Contributors -# - see ContributionInstructions.md for information on how you can Contribute to this project -# Stakeholder Specific Vulnerability Categorization (SSVC) is -# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed -# with this Software or contact permission@sei.cmu.edu for full terms. -# Created, in part, with funding and support from the United States Government -# (see Acknowledgments file). This program may include and/or can make use of -# certain third party source code, object code, documentation and other files -# (“Third Party Software”). See LICENSE.md for more details. -# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the -# U.S. Patent and Trademark Office by Carnegie Mellon University - -from ssvc.decision_points.cvss.attack_complexity import ACCESS_COMPLEXITY_1 -from ssvc.decision_points.cvss.attack_vector import ACCESS_VECTOR_1 -from ssvc.decision_points.cvss.authentication import AUTHENTICATION_1 -from ssvc.decision_points.cvss.availability_impact import ( - AVAILABILITY_IMPACT_1, -) -from ssvc.decision_points.cvss.collateral_damage_potential import ( - COLLATERAL_DAMAGE_POTENTIAL_1, -) -from ssvc.decision_points.cvss.confidentiality_impact import ( - CONFIDENTIALITY_IMPACT_1, -) -from ssvc.decision_points.cvss.exploitability import ( - EXPLOITABILITY_1, -) -from ssvc.decision_points.cvss.impact_bias import IMPACT_BIAS_1 -from ssvc.decision_points.cvss.integrity_impact import ( - INTEGRITY_IMPACT_1, -) -from ssvc.decision_points.cvss.remediation_level import ( - REMEDIATION_LEVEL_1, -) -from ssvc.decision_points.cvss.report_confidence import ( - REPORT_CONFIDENCE_1, -) -from ssvc.decision_points.cvss.target_distribution import ( - TARGET_DISTRIBUTION_1, -) -from ssvc.dp_groups.base import SsvcDecisionPointGroup - -# Instantiate the CVSS v1 decision point group -CVSSv1 = SsvcDecisionPointGroup( - name="CVSS", - version="1.0", - description="CVSS v1 decision points", - decision_points=( - ACCESS_VECTOR_1, - ACCESS_COMPLEXITY_1, - AUTHENTICATION_1, - CONFIDENTIALITY_IMPACT_1, - INTEGRITY_IMPACT_1, - AVAILABILITY_IMPACT_1, - IMPACT_BIAS_1, - EXPLOITABILITY_1, - REMEDIATION_LEVEL_1, - REPORT_CONFIDENCE_1, - COLLATERAL_DAMAGE_POTENTIAL_1, - TARGET_DISTRIBUTION_1, - ), -) - - -def main(): - print(CVSSv1.to_json(indent=2)) - - -if __name__ == "__main__": - main() diff --git a/src/ssvc/dp_groups/cvss/v2.py b/src/ssvc/dp_groups/cvss/v2.py deleted file mode 100644 index 3923a181..00000000 --- a/src/ssvc/dp_groups/cvss/v2.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -""" -file: v2 -author: adh -created_at: 9/20/23 12:54 PM -""" - -# Copyright (c) 2023 Carnegie Mellon University and Contributors. -# - see Contributors.md for a full list of Contributors -# - see ContributionInstructions.md for information on how you can Contribute to this project -# Stakeholder Specific Vulnerability Categorization (SSVC) is -# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed -# with this Software or contact permission@sei.cmu.edu for full terms. -# Created, in part, with funding and support from the United States Government -# (see Acknowledgments file). This program may include and/or can make use of -# certain third party source code, object code, documentation and other files -# (“Third Party Software”). See LICENSE.md for more details. -# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the -# U.S. Patent and Trademark Office by Carnegie Mellon University - -from ssvc.decision_points.cvss.attack_complexity import ACCESS_COMPLEXITY_2 -from ssvc.decision_points.cvss.attack_vector import ACCESS_VECTOR_2 -from ssvc.decision_points.cvss.authentication import AUTHENTICATION_2 -from ssvc.decision_points.cvss.availability_impact import ( - AVAILABILITY_IMPACT_1, -) -from ssvc.decision_points.cvss.availability_requirement import ( - AVAILABILITY_REQUIREMENT_1, -) -from ssvc.decision_points.cvss.collateral_damage_potential import ( - COLLATERAL_DAMAGE_POTENTIAL_2, -) -from ssvc.decision_points.cvss.confidentiality_impact import ( - CONFIDENTIALITY_IMPACT_1, -) -from ssvc.decision_points.cvss.confidentiality_requirement import ( - CONFIDENTIALITY_REQUIREMENT_1, -) -from ssvc.decision_points.cvss.exploitability import ( - EXPLOITABILITY_1_1, -) -from ssvc.decision_points.cvss.integrity_impact import ( - INTEGRITY_IMPACT_1, -) -from ssvc.decision_points.cvss.integrity_requirement import ( - INTEGRITY_REQUIREMENT_1, -) -from ssvc.decision_points.cvss.remediation_level import ( - REMEDIATION_LEVEL_1_1, -) -from ssvc.decision_points.cvss.report_confidence import ( - REPORT_CONFIDENCE_1_1, -) -from ssvc.decision_points.cvss.target_distribution import ( - TARGET_DISTRIBUTION_1_1, -) -from ssvc.dp_groups.base import SsvcDecisionPointGroup - -CVSSv2 = SsvcDecisionPointGroup( - name="CVSS Version 2", - description="The Common Vulnerability Scoring System (CVSS) is a free and open industry standard for assessing the severity of computer system security vulnerabilities. CVSS attempts to assign severity scores to vulnerabilities, allowing responders to prioritize responses and resources according to threat. Scores are calculated based on a formula that depends on several metrics that approximate ease of exploit and the impact of exploit. Scores range from 0 to 10, with 10 being the most severe.", - version="2.0", - decision_points=( - ACCESS_VECTOR_2, - ACCESS_COMPLEXITY_2, - AUTHENTICATION_2, - CONFIDENTIALITY_IMPACT_1, - INTEGRITY_IMPACT_1, - AVAILABILITY_IMPACT_1, - EXPLOITABILITY_1_1, - REMEDIATION_LEVEL_1_1, - REPORT_CONFIDENCE_1_1, - COLLATERAL_DAMAGE_POTENTIAL_2, - TARGET_DISTRIBUTION_1_1, - CONFIDENTIALITY_REQUIREMENT_1, - INTEGRITY_REQUIREMENT_1, - AVAILABILITY_REQUIREMENT_1, - ), -) - - -def main(): - print(CVSSv2.to_json(indent=2)) - - -if __name__ == "__main__": - main() diff --git a/src/ssvc/dp_groups/cvss/v3.py b/src/ssvc/dp_groups/cvss/v3.py deleted file mode 100644 index 93c42fff..00000000 --- a/src/ssvc/dp_groups/cvss/v3.py +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env python -""" -file: v3 -author: adh -created_at: 9/20/23 2:30 PM -""" -# Copyright (c) 2023 Carnegie Mellon University and Contributors. -# - see Contributors.md for a full list of Contributors -# - see ContributionInstructions.md for information on how you can Contribute to this project -# Stakeholder Specific Vulnerability Categorization (SSVC) is -# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed -# with this Software or contact permission@sei.cmu.edu for full terms. -# Created, in part, with funding and support from the United States Government -# (see Acknowledgments file). This program may include and/or can make use of -# certain third party source code, object code, documentation and other files -# (“Third Party Software”). See LICENSE.md for more details. -# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the -# U.S. Patent and Trademark Office by Carnegie Mellon University - -from copy import deepcopy - -from ssvc.decision_points.base import SsvcDecisionPointValue -from ssvc.decision_points.cvss.attack_complexity import ( - ATTACK_COMPLEXITY_3, -) -from ssvc.decision_points.cvss.attack_vector import ATTACK_VECTOR_3 -from ssvc.decision_points.cvss.availability_impact import ( - AVAILABILITY_IMPACT_2, -) -from ssvc.decision_points.cvss.availability_requirement import ( - AVAILABILITY_REQUIREMENT_1, -) -from ssvc.decision_points.cvss.confidentiality_impact import ( - CONFIDENTIALITY_IMPACT_2, -) -from ssvc.decision_points.cvss.confidentiality_requirement import ( - CONFIDENTIALITY_REQUIREMENT_1, -) -from ssvc.decision_points.cvss.exploitability import ( - EXPLOIT_CODE_MATURITY_1_1_1, -) -from ssvc.decision_points.cvss.integrity_impact import ( - INTEGRITY_IMPACT_2, -) -from ssvc.decision_points.cvss.integrity_requirement import ( - INTEGRITY_REQUIREMENT_1, -) -from ssvc.decision_points.cvss.privileges_required import ( - PRIVILEGES_REQUIRED_1, -) -from ssvc.decision_points.cvss.remediation_level import ( - REMEDIATION_LEVEL_1_1, -) -from ssvc.decision_points.cvss.report_confidence import ( - REPORT_CONFIDENCE_2, -) -from ssvc.decision_points.cvss.scope import SCOPE_1 as SCOPE -from ssvc.decision_points.cvss.user_interaction import ( - USER_INTERACTION_1, -) -from ssvc.dp_groups.base import SsvcDecisionPointGroup - - -def _modify(obj): - """ - Prepends "Modified " to the name and "M" to the key of the given object. Also adds a value of "Not Defined" to the - values list. - :param obj: the object to modify - :return: the object - """ - o = deepcopy(obj) - o.name = "Modified " + o.name - o.key = "M" + o.key - nd = SsvcDecisionPointValue( - name="Not Defined", key="ND", description="Ignore this value" - ) - values = list(o.values) - # if there is no value named "Not Defined" value, add it - names = [v.name for v in values] - if nd.name not in names: - values.append(nd) - o.values = tuple(values) - return o - - -MODIFIED_ATTACK_VECTOR = _modify(ATTACK_VECTOR_3) -MODIFIED_ATTACK_COMPLEXITY = _modify(ATTACK_COMPLEXITY_3) -MODIFIED_PRIVILEGES_REQUIRED = _modify(PRIVILEGES_REQUIRED_1) -MODIFIED_USER_INTERACTION = _modify(USER_INTERACTION_1) -MODIFIED_SCOPE = _modify(SCOPE) -MODIFIED_CONFIDENTIALITY_IMPACT = _modify(CONFIDENTIALITY_IMPACT_2) -MODIFIED_INTEGRITY_IMPACT = _modify(INTEGRITY_IMPACT_2) -MODIFIED_AVAILABILITY_IMPACT = _modify(AVAILABILITY_IMPACT_2) - - -CVSSv3 = SsvcDecisionPointGroup( - name="CVSS Version 3", - description="The Common Vulnerability Scoring System (CVSS) is a free and open industry standard for assessing the severity of computer system security vulnerabilities. CVSS attempts to assign severity scores to vulnerabilities, allowing responders to prioritize responses and resources according to threat. Scores are calculated based on a formula that depends on several metrics that approximate ease of exploit and the impact of exploit. Scores range from 0 to 10, with 10 being the most severe.", - version="3.0", - decision_points=( - ATTACK_VECTOR_3, - ATTACK_COMPLEXITY_3, - PRIVILEGES_REQUIRED_1, - USER_INTERACTION_1, - SCOPE, - CONFIDENTIALITY_IMPACT_2, - INTEGRITY_IMPACT_2, - AVAILABILITY_IMPACT_2, - EXPLOIT_CODE_MATURITY_1_1_1, - REMEDIATION_LEVEL_1_1, - REPORT_CONFIDENCE_2, - CONFIDENTIALITY_REQUIREMENT_1, - INTEGRITY_REQUIREMENT_1, - AVAILABILITY_REQUIREMENT_1, - MODIFIED_ATTACK_VECTOR, - MODIFIED_ATTACK_COMPLEXITY, - MODIFIED_PRIVILEGES_REQUIRED, - MODIFIED_USER_INTERACTION, - MODIFIED_SCOPE, - MODIFIED_CONFIDENTIALITY_IMPACT, - MODIFIED_INTEGRITY_IMPACT, - MODIFIED_AVAILABILITY_IMPACT, - ), -) - - -def main(): - print(CVSSv3.to_json(indent=2)) - - -if __name__ == "__main__": - main() diff --git a/src/test/__init__.py b/src/test/__init__.py index 5c4aa405..cf0a9163 100644 --- a/src/test/__init__.py +++ b/src/test/__init__.py @@ -1,14 +1,15 @@ -#!/usr/bin/env python +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University """ -file: __init__.py -author: adh -created_at: 9/27/23 3:56 PM +Provides test classes for SSVC. """ - - -def main(): - pass - - -if __name__ == "__main__": - main() diff --git a/src/test/test_cvss_helpers.py b/src/test/test_cvss_helpers.py new file mode 100644 index 00000000..193fb67a --- /dev/null +++ b/src/test/test_cvss_helpers.py @@ -0,0 +1,110 @@ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +import unittest + +import ssvc.decision_points.cvss.helpers as h +from ssvc.decision_points import SsvcDecisionPointValue +from ssvc.decision_points.cvss.base import CvssDecisionPoint + + +def fake_ms_impacts() -> list[CvssDecisionPoint]: + dps = [] + for key in ["MSC", "MSI", "MSA"]: + dp = CvssDecisionPoint( + name=f"{key} test", + description=f"{key} test", + version="1.0.0", + key=key, + values=( + SsvcDecisionPointValue( + name="None", + key="N", + description="No impact", + ), + SsvcDecisionPointValue( + name="Low", + key="L", + description="Low impact", + ), + SsvcDecisionPointValue( + name="High", + key="H", + description="High impact", + ), + ), + ) + dps.append(dp) + return dps + + +class MyTestCase(unittest.TestCase): + def setUp(self) -> None: + self.dps = [] + for i in range(3): + dp = CvssDecisionPoint( + name=f"test_{i}", + description=f"test_{i}", + version="1.0", + key="TDP{i}", + values=( + SsvcDecisionPointValue( + name=f"yes_{i}", + description=f"yes_{i}", + key=f"Y{i}", + ), + SsvcDecisionPointValue( + name=f"no_{i}", + description=f"no_{i}", + key=f"N{i}", + ), + ), + ) + self.dps.append(dp) + + def test_modify_3(self): + # version 3 just added "Modified" and "M" to the name and key + # and adds a "Not Defined" value with key "X" + for dp in self.dps: + modified = h.modify_3(dp) + self.assertTrue(modified.key.startswith("M")) + self.assertTrue(modified.name.startswith("Modified")) + + self.assertIn("Not Defined", [v.name for v in modified.values]) + self.assertIn("X", [v.key for v in modified.values]) + + def test_modify_4(self): + # _modify 4 assumes you've already done the Modify 3 step + # changes MSC, MSI, MSA "None" to "Negligible" + + dps = fake_ms_impacts() + + for dp in dps: + modified = h._modify_4(dp) + + self.assertIn("Negligible", [v.name for v in modified.values]) + self.assertNotIn("None", [v.name for v in modified.values]) + + # MSI should add "Safety" as the highest value + _msi = dps[1] + msi = h._modify_4(_msi) + + self.assertEqual("Safety", msi.values[-1].name) + + def test_modify_4_full(self): + self.test_modify_3() + self.test_modify_4() + + +if __name__ == "__main__": + unittest.main() diff --git a/src/test/test_dp_base.py b/src/test/test_dp_base.py index 4fcd7012..7d0214d4 100644 --- a/src/test/test_dp_base.py +++ b/src/test/test_dp_base.py @@ -40,7 +40,7 @@ def setUp(self) -> None: def tearDown(self) -> None: # restore the original registry - base.REGISTERED_DECISION_POINTS = self.original_registry + base._reset_registered() def test_registry(self): # just by creating the objects, they should be registered @@ -55,10 +55,6 @@ def test_registry(self): values=tuple(self.values), ) - def tearDown(self) -> None: - # restore the original registry - base.REGISTERED_DECISION_POINTS = self.original_registry - def test_registry(self): # just by creating the objects, they should be registered self.assertIn(self.dp, base.REGISTERED_DECISION_POINTS) diff --git a/src/test/test_dp_helpers.py b/src/test/test_dp_helpers.py new file mode 100644 index 00000000..97e06046 --- /dev/null +++ b/src/test/test_dp_helpers.py @@ -0,0 +1,172 @@ +# Copyright (c) 2023 Carnegie Mellon University and Contributors. +# - see Contributors.md for a full list of Contributors +# - see ContributionInstructions.md for information on how you can Contribute to this project +# Stakeholder Specific Vulnerability Categorization (SSVC) is +# licensed under a MIT (SEI)-style license, please see LICENSE.md distributed +# with this Software or contact permission@sei.cmu.edu for full terms. +# Created, in part, with funding and support from the United States Government +# (see Acknowledgments file). This program may include and/or can make use of +# certain third party source code, object code, documentation and other files +# (“Third Party Software”). See LICENSE.md for more details. +# Carnegie Mellon®, CERT® and CERT Coordination Center® are registered in the +# U.S. Patent and Trademark Office by Carnegie Mellon University + +import unittest +from copy import deepcopy + +from ssvc.decision_points import SsvcDecisionPoint, SsvcDecisionPointValue +from ssvc.decision_points.helpers import dp_diff + + +class MyTestCase(unittest.TestCase): + def setUp(self) -> None: + self.dp1 = SsvcDecisionPoint( + name="Test DP", + key="test_dp", + description="This is a test decision point", + version="1.0.0", + values=[ + SsvcDecisionPointValue( + name="Yes", + key="yes", + description="Yes", + ), + SsvcDecisionPointValue( + name="No", + key="no", + description="No", + ), + ], + ) + self.dp2 = deepcopy(self.dp1) + + def test_maybe_new_obj(self): + # ### Create a new object when + # * A different or new concept is being represented + + # if name, key, and description are the same, then it's not a new object + self.assertEqual(self.dp1.name, self.dp2.name) + self.assertEqual(self.dp1.key, self.dp2.key) + self.assertEqual(self.dp1.description, self.dp2.description) + + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertNotIn("new object", text) + + # if name, key, AND description are different, then it is maybe a new object + self.dp2.name = "New Test DP" + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertNotIn("new object", text) + + self.dp2.key = "new_test_dp" + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertNotIn("new object", text) + + self.dp2.description = "This is a new test decision point" + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + + # now that all three are different, it should suggest a new object + self.assertIn("new object", text) + + def test_major_version(self): + # ### Increment the Major Version when + # + # * Criteria for creating a new object are not met, _AND_ + # * existing values are removed, _OR_ + # * value semantics change in a way that older answers are no longer usable, + # _OR_ + # * new values are added that divide previous value semantics ambiguously + + # remove one + self.dp2.values = self.dp2.values[:-1] + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("major", text) + + # add one + self.dp2.values = list(self.dp1.values) + self.dp2.values.append( + SsvcDecisionPointValue( + name="Maybe", + key="maybe", + description="Maybe", + ) + ) + + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("major", text) + + def test_minor_version_when_new_option_added(self): + # ### Increment the Minor Version when + # * Criteria for incrementing the Major Version are not met, _AND_ + # * new options are added, _OR_ + # add one + self.dp2.values = list(self.dp1.values) + self.dp2.values.append( + SsvcDecisionPointValue( + name="Maybe", + key="maybe", + description="Maybe", + ) + ) + + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("minor", text) + + def test_minor_version_when_value_name_change(self): + # * value names or keys are changed, _OR_ + + self.dp2.values = deepcopy(self.dp1.values) + self.dp2.values[0].name = "New Yes" + + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("minor", text) + + def test_minor_version_when_value_key_changes(self): + self.dp2.values = deepcopy(self.dp1.values) + self.dp2.values[0].key = "new_yes" + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("minor", text) + + def test_minor_version_when_decision_point_name_changes(self): + # * the decision point name is changed + self.dp2.name = "New Test DP" + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("minor", text) + + def test_patch_version_when_typo_fixed(self): + # * typo fixes in option names or decision point name, _OR_ + self.dp2.name = "Test Dp" + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("patch", text) + + def test_patch_version_when_description_changes(self): + # ### Increment the Patch Version when + # * the decision point description changes in a way that does not affect + # semantics, _OR_ + + self.dp2.description = "This is a new test decision point" + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("patch", text) + + def test_patch_version_when_value_description_changes(self): + # * a value description changes in a way that does not affect semantics + self.dp2.values = deepcopy(self.dp1.values) + self.dp2.values[0].description = "New Yes" + results = dp_diff(self.dp1, self.dp2) + text = "\n".join(results) + self.assertIn("patch", text) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/test/test_schema.py b/src/test/test_schema.py index f4c830c7..401371ca 100644 --- a/src/test/test_schema.py +++ b/src/test/test_schema.py @@ -24,11 +24,10 @@ from ssvc.decision_points.critical_software import CRITICAL_SOFTWARE_1 # noqa from ssvc.decision_points.high_value_asset import HIGH_VALUE_ASSET_1 # noqa from ssvc.decision_points.in_kev import IN_KEV_1 +from ssvc.dp_groups.cvss.collections import CVSSv1, CVSSv2, CVSSv3, CVSSv4 # noqa + # importing these causes the decision points to register themselves -from ssvc.dp_groups.ssvc.collections import SSVCv1, SSVCv2, SSVCv2_1 # noqa -from ssvc.dp_groups.cvss.v1 import CVSSv1 # noqa -from ssvc.dp_groups.cvss.v2 import CVSSv2 # noqa -from ssvc.dp_groups.cvss.v3 import CVSSv3 # noqa +from ssvc.dp_groups.ssvc.collections import SSVCv1, SSVCv2, SSVCv2_1 # noqa def find_schema(basepath: str) -> str: @@ -49,15 +48,20 @@ def setUp(self) -> None: logger.addHandler(hdlr) self.logger = logger + self.dpgs = [SSVCv1, SSVCv2, SSVCv2_1, CVSSv1, CVSSv2, CVSSv3, CVSSv4] + def test_confirm_registered_decision_points(self): dps = list(REGISTERED_DECISION_POINTS) self.assertGreater(len(dps), 0) - extras = [CRITICAL_SOFTWARE_1, HIGH_VALUE_ASSET_1, IN_KEV_1] - for dpg in [SSVCv1, SSVCv2, SSVCv2_1, extras]: + for dpg in self.dpgs: for dp in dpg: self.assertIn(dp, REGISTERED_DECISION_POINTS) + extras = [CRITICAL_SOFTWARE_1, HIGH_VALUE_ASSET_1, IN_KEV_1] + for dp in extras: + self.assertIn(dp, REGISTERED_DECISION_POINTS) + def test_decision_point_validation(self): # path relative to top level of repo schema_file = find_schema("data/schema/Decision_Point.schema.json") @@ -85,7 +89,7 @@ def test_decision_point_group_validation(self): schema_file = find_schema("data/schema/Decision_Point_Group.schema.json") schema = json.load(open(schema_file)) - for dpg in (SSVCv1, SSVCv2, SSVCv2_1): + for dpg in self.dpgs: exp = None as_json = dpg.to_json() loaded = json.loads(as_json)