cvss-suite 1.2.0 → 3.1.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.
@@ -12,84 +13,81 @@ require_relative '../cvss_property'
12
13
  require_relative '../cvss_metric'
13
14
  require_relative '../helpers/cvss3_helper'
14
15
 
15
- ##
16
- # This class represents a CVSS Base metric in version 3.
17
-
18
- class Cvss3Base < CvssMetric
19
-
20
- ##
21
- # Property of this metric
22
-
23
- attr_reader :attack_vector, :attack_complexity, :privileges_required, :user_interaction,
24
- :scope, :confidentiality, :integrity, :availability
25
-
16
+ module CvssSuite
26
17
  ##
27
- # Returns score of this metric
28
-
29
- def score
30
-
31
- privilege_score = Cvss3Helper.privileges_required_score @privileges_required, @scope
32
-
33
- exploitability = 8.22 * @attack_vector.score * @attack_complexity.score * privilege_score * @user_interaction.score
34
-
35
- isc_base = 1 - ((1 - @confidentiality.score) * (1 - @integrity.score) * (1 - @availability.score))
36
-
37
- if @scope.selected_choice[:name] == 'Changed'
38
- impact_sub_score = 7.52 * (isc_base - 0.029) - 3.25 * (isc_base - 0.02)**15
39
- else
40
- impact_sub_score = 6.42 * isc_base
18
+ # This class represents a CVSS Base metric in version 3.
19
+ class Cvss3Base < CvssMetric
20
+ ##
21
+ # Property of this metric
22
+ attr_reader :attack_vector, :attack_complexity, :privileges_required, :user_interaction,
23
+ :scope, :confidentiality, :integrity, :availability
24
+
25
+ ##
26
+ # Returns score of this metric
27
+ def score
28
+ privilege_score = Cvss3Helper.privileges_required_score @privileges_required, @scope
29
+
30
+ exploitability = 8.22 * @attack_vector.score * @attack_complexity.score *
31
+ privilege_score * @user_interaction.score
32
+
33
+ isc_base = 1 - ((1 - @confidentiality.score) * (1 - @integrity.score) * (1 - @availability.score))
34
+
35
+ impact_sub_score = if @scope.selected_value[:name] == 'Changed'
36
+ 7.52 * (isc_base - 0.029) - 3.25 * (isc_base - 0.02)**15
37
+ else
38
+ 6.42 * isc_base
39
+ end
40
+
41
+ return 0 if impact_sub_score <= 0
42
+
43
+ if @scope.selected_value[:name] == 'Changed'
44
+ [10, 1.08 * (impact_sub_score + exploitability)].min
45
+ else
46
+ [10, impact_sub_score + exploitability].min
47
+ end
41
48
  end
42
49
 
43
- return 0 if impact_sub_score <= 0
44
-
45
- if @scope.selected_choice[:name] == 'Changed'
46
- [10, 1.08 * (impact_sub_score + exploitability)].min
47
- else
48
- [10, impact_sub_score + exploitability].min
50
+ private
51
+
52
+ def init_properties
53
+ @properties.push(@attack_vector =
54
+ CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV',
55
+ 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 }]))
59
+ @properties.push(@attack_complexity =
60
+ CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC',
61
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
62
+ { name: 'High', abbreviation: 'H', weight: 0.44 }]))
63
+ @properties.push(@privileges_required =
64
+ CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR',
65
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
66
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
67
+ { name: 'High', abbreviation: 'H', weight: 0.27 }]))
68
+ @properties.push(@user_interaction =
69
+ CvssProperty.new(name: 'User Interaction', abbreviation: 'UI',
70
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
71
+ { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
72
+ @properties.push(@scope =
73
+ CvssProperty.new(name: 'Scope', abbreviation: 'S',
74
+ values: [{ name: 'Unchanged', abbreviation: 'U' },
75
+ { name: 'Changed', abbreviation: 'C' }]))
76
+ @properties.push(@confidentiality =
77
+ CvssProperty.new(name: 'Confidentiality', abbreviation: 'C',
78
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
79
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
80
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
81
+ @properties.push(@integrity =
82
+ CvssProperty.new(name: 'Integrity', abbreviation: 'I',
83
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
84
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
85
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
86
+ @properties.push(@availability =
87
+ CvssProperty.new(name: 'Availability', abbreviation: 'A',
88
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
89
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
90
+ { name: 'High', abbreviation: 'H', weight: 0.56 }]))
49
91
  end
50
92
  end
51
-
52
- private
53
-
54
- def init_properties
55
- @properties.push(@attack_vector =
56
- CvssProperty.new(name: 'Attack Vector', abbreviation: 'AV', position: [0],
57
- choices: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
58
- { name: 'Adjacent', abbreviation: 'A', weight: 0.62 },
59
- { name: 'Local', abbreviation: 'L', weight: 0.55 },
60
- { name: 'Physical', abbreviation: 'P', weight: 0.2 }]))
61
- @properties.push(@attack_complexity =
62
- CvssProperty.new(name: 'Attack Complexity', abbreviation: 'AC', position: [1],
63
- choices: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
64
- { name: 'High', abbreviation: 'H', weight: 0.44 }]))
65
- @properties.push(@privileges_required =
66
- CvssProperty.new(name: 'Privileges Required', abbreviation: 'PR', position: [2],
67
- choices: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
68
- { name: 'Low', abbreviation: 'L', weight: 0.62 },
69
- { name: 'High', abbreviation: 'H', weight: 0.27 }]))
70
- @properties.push(@user_interaction =
71
- CvssProperty.new(name: 'User Interaction', abbreviation: 'UI', position: [3],
72
- choices: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
73
- { name: 'Required', abbreviation: 'R', weight: 0.62 }]))
74
- @properties.push(@scope =
75
- CvssProperty.new(name: 'Scope', abbreviation: 'S', position: [4],
76
- choices: [{ name: 'Unchanged', abbreviation: 'U' },
77
- { name: 'Changed', abbreviation: 'C' }]))
78
- @properties.push(@confidentiality =
79
- CvssProperty.new(name: 'Confidentiality', abbreviation: 'C', position: [5],
80
- choices: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
81
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
82
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
83
- @properties.push(@integrity =
84
- CvssProperty.new(name: 'Integrity', abbreviation: 'I', position: [6],
85
- choices: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
86
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
87
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
88
- @properties.push(@availability =
89
- CvssProperty.new(name: 'Availability', abbreviation: 'A', position: [7],
90
- choices: [{ name: 'None', abbreviation: 'N', weight: 0.0 },
91
- { name: 'Low', abbreviation: 'L', weight: 0.22 },
92
- { name: 'High', abbreviation: 'H', weight: 0.56 }]))
93
- end
94
93
  end
95
-
@@ -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.
@@ -12,133 +13,183 @@ require_relative '../cvss_property'
12
13
  require_relative '../cvss_metric'
13
14
  require_relative '../helpers/cvss3_helper'
14
15
 
15
- ##
16
- # This class represents a CVSS Environmental metric in version 3.
16
+ module CvssSuite
17
+ ##
18
+ # This class represents a CVSS Environmental metric in version 3.
19
+ class Cvss3Environmental < CvssMetric
20
+ ##
21
+ # Property of this metric
22
+ attr_reader :confidentiality_requirement, :integrity_requirement, :availability_requirement,
23
+ :modified_attack_vector, :modified_attack_complexity, :modified_privileges_required,
24
+ :modified_user_interaction, :modified_scope, :modified_confidentiality,
25
+ :modified_integrity, :modified_availability
17
26
 
18
- class Cvss3Environmental < CvssMetric
27
+ ##
28
+ # Returns score of this metric
19
29
 
20
- ##
21
- # Property of this metric
30
+ def score(base, temporal)
31
+ @base = base
22
32
 
23
- attr_reader :confidentiality_requirement, :integrity_requirement, :availability_requirement,
24
- :modified_attack_vector, :modified_attack_complexity, :modified_privileges_required,
25
- :modified_user_interaction, :modified_scope, :modified_confidentiality,
26
- :modified_integrity, :modified_availability
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
27
37
 
28
- ##
29
- # Returns score of this metric
38
+ merged_modified_scope = @modified_scope
39
+ if @modified_scope.selected_value[:name] == 'Not Defined'
40
+ merged_modified_scope = @base.scope
41
+ end
30
42
 
31
- def score(temporal_score)
43
+ privilege_score = Cvss3Helper.privileges_required_score(merged_modified_privileges_required, merged_modified_scope)
32
44
 
33
- privilege_score = Cvss3Helper.privileges_required_score @modified_privileges_required, @modified_scope
45
+ modified_exploitability_sub_score = modified_exploitability_sub(privilege_score)
34
46
 
35
- modified_exploitability_sub_score = modified_exploitability_sub privilege_score
47
+ modified_impact_sub_score = modified_impact_sub(isc_modified)
36
48
 
37
- isc_modified_score = isc_modified
49
+ return 0 if modified_impact_sub_score <= 0
38
50
 
39
- modified_impact_sub_score = modified_impact_sub isc_modified_score
51
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal.score
52
+ end
40
53
 
41
- return 0 if modified_impact_sub_score <= 0
54
+ private
55
+
56
+ def init_properties
57
+ @properties.push(@confidentiality_requirement =
58
+ CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR',
59
+ 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 }]))
63
+ @properties.push(@integrity_requirement =
64
+ CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR',
65
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
66
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
67
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
68
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
69
+
70
+ @properties.push(@availability_requirement =
71
+ CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR',
72
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.5 },
73
+ { name: 'Medium', abbreviation: 'M', weight: 1.0 },
74
+ { name: 'High', abbreviation: 'H', weight: 1.5 },
75
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
76
+ @properties.push(@modified_attack_vector =
77
+ CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV',
78
+ values: [{ name: 'Network', abbreviation: 'N', weight: 0.85 },
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 }]))
83
+ @properties.push(@modified_attack_complexity =
84
+ CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC',
85
+ values: [{ name: 'Low', abbreviation: 'L', weight: 0.77 },
86
+ { name: 'High', abbreviation: 'H', weight: 0.44 },
87
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
88
+ @properties.push(@modified_privileges_required =
89
+ CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR',
90
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
91
+ { name: 'Low', abbreviation: 'L', weight: 0.62 },
92
+ { name: 'High', abbreviation: 'H', weight: 0.27 },
93
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
94
+ @properties.push(@modified_user_interaction =
95
+ CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI',
96
+ values: [{ name: 'None', abbreviation: 'N', weight: 0.85 },
97
+ { name: 'Required', abbreviation: 'R', weight: 0.62 },
98
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
99
+ @properties.push(@modified_scope =
100
+ CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS',
101
+ values: [{ name: 'Changed', abbreviation: 'C' },
102
+ { name: 'Unchanged', abbreviation: 'U' },
103
+ { name: 'Not Defined', abbreviation: 'X' }]))
104
+ @properties.push(@modified_confidentiality =
105
+ CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC',
106
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
107
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
108
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
109
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
110
+ @properties.push(@modified_integrity =
111
+ CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI',
112
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
113
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
114
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
115
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
116
+ @properties.push(@modified_availability =
117
+ CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA',
118
+ values: [{ name: 'None', abbreviation: 'N', weight: 0 },
119
+ { name: 'Low', abbreviation: 'L', weight: 0.22 },
120
+ { name: 'High', abbreviation: 'H', weight: 0.56 },
121
+ { name: 'Not Defined', abbreviation: 'X', weight: 1 }]))
122
+ end
42
123
 
43
- calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal_score
44
- end
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
+
133
+ if @modified_scope.selected_value[:name] == 'Changed'
134
+ 7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified - 0.02)**15
135
+ else
136
+ 6.42 * isc_modified
137
+ end
138
+ end
45
139
 
46
- private
47
-
48
- def init_properties
49
- @properties.push(@confidentiality_requirement =
50
- CvssProperty.new(name: 'Confidentiality Requirement', abbreviation: 'CR', position: [8, 11],
51
- choices: [{name: 'Low', abbreviation: 'L', weight: 0.5},
52
- {name: 'Medium', abbreviation: 'M', weight: 1.0},
53
- {name: 'High', abbreviation: 'H', weight: 1.5},
54
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
55
- @properties.push(@integrity_requirement =
56
- CvssProperty.new(name: 'Integrity Requirement', abbreviation: 'IR', position: [9, 12],
57
- choices: [{name: 'Low', abbreviation: 'L', weight: 0.5},
58
- {name: 'Medium', abbreviation: 'M', weight: 1.0},
59
- {name: 'High', abbreviation: 'H', weight: 1.5},
60
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
61
-
62
- @properties.push(@availability_requirement =
63
- CvssProperty.new(name: 'Availability Requirement', abbreviation: 'AR', position: [10, 13],
64
- choices: [{name: 'Low', abbreviation: 'L', weight: 0.5},
65
- {name: 'Medium', abbreviation: 'M', weight: 1.0},
66
- {name: 'High', abbreviation: 'H', weight: 1.5},
67
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
68
- @properties.push(@modified_attack_vector =
69
- CvssProperty.new(name: 'Modified Attack Vector', abbreviation: 'MAV', position: [11, 14],
70
- choices: [{name: 'Network', abbreviation: 'N', weight: 0.85},
71
- {name: 'Adjacent Network', abbreviation: 'A', weight: 0.62},
72
- {name: 'Local', abbreviation: 'L', weight: 0.55},
73
- {name: 'Physical', abbreviation: 'P', weight: 0.2},
74
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
75
- @properties.push(@modified_attack_complexity =
76
- CvssProperty.new(name: 'Modified Attack Complexity', abbreviation: 'MAC', position: [12, 15],
77
- choices: [{name: 'Low', abbreviation: 'L', weight: 0.77},
78
- {name: 'High', abbreviation: 'H', weight: 0.44},
79
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
80
- @properties.push(@modified_privileges_required =
81
- CvssProperty.new(name: 'Modified Privileges Required', abbreviation: 'MPR', position: [13, 16],
82
- choices: [{name: 'None', abbreviation: 'N', weight: 0.85},
83
- {name: 'Low', abbreviation: 'L', weight: 0.62},
84
- {name: 'High', abbreviation: 'H', weight: 0.27},
85
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
86
- @properties.push(@modified_user_interaction =
87
- CvssProperty.new(name: 'Modified User Interaction', abbreviation: 'MUI', position: [14, 17],
88
- choices: [{name: 'None', abbreviation: 'N', weight: 0.85},
89
- {name: 'Required', abbreviation: 'R', weight: 0.62},
90
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
91
- @properties.push(@modified_scope =
92
- CvssProperty.new(name: 'Modified Scope', abbreviation: 'MS', position: [15, 18],
93
- choices: [{name: 'Changed', abbreviation: 'C'},
94
- {name: 'Unchanged', abbreviation: 'U'}]))
95
- @properties.push(@modified_confidentiality =
96
- CvssProperty.new(name: 'Modified Confidentiality', abbreviation: 'MC', position: [16, 19],
97
- choices: [{name: 'None', abbreviation: 'N', weight: 0},
98
- {name: 'Low', abbreviation: 'L', weight: 0.22},
99
- {name: 'High', abbreviation: 'H', weight: 0.56},
100
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
101
- @properties.push(@modified_integrity =
102
- CvssProperty.new(name: 'Modified Integrity', abbreviation: 'MI', position: [17, 20],
103
- choices: [{name: 'None', abbreviation: 'N', weight: 0},
104
- {name: 'Low', abbreviation: 'L', weight: 0.22},
105
- {name: 'High', abbreviation: 'H', weight: 0.56},
106
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
107
- @properties.push(@modified_availability =
108
- CvssProperty.new(name: 'Modified Availability', abbreviation: 'MA', position: [18, 21],
109
- choices: [{name: 'None', abbreviation: 'N', weight: 0},
110
- {name: 'Low', abbreviation: 'L', weight: 0.22},
111
- {name: 'High', abbreviation: 'H', weight: 0.56},
112
- {name: 'Not Defined', abbreviation: 'X', weight: 1}]))
113
- end
140
+ def isc_modified
141
+ merged_modified_confidentiality = @modified_confidentiality
142
+ if @modified_confidentiality.selected_value[:name] == 'Not Defined'
143
+ merged_modified_confidentiality = @base.confidentiality
144
+ end
114
145
 
115
- def modified_impact_sub(isc_modified)
116
- if @modified_scope.selected_choice[:name] == 'Changed'
117
- 7.52 * (isc_modified - 0.029) - 3.25 * (isc_modified - 0.02)**15
118
- else
119
- 6.42 * isc_modified
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
159
+
160
+ [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
120
161
  end
121
- end
122
162
 
123
- def isc_modified
124
- confidentiality_score = 1 - @modified_confidentiality.score * @confidentiality_requirement.score
125
- integrity_score = 1 - @modified_integrity.score * @integrity_requirement.score
126
- availability_score = 1 - @modified_availability.score * @availability_requirement.score
163
+ def modified_exploitability_sub(privilege_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
127
168
 
128
- [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
129
- end
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
130
173
 
131
- def modified_exploitability_sub(privilege_score)
132
- modified_exploitability_sub_score = 8.22 * @modified_attack_vector.score
133
- modified_exploitability_sub_score *= @modified_attack_complexity.score
134
- modified_exploitability_sub_score *= privilege_score
135
- modified_exploitability_sub_score *= @modified_user_interaction.score
136
- end
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
137
178
 
138
- def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
139
- factor = @modified_scope.selected_choice[:name] == 'Changed' ? 1.08 : 1.0
179
+ 8.22 * merged_modified_attack_vector.score * merged_modified_attack_complexity.score *
180
+ privilege_score * merged_modified_user_interaction.score
181
+ end
140
182
 
141
- ([factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min.round_up(1) * temporal_score)
183
+ def calculate_score(modified_impact_sub_score, modified_exploitability_sub_score, temporal_score)
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
142
189
 
190
+ Cvss3Helper.round_up(
191
+ [factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min
192
+ ) * temporal_score
193
+ end
143
194
  end
144
- end
195
+ end
@@ -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.
@@ -11,47 +12,46 @@
11
12
  require_relative '../cvss_property'
12
13
  require_relative '../cvss_metric'
13
14
 
14
- ##
15
- # This class represents a CVSS Temporal metric in version 3.
16
-
17
- class Cvss3Temporal < CvssMetric
18
-
19
- ##
20
- # Property of this metric
21
-
22
- attr_reader :exploit_code_maturity, :remediation_level, :report_confidence
23
-
15
+ module CvssSuite
24
16
  ##
25
- # Returns score of this metric
26
-
27
- def score
28
- return 1.0 unless valid?
29
- @exploit_code_maturity.score * @remediation_level.score * @report_confidence.score
30
- end
31
-
32
- private
33
-
34
- def init_properties
35
- @properties.push(@exploit_code_maturity =
36
- CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E', position: [8],
37
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
38
- { name: 'Unproven', abbreviation: 'U', weight: 0.91 },
39
- { name: 'Proof-of-Concept', abbreviation: 'P', weight: 0.94 },
40
- { name: 'Functional', abbreviation: 'F', weight: 0.97 },
41
- { name: 'High', abbreviation: 'H', weight: 1.0 }]))
42
- @properties.push(@remediation_level =
43
- CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL', position: [9],
44
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
45
- { name: 'Official Fix', abbreviation: 'O', weight: 0.95 },
46
- { name: 'Temporary Fix', abbreviation: 'T', weight: 0.96 },
47
- { name: 'Workaround', abbreviation: 'W', weight: 0.97 },
48
- { name: 'Unavailable', abbreviation: 'U', weight: 1.0 }]))
49
-
50
- @properties.push(@report_confidence =
51
- CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC', position: [10],
52
- choices: [{ name: 'Not Defined', abbreviation: 'X', weight: 1.0 },
53
- { name: 'Unknown', abbreviation: 'U', weight: 0.92 },
54
- { name: 'Reasonable', abbreviation: 'R', weight: 0.96 },
55
- { name: 'Confirmed', abbreviation: 'C', weight: 1.0 }]))
17
+ # This class represents a CVSS Temporal metric in version 3.
18
+ class Cvss3Temporal < CvssMetric
19
+ ##
20
+ # Property of this metric
21
+ attr_reader :exploit_code_maturity, :remediation_level, :report_confidence
22
+
23
+ ##
24
+ # Returns score of this metric
25
+ def score
26
+ return 1.0 unless valid?
27
+
28
+ @exploit_code_maturity.score * @remediation_level.score * @report_confidence.score
29
+ end
30
+
31
+ private
32
+
33
+ def init_properties
34
+ @properties.push(@exploit_code_maturity =
35
+ CvssProperty.new(name: 'Exploit Code Maturity', abbreviation: 'E',
36
+ values: [{ name: 'Not Defined', abbreviation: 'X', 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 }]))
41
+ @properties.push(@remediation_level =
42
+ CvssProperty.new(name: 'Remediation Level', abbreviation: 'RL',
43
+ values: [{ name: 'Not Defined', abbreviation: 'X', 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 }]))
48
+
49
+ @properties.push(@report_confidence =
50
+ CvssProperty.new(name: 'Report Confidence', abbreviation: 'RC',
51
+ values: [{ name: 'Not Defined', abbreviation: 'X', 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 }]))
55
+ end
56
56
  end
57
- end
57
+ end