nvd_cvss/v4/
exploit_maturity.rs

1use crate::error::{CVSSError, Result};
2use crate::metric::{Help, Metric, MetricType, MetricTypeV4, Worth};
3use serde::{Deserialize, Serialize};
4use std::fmt::{Display, Formatter};
5use std::str::FromStr;
6
7#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
8#[serde(rename_all = "UPPERCASE")]
9pub enum ExploitMaturity {
10  /// NotDefined(X) 未定义 ;可靠的威胁情报无法确定漏洞利用成熟度特征。这是默认值,在假设最坏情况的情况下计算分数时,等效于Attacked(A)。
11  NotDefined,
12  /// Attacked(A) 已报告针对此漏洞的攻击;简化利用该漏洞的尝试解决方案已公开(或私下可用)。
13  Attacked,
14  /// POC(P) POC已公开;且未感知到针对此漏洞的利用尝试;且未感知到简化利用该漏洞的尝试的公开可用解决方案
15  Poc,
16  /// Unreported(U) 未感知到POC公开;且未感知到针对此漏洞的利用尝试;且未感知到简化利用该漏洞的尝试的公开可用解决方案。
17  Unreported,
18}
19
20impl Default for ExploitMaturity {
21  fn default() -> Self {
22    // If E=X it will default to the worst case (i.e., E=A).
23    Self::Attacked
24  }
25}
26impl ExploitMaturity {
27  // EQ5: 0-E:A
28  //      1-E:P
29  //      2-E:U
30  pub(crate) fn eq5(&self) -> Option<u32> {
31    match self {
32      Self::NotDefined => None,
33      Self::Attacked => Some(0),
34      Self::Poc => Some(1),
35      Self::Unreported => Some(2),
36    }
37  }
38}
39
40impl FromStr for ExploitMaturity {
41  type Err = CVSSError;
42
43  fn from_str(s: &str) -> Result<Self> {
44    let name = Self::name();
45    let s = s.to_uppercase();
46    let (_name, v) = s
47      .split_once(&format!("{}:", name))
48      .ok_or(CVSSError::InvalidCVSS {
49        key: name.to_string(),
50        value: s.to_string(),
51        expected: name.to_string(),
52      })?;
53    let c = v.chars().next();
54    match c {
55      Some('A') => Ok(Self::Attacked),
56      Some('P') => Ok(Self::Poc),
57      Some('U') => Ok(Self::Unreported),
58      Some('X') => Ok(Self::NotDefined),
59      _ => Err(CVSSError::InvalidCVSS {
60        key: name.to_string(),
61        value: format!("{:?}", c),
62        expected: "A,P,U,X".to_string(),
63      }),
64    }
65  }
66}
67
68impl Display for ExploitMaturity {
69  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
70    write!(f, "{}:{}", Self::name(), self.as_str())
71  }
72}
73
74impl Metric for ExploitMaturity {
75  const TYPE: MetricType = MetricType::V4(MetricTypeV4::E);
76
77  fn help(&self) -> Help {
78    match self {
79      Self::NotDefined => Help {
80        worth: Worth::Worst,
81        des: "".to_string(),
82      },
83      Self::Attacked => Help {
84        worth: Worth::Worst,
85        des: "".to_string(),
86      },
87      Self::Poc => Help {
88        worth: Worth::Worst,
89        des: "".to_string(),
90      },
91      Self::Unreported => Help {
92        worth: Worth::Worst,
93        des: "".to_string(),
94      },
95    }
96  }
97
98  fn score(&self) -> f32 {
99    match self {
100      Self::NotDefined => 0.0,
101      Self::Attacked => 0.0,
102      Self::Poc => 0.1,
103      Self::Unreported => 0.2,
104    }
105  }
106
107  fn as_str(&self) -> &'static str {
108    match self {
109      Self::NotDefined => "X",
110      Self::Attacked => "A",
111      Self::Poc => "P",
112      Self::Unreported => "N",
113    }
114  }
115}