CVSS 4.0 分数计算公式
1.CVSS 4.0 分数计算公式
| CVSS名称 | CVSS 指标 |
|---|---|
| CVSS-B | 基础指标 |
| CVSS-BE | 基础和环境指标 |
| CVSS-BT | 基础和威胁指标 |
| CVSS-BTE | 基础、威胁和环境指标 |
1.1 各指标内容及说明
1.1.1 基本指标
1.1.1.1 利用难度指标
| 名称 | 指标 | 默认 |
|---|---|---|
| 攻击向量 (AV) | 网络(N)/相邻网络(A)/本地网络(L) | N |
| 攻击复杂度 (AC) | 低 (L)/高(H) | L |
| 攻击要求 (AT) | 无 (N)/存在 § | N |
| 特权要求 (PR) | 无 (N)/低 (L)/高 (H) | N |
| 交互 (UI) | 无 (N)/被动的 §/主动的 (A) | N |
1.1.1.2 易受攻击系统影响指标
| 名称 | 指标 | 默认 |
|---|---|---|
| 机密性 (VC) | 高 (H)/低 (L)/无 (N) | N |
| 完整性 (VI) | 高 (H)/低 (L)/无 (N) | N |
| 可用性 (VA) | 高 (H)/低 (L)/无 (N) | N |
1.1.1.3 后续影响指标
| 名称 | 指标 | 默认 |
|---|---|---|
| 机密性 (SC) | 高 (H)/低 (L)/无 (N) | N |
| 完整性 (SI) | 高 (H)/低 (L)/无 (N) | N |
| 可用性 (SA) | 高 (H)/低 (L)/无 (N) | N |
1.1.2 补充指标
| 名称 | 指标 | 默认 |
|---|---|---|
| 安全 (S) | 未定义 (X)/可忽略的 (N)/存在的 § | X |
| 自动化 (AU) | 未定义 (X)/否(N)/是 (Y) | X |
| 恢复性 ® | 未定义 (X)/自动的 (A)/用户 (U)/不可恢复 (I) | X |
| 价值密度 (V) | 未定义 (X)/分散性 (D)/集中性 © | X |
| 漏洞响应工作 (RE) | 未定义 (X)/低 (L)/中 (M)/高 (H) | X |
| 供应商紧急性 (U) | 未定义 (X)/无(Clear)/低(Green)/中(Amber)/高(Red) | X |
1.1.3 环境-修改的基本指标
1.1.3.1 可利用性指标
| 名称 | 指标 | 默认 |
|---|---|---|
| 攻击向量 (MAV) | 未定义 (X)/网络 (N)/相邻 (A)/本地 (L)/物理 § | X |
| 攻击复杂度 (MAC) | 未定义 (X)/低 (L)/高 (H) | X |
| 攻击要求 (MAT) | 未定义 (X)/无 (N)/存在 § | X |
| 所需权限 (MPR) | 未定义 (X)/无 (N)/低 (L)/高 (H) | X |
| 用户交互 (MUI) | 未定义 (X)/None (N)/Passive §/Active (A) | X |
1.1.3.2 易受攻击系统影响指标
| 名称 | 指标 | 默认 |
|---|---|---|
| 机密性 (MVC) | 未定义 (X)/高 (H)/低 (L)/无 (N) | X |
| 完整性 (MVI) | 未定义 (X)/高 (H)/低 (L)/无 (N) | X |
| 可用性 (MVA) | 未定义 (X)/高 (H)/低 (L)/无 (N) | X |
1.1.3.3 后续系统影响性
| 名称 | 指标 | 默认 |
|---|---|---|
| 机密性 (MSC) | 未定义 (X)/高 (H)/低 (L)/可忽略 (N) | X |
| 完整性 (MSI) | 未定义 (X)/安全 (S)/高 (H)/低 (L)/可忽略 (N) | X |
| 可用性 (MSA) | 未定义 (X)/安全 (S)/高 (H)/低 (L)/可忽略 (N) | X |
1.1.4 环境-安全要求
| 名称 | 指标 | 默认 |
|---|---|---|
| 机密要求 (CR) | 未定义 (X)/高 (H)/中 (M)/低 (L) | X |
| 完整性要求 (IR) | 未定义 (X)/高 (H)/中 (M)/低 (L) | X |
| 可用性要求 (AR) | 未定义 (X)/高 (H)/中 (M)/低 (L) | X |
1.1.5 威胁指标
| 名称 | 指标 | 默认 |
|---|---|---|
| 利用情报 (E) | 未定义 (X)/在野利用 (A)/概念验证 §/无报告 (U) | X |
1.2.基本指标、威胁指标、环境和补充指标–
CVSS-BTE分数 = 基础 MacroVector 分数 - (基础分数 - 相邻低分)×(指标距离 / 组内最大距离)
1.2.1.确定等价类(EQ)级别
将指标分为 6 个等价类,每个 EQ 对应不同的指标组合,其级别由指标值决定:
EQ1:Attack Vector (AV)-攻击向量、Privileges Required (PR)-所需权限要求、User Interaction (UI)-用户交互
EQ2:Attack Complexity (AC)-攻击复杂性、Attack Requirements (AT)-攻击要求
EQ3:Vulnerable System Confidentiality (VC)-易受攻击系统的机(保)密性影响、Integrity (VI)-易受攻击系统的完整性影响、Availability (VA)-易受攻击系统的可用性影响
EQ4:Subsequent System Confidentiality (SC)-后续系统的机(保)密性影响、Integrity (SI)-后续系统的完整性影响、Availability (SA)-后续系统的可用性影响,以及 Safety (S)-安全性
EQ5:Exploit Maturity (E)-威胁指标利用成熟度
EQ6:VC/VI/VA 与 Confidentiality Requirement (CR)-机(保)密性、Integrity Requirement (IR)-完整性、Availability Requirement (AR)-可用性 的组合(+的关系)
1.2.2.确定 MacroVector 及其基础分数
每个 MacroVector 由各 EQ 的级别组合定义,其基础分数通过专家评估预先确定,存储在 cvss_lookup.js 文件中
通过各 EQ 的级别组合,确定向量所属的 MacroVector(等价类集合)
一般通过 cvss_lookup 查询获取
1.2.3.计算指标距离与分数调整
对于目标向量,计算其与所在 MacroVector 中最高严重性向量的 严重性距离(Severity Distance),即通过改变单个指标值使其转化为最高严重性向量所需的步骤数。
1.2.4. 计算最终分数
步骤 1:确定 MacroVector 的基础分数 S_macro。
步骤 2:计算目标向量在 MacroVector 内的深度 D(即该 MacroVector 中最高与最低向量的最大距离)。
步骤 3:计算目标向量与最高向量的距离 d。
步骤 4:计算调整因子 f = d / D,若 D=0(无距离),则 f=0。
步骤 5:最终分数 S = S_macro - (S_macro - S_lower) × f,其中 S_lower 为相邻较低 MacroVector 的分数,若无则忽略。
步骤 6:分数四舍五入到一位小数。
1.3.计算逻辑
1.3.1 以go语言为例:
1.3.1.1. 首先会获取到一个选中的cvss4的评分向量,
如:CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N
暂定变量VectorString,代码:
VectorString :="CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N"
1.3.1.2. 由于CVSS4的指标一共有31个,
这里需要判断评分向量数据是否异常,且补充默认项
定义所有默认项:
var allCvssSelected = map[string]string{"AC": "L", "AR": "X", "AT": "N", "AU": "X", "AV": "N", "CR": "X", "E": "X", "IR": "X", "MAC": "X", "MAT": "X", "MAV": "X", "MPR": "X", "MSA": "X", "MSC": "X", "MSI": "X", "MUI": "X", "MVA": "X", "MVC": "X", "MVI": "X", "PR": "N", "R": "X", "RE": "X", "S": "X", "SA": "N", "SC": "N", "SI": "N", "U": "X", "UI": "N", "V": "X", "VA": "N", "VC": "N", "VI": "N"}
这里要判断VectorString的数据正确,然后替换到默认项allCvssSelected,如
cvssSelected:=GetCvssSelected(VectorString)
具体GetCvssSelected实现很简单,参考坐标### 1.1.1 基本指标,这里需要定义一个包含31个指标的Map用于校验key和value;如:
var ExpectedMetricOrder = map[string][]string{
// 基础指标组 (11 个指标)
"AV": {"N", "A", "L", "P"}, // Attack Vector
"AC": {"L", "H"}, // Attack Complexity
"AT": {"N", "P"}, // Attack Requirements
"PR": {"N", "L", "H"}, // Privileges Required
"UI": {"N", "P", "A"}, // User Interaction
"VC": {"H", "L", "N"}, // Confidentiality Impact
"VI": {"H", "L", "N"}, // Integrity Impact
"VA": {"H", "L", "N"}, // Availability Impact
"SC": {"H", "L", "N"}, // Confidentiality Requirement
"SI": {"H", "L", "N"}, // Integrity Requirement
"SA": {"H", "L", "N"}, // Availability Requirement
// 威胁指标组 (1 个指标)
"E": {"X", "A", "P", "U"}, // Exploit Code Maturity
// 环境指标组 (14 个指标)
"CR": {"X", "H", "M", "L"}, // Confidentiality Requirement
"IR": {"X", "H", "M", "L"}, // Integrity Requirement
"AR": {"X", "H", "M", "L"}, // Availability Requirement
"MAV": {"X", "N", "A", "L", "P"}, // Modified Attack Vector
"MAC": {"X", "L", "H"}, // Modified Attack Complexity
"MAT": {"X", "N", "P"}, // Modified Attack Requirements
"MPR": {"X", "N", "L", "H"}, // Modified Privileges Required
"MUI": {"X", "N", "P", "A"}, // Modified User Interaction
"MVC": {"X", "H", "L", "N"}, // Modified Confidentiality Impact
"MVI": {"X", "H", "L", "N"}, // Modified Integrity Impact
"MVA": {"X", "H", "L", "N"}, // Modified Availability Impact
"MSC": {"X", "H", "L", "N"}, // Modified Confidentiality Requirement
"MSI": {"X", "S", "H", "L", "N"}, // Modified Integrity Requirement
"MSA": {"X", "S", "H", "L", "N"}, // Modified Availability Requirement
// 补充指标组 (6 个指标)
"S": {"X", "N", "P"}, // Security Requirements
"AU": {"X", "N", "Y"}, // Authentication
"R": {"X", "A", "U", "I"}, // Remediation Level
"V": {"X", "D", "C"}, // Report Confidence
"RE": {"X", "L", "M", "H"}, // Vulnerability Response Effort
"U": {"X", "Clear", "Green", "Amber", "Red"}, // User Notes
}
具体判断和覆盖默认值逻辑实现,常规判断自己处理好
func GetCvssSelected(vector string) (map[string]string, error) {
if len(vector) > 0 && vector[0] == '#' {
vector = vector[1:]
}
if !strings.HasPrefix(vector, "CVSS:4.0") {
return nil, fmt.Errorf("invalid vector, missing CVSS:4.0 prefix")
}
metrics := strings.Split(vector, "/")
if len(metrics) < 2 {
return nil, fmt.Errorf("invalid vector format after splitting")
}
metrics = metrics[1:]
toSelect := make(map[string]string, len(metrics))
for _, metricStr := range metrics {
parts := strings.Split(metricStr, ":")
if len(parts) != 2 {
return nil, fmt.Errorf("invalid metric format: %s", metricStr)
}
key, value := parts[0], parts[1]
expected, ok := ExpectedMetricOrder[key]
if !ok || expected == nil {
return nil, fmt.Errorf("invalid vector, unexpected metric key: %s", key)
}
expectedMap := make(map[string]bool, len(expected))
for _, v := range expected {
expectedMap[v] = true
}
if !expectedMap[value] {
return nil, fmt.Errorf("invalid vector, for key %s, value is invalid", key)
}
toSelect[key] = value
}
reSelect := allCvssSelected
for kt, vt := range toSelect {
reSelect[kt] = vt
}
return reSelect, nil
}
1.3.1.3. MacroVector 分数查找表,一般定义为CvssLookup
var CvssLookup = map[string]float64{"000000": 10, "000001": 9.9, "000010": 9.8, "000011": 9.5, "000020": 9.5, "000021": 9.2, "000100": 10, "000101": 9.6, "000110": 9.3, "000111": 8.7, "000120": 9.1, "000121": 8.1, "000200": 9.3, "000201": 9, "000210": 8.9, "000211": 8, "000220": 8.1, "000221": 6.8, "001000": 9.8, "001001": 9.5, "001010": 9.5, "001011": 9.2, "001020": 9, "001021": 8.4, "001100": 9.3, "001101": 9.2, "001110": 8.9, "001111": 8.1, "001120": 8.1, "001121": 6.5, "001200": 8.8, "001201": 8, "001210": 7.8, "001211": 7, "001220": 6.9, "001221": 4.8, "002001": 9.2, "002011": 8.2, "002021": 7.2, "002101": 7.9, "002111": 6.9, "002121": 5, "002201": 6.9, "002211": 5.5, "002221": 2.7, "010000": 9.9, "010001": 9.7, "010010": 9.5, "010011": 9.2, "010020": 9.2, "010021": 8.5, "010100": 9.5, "010101": 9.1, "010110": 9, "010111": 8.3, "010120": 8.4, "010121": 7.1, "010200": 9.2, "010201": 8.1, "010210": 8.2, "010211": 7.1, "010220": 7.2, "010221": 5.3, "011000": 9.5, "011001": 9.3, "011010": 9.2, "011011": 8.5, "011020": 8.5, "011021": 7.3, "011100": 9.2, "011101": 8.2, "011110": 8, "011111": 7.2, "011120": 7, "011121": 5.9, "011200": 8.4, "011201": 7, "011210": 7.1, "011211": 5.2, "011220": 5, "011221": 3, "012001": 8.6, "012011": 7.5, "012021": 5.2, "012101": 7.1, "012111": 5.2, "012121": 2.9, "012201": 6.3, "012211": 2.9, "012221": 1.7, "100000": 9.8, "100001": 9.5, "100010": 9.4, "100011": 8.7, "100020": 9.1, "100021": 8.1, "100100": 9.4, "100101": 8.9, "100110": 8.6, "100111": 7.4, "100120": 7.7, "100121": 6.4, "100200": 8.7, "100201": 7.5, "100210": 7.4, "100211": 6.3, "100220": 6.3, "100221": 4.9, "101000": 9.4, "101001": 8.9, "101010": 8.8, "101011": 7.7, "101020": 7.6, "101021": 6.7, "101100": 8.6, "101101": 7.6, "101110": 7.4, "101111": 5.8, "101120": 5.9, "101121": 5, "101200": 7.2, "101201": 5.7, "101210": 5.7, "101211": 5.2, "101220": 5.2, "101221": 2.5, "102001": 8.3, "102011": 7, "102021": 5.4, "102101": 6.5, "102111": 5.8, "102121": 2.6, "102201": 5.3, "102211": 2.1, "102221": 1.3, "110000": 9.5, "110001": 9, "110010": 8.8, "110011": 7.6, "110020": 7.6, "110021": 7, "110100": 9, "110101": 7.7, "110110": 7.5, "110111": 6.2, "110120": 6.1, "110121": 5.3, "110200": 7.7, "110201": 6.6, "110210": 6.8, "110211": 5.9, "110220": 5.2, "110221": 3, "111000": 8.9, "111001": 7.8, "111010": 7.6, "111011": 6.7, "111020": 6.2, "111021": 5.8, "111100": 7.4, "111101": 5.9, "111110": 5.7, "111111": 5.7, "111120": 4.7, "111121": 2.3, "111200": 6.1, "111201": 5.2, "111210": 5.7, "111211": 2.9, "111220": 2.4, "111221": 1.6, "112001": 7.1, "112011": 5.9, "112021": 3, "112101": 5.8, "112111": 2.6, "112121": 1.5, "112201": 2.3, "112211": 1.3, "112221": 0.6, "200000": 9.3, "200001": 8.7, "200010": 8.6, "200011": 7.2, "200020": 7.5, "200021": 5.8, "200100": 8.6, "200101": 7.4, "200110": 7.4, "200111": 6.1, "200120": 5.6, "200121": 3.4, "200200": 7, "200201": 5.4, "200210": 5.2, "200211": 4, "200220": 4, "200221": 2.2, "201000": 8.5, "201001": 7.5, "201010": 7.4, "201011": 5.5, "201020": 6.2, "201021": 5.1, "201100": 7.2, "201101": 5.7, "201110": 5.5, "201111": 4.1, "201120": 4.6, "201121": 1.9, "201200": 5.3, "201201": 3.6, "201210": 3.4, "201211": 1.9, "201220": 1.9, "201221": 0.8, "202001": 6.4, "202011": 5.1, "202021": 2, "202101": 4.7, "202111": 2.1, "202121": 1.1, "202201": 2.4, "202211": 0.9, "202221": 0.4, "210000": 8.8, "210001": 7.5, "210010": 7.3, "210011": 5.3, "210020": 6, "210021": 5, "210100": 7.3, "210101": 5.5, "210110": 5.9, "210111": 4, "210120": 4.1, "210121": 2, "210200": 5.4, "210201": 4.3, "210210": 4.5, "210211": 2.2, "210220": 2, "210221": 1.1, "211000": 7.5, "211001": 5.5, "211010": 5.8, "211011": 4.5, "211020": 4, "211021": 2.1, "211100": 6.1, "211101": 5.1, "211110": 4.8, "211111": 1.8, "211120": 2, "211121": 0.9, "211200": 4.6, "211201": 1.8, "211210": 1.7, "211211": 0.7, "211220": 0.8, "211221": 0.2, "212001": 5.3, "212011": 2.4, "212021": 1.4, "212101": 2.4, "212111": 1.2, "212121": 0.5, "212201": 1, "212211": 0.3, "212221": 0.1}
1.3 最终实现CVSS评分方法
func CalculateScore(VectorString string) float64 {
cvssSelected, _ := GetCvssSelected(VectorString)
impactMetrics := []string{"VC", "VI", "VA", "SC", "SI", "SA"}
allN := true
for _, metric := range impactMetrics {
if M(cvssSelected, metric) != "N" {
allN = false
break
}
}
if allN {
return 0.0
}
macroVectorResult := MacroVector(cvssSelected)
if len(macroVectorResult) != 6 {
return 0.0
}
value := CvssLookup[macroVectorResult]
chars := strings.Split(macroVectorResult, "")
eq1, _ := strconv.Atoi(chars[0])
eq2, _ := strconv.Atoi(chars[1])
eq3, _ := strconv.Atoi(chars[2])
eq4, _ := strconv.Atoi(chars[3])
eq5, _ := strconv.Atoi(chars[4])
eq6, _ := strconv.Atoi(chars[5])
eq1NextLowerMacro := fmt.Sprintf("%d%d%d%d%d%d", eq1+1, eq2, eq3, eq4, eq5, eq6)
eq2NextLowerMacro := fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2+1, eq3, eq4, eq5, eq6)
var eq3eq6NextLowerMacro string
if eq3 == 1 && eq6 == 1 {
eq3eq6NextLowerMacro = fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2, eq3+1, eq4, eq5, eq6)
} else if eq3 == 0 && eq6 == 1 {
eq3eq6NextLowerMacro = fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2, eq3+1, eq4, eq5, eq6)
} else if eq3 == 1 && eq6 == 0 {
eq3eq6NextLowerMacro = fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2, eq3, eq4, eq5, eq6+1)
} else if eq3 == 0 && eq6 == 0 {
left := fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2, eq3, eq4, eq5, eq6+1)
right := fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2, eq3+1, eq4, eq5, eq6)
scoreLeft := CvssLookup[left]
scoreRight := CvssLookup[right]
if scoreLeft > scoreRight {
eq3eq6NextLowerMacro = left
} else {
eq3eq6NextLowerMacro = right
}
} else {
eq3eq6NextLowerMacro = fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2, eq3+1, eq4, eq5, eq6+1)
}
eq4NextLowerMacro := fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2, eq3, eq4+1, eq5, eq6)
eq5NextLowerMacro := fmt.Sprintf("%d%d%d%d%d%d", eq1, eq2, eq3, eq4, eq5+1, eq6)
scoreEq1NextLowerMacro := CvssLookup[eq1NextLowerMacro]
scoreEq2NextLowerMacro := CvssLookup[eq2NextLowerMacro]
scoreEq3eq6NextLowerMacro := CvssLookup[eq3eq6NextLowerMacro]
scoreEq4NextLowerMacro := CvssLookup[eq4NextLowerMacro]
scoreEq5NextLowerMacro := CvssLookup[eq5NextLowerMacro]
eq1Maxes := getEQMaxes(1, eq1)
eq2Maxes := getEQMaxes(2, eq2)
eq3eq6Maxes := getEQMaxes3(eq3, eq6)
eq4Maxes := getEQMaxes(4, eq4)
eq5Maxes := getEQMaxes(5, eq5)
maxVectors := make([]string, 0)
for _, eq1Max := range eq1Maxes {
for _, eq2Max := range eq2Maxes {
for _, eq3eq6Max := range eq3eq6Maxes {
for _, eq4Max := range eq4Maxes {
for _, eq5Max := range eq5Maxes {
maxVectors = append(maxVectors, fmt.Sprintf("%s%s%s%s%s",
eq1Max, eq2Max, eq3eq6Max, eq4Max, eq5Max))
}
}
}
}
}
var maxVector string
var severityDistanceAV, severityDistancePR, severityDistanceUI,
severityDistanceAC, severityDistanceAT,
severityDistanceVC, severityDistanceVI, severityDistanceVA,
severityDistanceSC, severityDistanceSI, severityDistanceSA,
severityDistanceCR, severityDistanceIR, severityDistanceAR float64
for _, mv := range maxVectors {
severityDistanceAV = AVLevels[M(cvssSelected, "AV")] - AVLevels[ExtractValueMetric("AV", mv)]
severityDistancePR = PRLevels[M(cvssSelected, "PR")] - PRLevels[ExtractValueMetric("PR", mv)]
severityDistanceUI = UILevels[M(cvssSelected, "UI")] - UILevels[ExtractValueMetric("UI", mv)]
severityDistanceAC = ACLevels[M(cvssSelected, "AC")] - ACLevels[ExtractValueMetric("AC", mv)]
severityDistanceAT = ATLevels[M(cvssSelected, "AT")] - ATLevels[ExtractValueMetric("AT", mv)]
severityDistanceVC = VCLevels[M(cvssSelected, "VC")] - VCLevels[ExtractValueMetric("VC", mv)]
severityDistanceVI = VILevels[M(cvssSelected, "VI")] - VILevels[ExtractValueMetric("VI", mv)]
severityDistanceVA = VALevels[M(cvssSelected, "VA")] - VALevels[ExtractValueMetric("VA", mv)]
severityDistanceSC = SCLevels[M(cvssSelected, "SC")] - SCLevels[ExtractValueMetric("SC", mv)]
severityDistanceSI = SILevels[M(cvssSelected, "SI")] - SILevels[ExtractValueMetric("SI", mv)]
severityDistanceSA = SALevels[M(cvssSelected, "SA")] - SALevels[ExtractValueMetric("SA", mv)]
severityDistanceCR = CRLevels[M(cvssSelected, "CR")] - CRLevels[ExtractValueMetric("CR", mv)]
severityDistanceIR = IRLevels[M(cvssSelected, "IR")] - IRLevels[ExtractValueMetric("IR", mv)]
severityDistanceAR = ARLevels[M(cvssSelected, "AR")] - ARLevels[ExtractValueMetric("AR", mv)]
if severityDistanceAV < 0 || severityDistancePR < 0 || severityDistanceUI < 0 ||
severityDistanceAC < 0 || severityDistanceAT < 0 || severityDistanceVC < 0 ||
severityDistanceVI < 0 || severityDistanceVA < 0 || severityDistanceSC < 0 ||
severityDistanceSI < 0 || severityDistanceSA < 0 || severityDistanceCR < 0 ||
severityDistanceIR < 0 || severityDistanceAR < 0 {
continue
}
maxVector = mv
break
}
if maxVector == "" {
return math.Round(value*10) / 10
}
currentSeverityDistanceEq1 := severityDistanceAV + severityDistancePR + severityDistanceUI
currentSeverityDistanceEq2 := severityDistanceAC + severityDistanceAT
currentSeverityDistanceEq3eq6 := severityDistanceVC + severityDistanceVI + severityDistanceVA + severityDistanceCR + severityDistanceIR + severityDistanceAR
currentSeverityDistanceEq4 := severityDistanceSC + severityDistanceSI + severityDistanceSA
step := 0.1
var availableDistanceEq1 float64
if scoreEq1NextLowerMacro != 0 {
availableDistanceEq1 = value - scoreEq1NextLowerMacro
}
var availableDistanceEq2 float64
if scoreEq2NextLowerMacro != 0 {
availableDistanceEq2 = value - scoreEq2NextLowerMacro
}
var availableDistanceEq3eq6 float64
if scoreEq3eq6NextLowerMacro != 0 {
availableDistanceEq3eq6 = value - scoreEq3eq6NextLowerMacro
}
var availableDistanceEq4 float64
if scoreEq4NextLowerMacro != 0 {
availableDistanceEq4 = value - scoreEq4NextLowerMacro
}
var availableDistanceEq5 float64
if scoreEq5NextLowerMacro != 0 {
availableDistanceEq5 = value - scoreEq5NextLowerMacro
}
percentToNextEq1Severity := 0.0
percentToNextEq2Severity := 0.0
percentToNextEq3eq6Severity := 0.0
percentToNextEq4Severity := 0.0
percentToNextEq5Severity := 0.0
normalizedSeverityEq1 := 0.0
normalizedSeverityEq2 := 0.0
normalizedSeverityEq3eq6 := 0.0
normalizedSeverityEq4 := 0.0
normalizedSeverityEq5 := 0.0
getMaxSeverity := func(eq string, value int, eq6value int) float64 {
result := NewMaxSeverity()
var eqN map[int]float64
if eq == "EQ1" {
eqN = result.EQ1
} else if eq == "EQ2" {
eqN = result.EQ2
} else if eq == "EQ3EQ6" {
base := result.EQ3EQ6
eqN = base[value]
value = eq6value
} else if eq == "EQ4" {
eqN = result.EQ4
}
num, ok := eqN[value]
if ok {
return num
}
return 0.0
}
maxSeverityEq1 := getMaxSeverity("EQ1", eq1, 0) * step
maxSeverityEq2 := getMaxSeverity("EQ2", eq2, 0) * step
maxSeverityEq3eq6 := getMaxSeverity("EQ3EQ6", eq3, eq6) * step
maxSeverityEq4 := getMaxSeverity("EQ4", eq4, 0) * step
nExistingLower := 0
if availableDistanceEq1 != 0 {
nExistingLower++
percentToNextEq1Severity = currentSeverityDistanceEq1 / maxSeverityEq1
normalizedSeverityEq1 = availableDistanceEq1 * percentToNextEq1Severity
}
if availableDistanceEq2 != 0 {
nExistingLower++
percentToNextEq2Severity = currentSeverityDistanceEq2 / maxSeverityEq2
normalizedSeverityEq2 = availableDistanceEq2 * percentToNextEq2Severity
}
if availableDistanceEq3eq6 != 0 {
nExistingLower++
percentToNextEq3eq6Severity = currentSeverityDistanceEq3eq6 / maxSeverityEq3eq6
normalizedSeverityEq3eq6 = availableDistanceEq3eq6 * percentToNextEq3eq6Severity
}
if availableDistanceEq4 != 0 {
nExistingLower++
percentToNextEq4Severity = currentSeverityDistanceEq4 / maxSeverityEq4
normalizedSeverityEq4 = availableDistanceEq4 * percentToNextEq4Severity
}
if availableDistanceEq5 != 0 {
nExistingLower++
percentToNextEq5Severity = 0.0
normalizedSeverityEq5 = availableDistanceEq5 * percentToNextEq5Severity
}
totalNormalizedSeverity := normalizedSeverityEq1 + normalizedSeverityEq2 + normalizedSeverityEq3eq6 + normalizedSeverityEq4 + normalizedSeverityEq5
var meanDistance float64
if nExistingLower == 0 {
meanDistance = 0
} else {
meanDistance = totalNormalizedSeverity / float64(nExistingLower)
}
value -= meanDistance
if value < 0 {
value = 0.0
}
if value > 10 {
value = 10.0
}
return math.Round(value*10) / 10
}
预期结构测试用例:
func main() {
VectorString := "CVSS:4.0/AV:A/AC:H/AT:P/PR:L/UI:P/VC:L/VI:L/VA:L/SC:L/SI:L/SA:L/E:A/CR:M/IR:M/AR:M/MAV:A/MAC:H/MAT:P/MPR:L/MUI:P/MVC:L/MVI:L/MVA:L/MSC:H/MSI:H/MSA:H/S:P" //2.4
VectorString = "CVSS:4.0/AV:A/AC:H/AT:P/PR:L/UI:P/VC:L/VI:L/VA:L/SC:H/SI:L/SA:L/E:X/S:N/AU:N/R:A/V:D/RE:L/U:Clear" //2.1
score := CalculateScore(VectorString)
fmt.Println(score)
level := QualScore(score)
fmt.Println(level)
}


整体实现go代码可联系我
1.4 js和文档参考链接:
https://www.first.org/cvss/calculator/4-0
https://cvss.xc1ym.com/app.js?v=7
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)