cvss-suite 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,10 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
- # Copyright (c) Siemens AG, 2016
3
+ # Copyright (c) 2016-2022 Siemens AG
4
+ # Copyright (c) 2022 0llirocks
4
5
  #
5
6
  # Authors:
6
- # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ # 0llirocks <http://0lli.rocks>
7
8
  #
8
9
  # This work is licensed under the terms of the MIT license.
9
10
  # See the LICENSE.md file in the top-level directory.
@@ -26,8 +27,20 @@ module CvssSuite
26
27
  ##
27
28
  # Returns score of this metric
28
29
 
29
- def score(temporal_score)
30
- privilege_score = Cvss3Helper.privileges_required_score(@modified_privileges_required, @modified_scope)
30
+ def score(base, temporal)
31
+ @base = base
32
+
33
+ merged_modified_privileges_required = @modified_privileges_required
34
+ if @modified_privileges_required.selected_value[:name] == 'Not Defined'
35
+ merged_modified_privileges_required = @base.privileges_required
36
+ end
37
+
38
+ merged_modified_scope = @modified_scope
39
+ if @modified_scope.selected_value[:name] == 'Not Defined'
40
+ merged_modified_scope = @base.scope
41
+ end
42
+
43
+ privilege_score = Cvss3Helper.privileges_required_score(merged_modified_privileges_required, merged_modified_scope)
31
44
 
32
45
  modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
33
46
 
@@ -35,7 +48,7 @@ module CvssSuite
35
48
 
36
49
  return 0 if modified_impact_sub_score <= 0
37
50
 
38
- calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
51
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
39
52
  end
40
53
 
41
54
  private
@@ -44,70 +57,79 @@ module CvssSuite
44
57
  @properties.push(@confidentiality_requirement =
45
58
  CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
46
59
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
47
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
48
- { name: 'High', abbreviation: 'H', weight: 1.5 },
49
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
60
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
61
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
62
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
50
63
  @properties.push(@integrity_requirement =
51
64
  CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
52
65
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
53
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
54
- { name: 'High', abbreviation: 'H', weight: 1.5 },
55
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
66
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
67
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
68
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
56
69
 
57
70
  @properties.push(@availability_requirement =
58
71
  CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
59
72
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
60
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
61
- { name: 'High', abbreviation: 'H', weight: 1.5 },
62
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
73
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
74
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
75
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
63
76
  @properties.push(@modified_attack_vector =
64
77
  CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
65
78
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
66
- { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
67
- { name: 'Local', abbreviation: 'L', weight: 0.55 },
68
- { name: 'Physical', abbreviation: 'P', weight: 0.2 },
69
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
79
+ { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
80
+ { name: 'Local', abbreviation: 'L', weight: 0.55 },
81
+ { name: 'Physical', abbreviation: 'P', weight: 0.2 },
82
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
70
83
  @properties.push(@modified_attack_complexity =
71
84
  CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
72
85
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
73
- { name: 'High', abbreviation: 'H', weight: 0.44 },
74
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
86
+ { name: 'High', abbreviation: 'H', weight: 0.44 },
87
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
75
88
  @properties.push(@modified_privileges_required =
76
89
  CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
77
90
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
78
- { name: 'Low', abbreviation: 'L', weight: 0.62 },
79
- { name: 'High', abbreviation: 'H', weight: 0.27 },
80
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
91
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
92
+ { name: 'High', abbreviation: 'H', weight: 0.27 },
93
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
81
94
  @properties.push(@modified_user_interaction =
82
95
  CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
83
96
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
84
- { name: 'Required', abbreviation: 'R', weight: 0.62 },
85
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
97
+ { name: 'Required', abbreviation: 'R', weight: 0.62 },
98
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
86
99
  @properties.push(@modified_scope =
87
100
  CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
88
101
  values: [{ name: 'Changed', abbreviation: 'C' },
89
- { name: 'Unchanged', abbreviation: 'U' }]))
102
+ { name: 'Unchanged', abbreviation: 'U' },
103
+ { name: 'Not Defined', abbreviation: 'X' }]))
90
104
  @properties.push(@modified_confidentiality =
91
105
  CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
92
106
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
93
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
94
- { name: 'High', abbreviation: 'H', weight: 0.56 },
95
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
107
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
108
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
109
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
96
110
  @properties.push(@modified_integrity =
97
111
  CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
98
112
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
99
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
100
- { name: 'High', abbreviation: 'H', weight: 0.56 },
101
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
113
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
114
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
115
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
102
116
  @properties.push(@modified_availability =
103
117
  CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
104
118
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
105
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
106
- { name: 'High', abbreviation: 'H', weight: 0.56 },
107
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
119
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
120
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
121
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
108
122
  end
109
123
 
110
124
  def modified_impact_sub(isc_modified)
125
+ if @modified_scope.selected_value[:name] == 'Not Defined'
126
+ if @base.scope.selected_value[:name] == 'Changed'
127
+ return 7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified - 0.02)**15
128
+ else
129
+ return 6.42 * isc_modified
130
+ end
131
+ end
132
+
111
133
  if @modified_scope.selected_value[:name] == 'Changed'
112
134
  7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified - 0.02)**15
113
135
  else
@@ -116,20 +138,54 @@ module CvssSuite
116
138
  end
117
139
 
118
140
  def isc_modified
119
- confidentiality_score = 1 - @modified_confidentiality.score * @confidentiality_requirement.score
120
- integrity_score = 1 - @modified_integrity.score * @integrity_requirement.score
121
- availability_score = 1 - @modified_availability.score * @availability_requirement.score
141
+ merged_modified_confidentiality = @modified_confidentiality
142
+ if @modified_confidentiality.selected_value[:name] == 'Not Defined'
143
+ merged_modified_confidentiality = @base.confidentiality
144
+ end
145
+
146
+ merged_modified_integrity = @modified_integrity
147
+ if @modified_integrity.selected_value[:name] == 'Not Defined'
148
+ merged_modified_integrity = @base.integrity
149
+ end
150
+
151
+ merged_modified_availability = @modified_availability
152
+ if @modified_availability.selected_value[:name] == 'Not Defined'
153
+ merged_modified_availability = @base.availability
154
+ end
155
+
156
+ confidentiality_score = 1 - merged_modified_confidentiality.score * @confidentiality_requirement.score
157
+ integrity_score = 1 - merged_modified_integrity.score * @integrity_requirement.score
158
+ availability_score = 1 - merged_modified_availability.score * @availability_requirement.score
122
159
 
123
160
  [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
124
161
  end
125
162
 
126
163
  def modified_exploitability_sub(privilege_score)
127
- 8.22 * @modified_attack_vector.score * @modified_attack_complexity.score *
128
- privilege_score * @modified_user_interaction.score
164
+ merged_modified_attack_vector = @modified_attack_vector
165
+ if @modified_attack_vector.selected_value[:name] == 'Not Defined'
166
+ merged_modified_attack_vector = @base.attack_vector
167
+ end
168
+
169
+ merged_modified_attack_complexity = @modified_attack_complexity
170
+ if @modified_attack_complexity.selected_value[:name] == 'Not Defined'
171
+ merged_modified_attack_complexity = @base.attack_complexity
172
+ end
173
+
174
+ merged_modified_user_interaction = @modified_user_interaction
175
+ if @modified_user_interaction.selected_value[:name] == 'Not Defined'
176
+ merged_modified_user_interaction = @base.user_interaction
177
+ end
178
+
179
+ 8.22 * merged_modified_attack_vector.score * merged_modified_attack_complexity.score *
180
+ privilege_score * merged_modified_user_interaction.score
129
181
  end
130
182
 
131
183
  def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
132
- factor = @modified_scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
184
+ if @modified_scope.selected_value[:name] == 'Not Defined'
185
+ factor = @base.scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
186
+ else
187
+ factor = @modified_scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
188
+ end
133
189
 
134
190
  Cvss3Helper.round_up(
135
191
  [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min
@@ -1,9 +1,10 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
- # Copyright (c) Siemens AG, 2016
3
+ # Copyright (c) 2016-2022 Siemens AG
4
+ # Copyright (c) 2022 0llirocks
4
5
  #
5
6
  # Authors:
6
- # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ # 0llirocks <http://0lli.rocks>
7
8
  #
8
9
  # This work is licensed under the terms of the MIT license.
9
10
  # See the LICENSE.md file in the top-level directory.
@@ -33,24 +34,24 @@ module CvssSuite
33
34
  @properties.push(@exploit_code_maturity =
34
35
  CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
35
36
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
36
- { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
37
- { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
38
- { name: 'Functional', abbreviation: 'F', weight: 0.97 },
39
- { name: 'High', abbreviation: 'H', weight: 1.0 }]))
37
+ { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
38
+ { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
39
+ { name: 'Functional', abbreviation: 'F', weight: 0.97 },
40
+ { name: 'High', abbreviation: 'H', weight: 1.0 }]))
40
41
  @properties.push(@remediation_level =
41
42
  CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
42
43
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
43
- { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
44
- { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
45
- { name: 'Workaround', abbreviation: 'W', weight: 0.97 },
46
- { name: 'Unavailable', abbreviation: 'U', weight: 1.0 }]))
44
+ { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
45
+ { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
46
+ { name: 'Workaround', abbreviation: 'W', weight: 0.97 },
47
+ { name: 'Unavailable', abbreviation: 'U', weight: 1.0 }]))
47
48
 
48
49
  @properties.push(@report_confidence =
49
50
  CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
50
51
  values: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
51
- { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
52
- { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
53
- { name: 'Confirmed', abbreviation: 'C', weight: 1.0 }]))
52
+ { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
53
+ { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
54
+ { name: 'Confirmed', abbreviation: 'C', weight: 1.0 }]))
54
55
  end
55
56
  end
56
57
  end
@@ -1,9 +1,10 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
- # Copyright (c) Siemens AG, 2019
3
+ # Copyright (c) 2019-2022 Siemens AG
4
+ # Copyright (c) 2022 0llirocks
4
5
  #
5
6
  # Authors:
6
- # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ # 0llirocks <http://0lli.rocks>
7
8
  #
8
9
  # This work is licensed under the terms of the MIT license.
9
10
  # See the LICENSE.md file in the top-level directory.
@@ -46,7 +47,7 @@ module CvssSuite
46
47
  def environmental_score
47
48
  return temporal_score unless @environmental.valid?
48
49
 
49
- Cvss31Helper.round_up(@environmental.score(@temporal.score))
50
+ Cvss31Helper.round_up(@environmental.score(@base, @temporal))
50
51
  end
51
52
 
52
53
  private
@@ -1,9 +1,10 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
- # Copyright (c) Siemens AG, 2019
3
+ # Copyright (c) 2019-2022 Siemens AG
4
+ # Copyright (c) 2022 0llirocks
4
5
  #
5
6
  # Authors:
6
- # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ # 0llirocks <http://0lli.rocks>
7
8
  #
8
9
  # This work is licensed under the terms of the MIT license.
9
10
  # See the LICENSE.md file in the top-level directory.
@@ -53,41 +54,41 @@ module CvssSuite
53
54
  @properties.push(@attack_vector =
54
55
  CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV', position: [0],
55
56
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
56
- { name: 'Adjacent', abbreviation: 'A', weight: 0.62 },
57
- { name: 'Local', abbreviation: 'L', weight: 0.55 },
58
- { name: 'Physical', abbreviation: 'P', weight: 0.2 }]))
57
+ { name: 'Adjacent', abbreviation: 'A', weight: 0.62 },
58
+ { name: 'Local', abbreviation: 'L', weight: 0.55 },
59
+ { name: 'Physical', abbreviation: 'P', weight: 0.2 }]))
59
60
  @properties.push(@attack_complexity =
60
61
  CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC', position: [1],
61
62
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
62
- { name: 'High', abbreviation: 'H', weight: 0.44 }]))
63
+ { name: 'High', abbreviation: 'H', weight: 0.44 }]))
63
64
  @properties.push(@privileges_required =
64
65
  CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR', position: [2],
65
66
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
66
- { name: 'Low', abbreviation: 'L', weight: 0.62 },
67
- { name: 'High', abbreviation: 'H', weight: 0.27 }]))
67
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
68
+ { name: 'High', abbreviation: 'H', weight: 0.27 }]))
68
69
  @properties.push(@user_interaction =
69
70
  CvssProperty.new(name: 'User Interaction', abbreviation: 'UI', position: [3],
70
71
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
71
- { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
72
+ { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
72
73
  @properties.push(@scope =
73
74
  CvssProperty.new(name: 'Scope', abbreviation: 'S', position: [4],
74
75
  values: [{ name: 'Unchanged', abbreviation: 'U' },
75
- { name: 'Changed', abbreviation: 'C' }]))
76
+ { name: 'Changed', abbreviation: 'C' }]))
76
77
  @properties.push(@confidentiality =
77
78
  CvssProperty.new(name: 'Confidentiality', abbreviation: 'C', position: [5],
78
79
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
79
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
80
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
80
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
81
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
81
82
  @properties.push(@integrity =
82
83
  CvssProperty.new(name: 'Integrity', abbreviation: 'I', position: [6],
83
84
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
84
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
85
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
85
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
86
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
86
87
  @properties.push(@availability =
87
88
  CvssProperty.new(name: 'Availability', abbreviation: 'A', position: [7],
88
89
  values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
89
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
90
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
90
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
91
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
91
92
  end
92
93
  end
93
94
  end
@@ -1,9 +1,10 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
- # Copyright (c) Siemens AG, 2019
3
+ # Copyright (c) 2019-2022 Siemens AG
4
+ # Copyright (c) 2022 0llirocks
4
5
  #
5
6
  # Authors:
6
- # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ # 0llirocks <http://0lli.rocks>
7
8
  #
8
9
  # This work is licensed under the terms of the MIT license.
9
10
  # See the LICENSE.md file in the top-level directory.
@@ -26,8 +27,20 @@ module CvssSuite
26
27
 
27
28
  ##
28
29
  # Returns score of this metric
29
- def score(temporal_score)
30
- privilege_score = Cvss3Helper.privileges_required_score(@modified_privileges_required, @modified_scope)
30
+ def score(base, temporal)
31
+ @base = base
32
+
33
+ merged_modified_privileges_required = @modified_privileges_required
34
+ if @modified_privileges_required.selected_value[:name] == 'Not Defined'
35
+ merged_modified_privileges_required = @base.privileges_required
36
+ end
37
+
38
+ merged_modified_scope = @modified_scope
39
+ if @modified_scope.selected_value[:name] == 'Not Defined'
40
+ merged_modified_scope = @base.scope
41
+ end
42
+
43
+ privilege_score = Cvss3Helper.privileges_required_score(merged_modified_privileges_required, merged_modified_scope)
31
44
 
32
45
  modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
33
46
 
@@ -35,7 +48,7 @@ module CvssSuite
35
48
 
36
49
  return 0 if modified_impact_sub_score <= 0
37
50
 
38
- calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal_score
51
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
39
52
  end
40
53
 
41
54
  private
@@ -44,70 +57,79 @@ module CvssSuite
44
57
  @properties.push(@confidentiality_requirement =
45
58
  CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
46
59
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
47
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
48
- { name: 'High', abbreviation: 'H', weight: 1.5 },
49
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
60
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
61
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
62
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
50
63
  @properties.push(@integrity_requirement =
51
64
  CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
52
65
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
53
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
54
- { name: 'High', abbreviation: 'H', weight: 1.5 },
55
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
66
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
67
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
68
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
56
69
 
57
70
  @properties.push(@availability_requirement =
58
71
  CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
59
72
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
60
- { name: 'Medium', abbreviation: 'M', weight: 1.0 },
61
- { name: 'High', abbreviation: 'H', weight: 1.5 },
62
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
73
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
74
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
75
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
63
76
  @properties.push(@modified_attack_vector =
64
77
  CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
65
78
  values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
66
- { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
67
- { name: 'Local', abbreviation: 'L', weight: 0.55 },
68
- { name: 'Physical', abbreviation: 'P', weight: 0.2 },
69
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
79
+ { name: 'Adjacent Network', abbreviation: 'A', weight: 0.62 },
80
+ { name: 'Local', abbreviation: 'L', weight: 0.55 },
81
+ { name: 'Physical', abbreviation: 'P', weight: 0.2 },
82
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
70
83
  @properties.push(@modified_attack_complexity =
71
84
  CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
72
85
  values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
73
- { name: 'High', abbreviation: 'H', weight: 0.44 },
74
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
86
+ { name: 'High', abbreviation: 'H', weight: 0.44 },
87
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
75
88
  @properties.push(@modified_privileges_required =
76
89
  CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
77
90
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
78
- { name: 'Low', abbreviation: 'L', weight: 0.62 },
79
- { name: 'High', abbreviation: 'H', weight: 0.27 },
80
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
91
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
92
+ { name: 'High', abbreviation: 'H', weight: 0.27 },
93
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
81
94
  @properties.push(@modified_user_interaction =
82
95
  CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
83
96
  values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
84
- { name: 'Required', abbreviation: 'R', weight: 0.62 },
85
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
97
+ { name: 'Required', abbreviation: 'R', weight: 0.62 },
98
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
86
99
  @properties.push(@modified_scope =
87
100
  CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
88
101
  values: [{ name: 'Changed', abbreviation: 'C' },
89
- { name: 'Unchanged', abbreviation: 'U' }]))
102
+ { name: 'Unchanged', abbreviation: 'U' },
103
+ { name: 'Not Defined', abbreviation: 'X' }]))
90
104
  @properties.push(@modified_confidentiality =
91
105
  CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
92
106
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
93
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
94
- { name: 'High', abbreviation: 'H', weight: 0.56 },
95
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
107
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
108
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
109
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
96
110
  @properties.push(@modified_integrity =
97
111
  CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
98
112
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
99
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
100
- { name: 'High', abbreviation: 'H', weight: 0.56 },
101
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
113
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
114
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
115
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
102
116
  @properties.push(@modified_availability =
103
117
  CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
104
118
  values: [{ name: 'None', abbreviation: 'N', weight: 0 },
105
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
106
- { name: 'High', abbreviation: 'H', weight: 0.56 },
107
- { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
119
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
120
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
121
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
108
122
  end
109
123
 
110
124
  def modified_impact_sub(isc_modified)
125
+ if @modified_scope.selected_value[:name] == 'Not Defined'
126
+ if @base.scope.selected_value[:name] == 'Changed'
127
+ return 7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified * 0.9731 - 0.02)**13
128
+ else
129
+ return 6.42 * isc_modified
130
+ end
131
+ end
132
+
111
133
  if @modified_scope.selected_value[:name] == 'Changed'
112
134
  7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified * 0.9731 - 0.02)**13
113
135
  else
@@ -116,20 +138,54 @@ module CvssSuite
116
138
  end
117
139
 
118
140
  def isc_modified
119
- confidentiality_score = 1 - @modified_confidentiality.score * @confidentiality_requirement.score
120
- integrity_score = 1 - @modified_integrity.score * @integrity_requirement.score
121
- availability_score = 1 - @modified_availability.score * @availability_requirement.score
141
+ merged_modified_confidentiality = @modified_confidentiality
142
+ if @modified_confidentiality.selected_value[:name] == 'Not Defined'
143
+ merged_modified_confidentiality = @base.confidentiality
144
+ end
145
+
146
+ merged_modified_integrity = @modified_integrity
147
+ if @modified_integrity.selected_value[:name] == 'Not Defined'
148
+ merged_modified_integrity = @base.integrity
149
+ end
150
+
151
+ merged_modified_availability = @modified_availability
152
+ if @modified_availability.selected_value[:name] == 'Not Defined'
153
+ merged_modified_availability = @base.availability
154
+ end
155
+
156
+ confidentiality_score = 1 - merged_modified_confidentiality.score * @confidentiality_requirement.score
157
+ integrity_score = 1 - merged_modified_integrity.score * @integrity_requirement.score
158
+ availability_score = 1 - merged_modified_availability.score * @availability_requirement.score
122
159
 
123
160
  [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
124
161
  end
125
162
 
126
163
  def modified_exploitability_sub(privilege_score)
127
- 8.22 * @modified_attack_vector.score * @modified_attack_complexity.score *
128
- privilege_score * @modified_user_interaction.score
164
+ merged_modified_attack_vector = @modified_attack_vector
165
+ if @modified_attack_vector.selected_value[:name] == 'Not Defined'
166
+ merged_modified_attack_vector = @base.attack_vector
167
+ end
168
+
169
+ merged_modified_attack_complexity = @modified_attack_complexity
170
+ if @modified_attack_complexity.selected_value[:name] == 'Not Defined'
171
+ merged_modified_attack_complexity = @base.attack_complexity
172
+ end
173
+
174
+ merged_modified_user_interaction = @modified_user_interaction
175
+ if @modified_user_interaction.selected_value[:name] == 'Not Defined'
176
+ merged_modified_user_interaction = @base.user_interaction
177
+ end
178
+
179
+ 8.22 * merged_modified_attack_vector.score * merged_modified_attack_complexity.score *
180
+ privilege_score * merged_modified_user_interaction.score
129
181
  end
130
182
 
131
183
  def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
132
- factor = @modified_scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
184
+ if @modified_scope.selected_value[:name] == 'Not Defined'
185
+ factor = @base.scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
186
+ else
187
+ factor = @modified_scope.selected_value[:name] == 'Changed' ? 1.08 : 1.0
188
+ end
133
189
 
134
190
  Cvss31Helper.round_up(
135
191
  [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min