aboutsummaryrefslogtreecommitdiff
path: root/cvss/v3metric.go
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2022-02-17 20:28:58 -0500
committerPaul Duncan <pabs@pablotron.org>2022-02-17 20:28:58 -0500
commitd4b400e50e02e668b92806a4e20c8c9f643dd491 (patch)
tree5ced786ff0d2dfcb186e7210c26322a7676ed5e3 /cvss/v3metric.go
parent47d25cba0fa216342ce3cc5f1cb3a8bd8d17c824 (diff)
downloadcvez-d4b400e50e02e668b92806a4e20c8c9f643dd491.tar.bz2
cvez-d4b400e50e02e668b92806a4e20c8c9f643dd491.zip
cvss: move v31 utility functions to work with all 3.x vectors
Diffstat (limited to 'cvss/v3metric.go')
-rw-r--r--cvss/v3metric.go181
1 files changed, 180 insertions, 1 deletions
diff --git a/cvss/v3metric.go b/cvss/v3metric.go
index c0f00be..b4bb89b 100644
--- a/cvss/v3metric.go
+++ b/cvss/v3metric.go
@@ -1,5 +1,9 @@
package cvss
+import (
+ "math"
+)
+
//go:generate stringer -linecomment -type=v3Metric
// metric value
@@ -324,7 +328,7 @@ func (m v3Metric) Key() Key {
}
}
-// Convert string to CVSS 3.1 metric.
+// Convert string to CVSS 3.x metric.
func getV3Metric(version Version, s string) (v3Metric, error) {
if m, ok := v3MetricStrLut[s]; ok {
return m, nil
@@ -332,3 +336,178 @@ func getV3Metric(version Version, s string) (v3Metric, error) {
return v3InvalidMetric, newBadMetric(version, s)
}
}
+
+// Does the map have at least one of the keys needed for a temporal
+// score defined?
+func hasV3TemporalScoreKeys(keys map[Key]v3Metric) bool {
+ ecm, ecm_ok := keys[v3ExploitCodeMaturity] // E
+ rl, rl_ok := keys[v3RemediationLevel] // RL
+ rc, rc_ok := keys[v3ReportConfidence] // RC
+
+ return (ecm_ok && ecm != v3ENotDefined) ||
+ (rl_ok && rl != v3RLNotDefined) ||
+ (rc_ok && rc != v3RCNotDefined)
+}
+
+// Does the map have at least one of the keys needed for an env score to
+// be defined?
+func hasV3EnvScoreKeys(keys map[Key]v3Metric) bool {
+ mav, mav_ok := keys[v3ModifiedAttackVector] // MAV
+ mac, mac_ok := keys[v3ModifiedAttackComplexity] // MAC
+ mpr, mpr_ok := keys[v3ModifiedPrivilegesRequired] // MPR
+ mui, mui_ok := keys[v3ModifiedUserInteraction] // MUI
+ ms, ms_ok := keys[v3ModifiedScope] // MS
+ mc, mc_ok := keys[v3ModifiedConfidentiality] // MC
+ mi, mi_ok := keys[v3ModifiedIntegrity] // MI
+ ma, ma_ok := keys[v3ModifiedAvailability] // MA
+ cr, cr_ok := keys[v3ConfidentialityRequirement] // CR
+ ir, ir_ok := keys[v3IntegrityRequirement] // IR
+ ar, ar_ok := keys[v3AvailabilityRequirement] // AR
+
+ return (mav_ok && mav != v3MAVNotDefined) ||
+ (mac_ok && mac != v3MACNotDefined) ||
+ (mpr_ok && mpr != v3MPRNotDefined) ||
+ (mui_ok && mui != v3MUINotDefined) ||
+ (ms_ok && ms != v3MSNotDefined) ||
+ (mc_ok && mc != v3MCNotDefined) ||
+ (mi_ok && mi != v3MINotDefined) ||
+ (ma_ok && ma != v3MANotDefined) ||
+ (cr_ok && cr != v3CRNotDefined) ||
+ (ir_ok && ir != v3IRNotDefined) ||
+ (ar_ok && ar != v3ARNotDefined);
+}
+
+// roundup implemention (from CVSS v3.1 spec, appendix A)
+func roundup(val float64) float64 {
+ return math.Ceil(10.0 * val) / 10.0
+}
+
+var v3MetricCoefs = map[v3Metric]float64 {
+ v3AVNetwork: 0.85, // AV:N
+ v3AVAdjacentNetwork: 0.62, // AV:A
+ v3AVLocal: 0.55, // AV:L
+ v3AVPhysical: 0.2, // AV:P
+
+ v3ACLow: 0.77, // AC:L
+ v3ACHigh: 0.44, // AC:H
+
+ v3PRNone: 0.85, // PR:N
+ v3PRLow: 0.62, // PR:L
+ v3PRHigh: 0.27, // PR:H
+
+ v3UINone: 0.85, // UI:N
+ v3UIRequired: 0.62, // UI:R
+
+ v3CHigh: 0.56, // C:H
+ v3CLow: 0.22, // C:L
+ v3CNone: 0.0, // C:N
+
+ v3IHigh: 0.56, // I:H
+ v3ILow: 0.22, // I:L
+ v3INone: 0.0, // I:N
+
+ v3AHigh: 0.56, // A:H
+ v3ALow: 0.22, // A:L
+ v3ANone: 0.0, // A:N
+
+ v3ENotDefined: 1.0, // E:X
+ v3EHigh: 1.0, // E:H
+ v3EFunctional: 0.97, // E:F
+ v3EProofOfConcept: 0.94, // E:P
+ v3EUnproven: 0.91, // E:U
+
+ v3RLNotDefined: 1.0, // RL:X
+ v3RLUnavailable: 1.0, // RL:U
+ v3RLWorkaround: 0.97, // RL:W
+ v3RLTemporaryFix: 0.96, // RL:T
+ v3RLOfficialFix: 0.95, // RL:O
+
+ v3RCNotDefined: 1.0, // RC:X
+ v3RCConfirmed: 1.0, // RC:C
+ v3RCReasonable: 0.96, // RC:R
+ v3RCUnknown: 0.92, // RC:U
+
+ v3CRNotDefined: 1.0, // CR:X
+ v3CRHigh: 1.5, // CR:H
+ v3CRMedium: 1.0, // CR:M
+ v3CRLow: 0.5, // CR:L
+
+ v3IRNotDefined: 1.0, // IR:X
+ v3IRHigh: 1.5, // IR:H
+ v3IRMedium: 1.0, // IR:M
+ v3IRLow: 0.5, // IR:L
+
+ v3ARNotDefined: 1.0, // AR:X
+ v3ARHigh: 1.5, // AR:H
+ v3ARMedium: 1.0, // AR:M
+ v3ARLow: 0.5, // AR:L
+
+ v3MAVNotDefined: 1.0, // MAV:X
+ v3MAVNetwork: 0.85, // MAV:N
+ v3MAVAdjacentNetwork: 0.62, // MAV:A
+ v3MAVLocal: 0.55, // MAV:L
+ v3MAVPhysical: 0.2, // MAV:P
+
+ v3MACNotDefined: 1.0, // MAC:X
+ v3MACLow: 0.77, // MAC:L
+ v3MACHigh: 0.44, // MAC:H
+
+ v3MPRNotDefined: 1.0, // MPR:X
+ v3MPRNone: 0.85, // MPR:N
+ v3MPRLow: 0.62, // MPR:L
+ v3MPRHigh: 0.27, // MPR:H
+
+ v3MUINotDefined: 1.0, // MUI:X
+ v3MUINone: 0.85, // MUI:N
+ v3MUIRequired: 0.62, // MUI:R
+
+ v3MCNotDefined: 1.0, // MC:X
+ v3MCHigh: 0.56, // MC:H
+ v3MCLow: 0.22, // MC:L
+ v3MCNone: 0.0, // MC:N
+
+ v3MINotDefined: 1.0, // MI:X
+ v3MIHigh: 0.56, // MI:H
+ v3MILow: 0.22, // MI:L
+ v3MINone: 0.0, // MI:N
+
+ v3MANotDefined: 1.0, // MA:X
+ v3MAHigh: 0.56, // MA:H
+ v3MALow: 0.22, // MA:L
+ v3MANone: 0.0, // MA:N
+}
+
+// map of modified metrics to not defined value and base key
+var v3ModMetricDefaults = map[v3Key]struct {
+ notDefined v3Metric
+ baseKey v3Key
+} {
+ v3ModifiedAttackVector: { v3MAVNotDefined, v3AttackVector },
+ v3ModifiedAttackComplexity: { v3MACNotDefined, v3AttackComplexity },
+ v3ModifiedUserInteraction: { v3MUINotDefined, v3UserInteraction },
+ v3ModifiedConfidentiality: { v3MCNotDefined, v3Confidentiality },
+ v3ModifiedIntegrity: { v3MINotDefined, v3Integrity },
+ v3ModifiedAvailability: { v3MANotDefined, v3Availability },
+}
+
+// Get modified metric coefficient, or fall back to base coefficient if
+// modified metric is not defined.
+func getV3ModCoef(keys map[Key]v3Metric, key v3Key) float64 {
+ d := v3ModMetricDefaults[key]
+ if v, _ := keys[key]; v != d.notDefined {
+ // return modified metric coefficient
+ return v3MetricCoefs[v]
+ } else {
+ // return base coefficient
+ return v3MetricCoefs[keys[d.baseKey]]
+ }
+}
+
+var v3PrivReqCoefs = map[v3Metric]map[bool]float64 {
+ v3PRNone: map[bool]float64 { false: 0.85, true: 0.85 },
+ v3PRLow: map[bool]float64 { false: 0.62, true: 0.68 },
+ v3PRHigh: map[bool]float64 { false: 0.27, true: 0.50 },
+ v3MPRNone: map[bool]float64 { false: 0.85, true: 0.85 },
+ v3MPRLow: map[bool]float64 { false: 0.62, true: 0.68 },
+ v3MPRHigh: map[bool]float64 { false: 0.27, true: 0.50 },
+}