cvss-suite 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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