cvss-suite 1.2.0 → 3.1.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.
@@ -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