cvss-suite 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: afb88b54004ef3913747597ae1168ed958f0c9b5
4
- data.tar.gz: 8c94135d2769d08a6bcc3c08681d09e586bcd959
2
+ SHA256:
3
+ metadata.gz: 6aacfd5bb6fb48310c6c6c5cb2821a247971ef6115cb7c4c86dddb4335d8dafd
4
+ data.tar.gz: 5c881abb0186de84cb10596ff12333a9e8934ed290b8fe762471aaf82f008177
5
5
  SHA512:
6
- metadata.gz: dd42ce66b758b6113fe4865efb111ee76b6b37c19cbbd33169447b92a143029edbc92222b32f1fd520a4737914b9de8609eb6b63dda957d4a41eedf038792454
7
- data.tar.gz: 8d84caab47da1365b5fec94a93d5cb4fa1e0990e749121edf7d529687301d1e694c33bd8c16cef6faaa560f5835d86f86b52a895d5fb92e8dc57116fafe4c03e
6
+ metadata.gz: 293c41865c1905f2ca44a34d7298813484312af93deb77f443411222df307df80f4a40781af2137b05f561e66fd8317196b5a8512ea82c21d565d4eb221492ff
7
+ data.tar.gz: 3c33b092a180ca728add5bcb4380881789f98652cf5476eb841ee23ee8b38a72e56cd7be916cfb297aa644d470830280826086561850c4625228a06e43bb82f2
data/CHANGES.md CHANGED
@@ -2,6 +2,25 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+ ## [1.2.0] - 2019-07-02
6
+
7
+ ### Notes
8
+ Because version 2.0 of this gem will include breaking changes, please make sure to include this gem in your gemfile as shown below to not automatically update to version 2.0.
9
+
10
+ ```ruby
11
+ gem 'cvss-suite', '~> 1.2'
12
+ ```
13
+
14
+ ### Improvements
15
+ * Added Severity
16
+ * Added CVSS 3.1
17
+ * CVSS 3.0 vectors now return 3.0 instead of 3 as version
18
+
19
+ ### Changes in CVSS 3.1 [Source] (https://www.first.org/cvss/v3.1/user-guide)
20
+ * The Temporal Score for all vulnerabilities which have a Base Score of 2.5, 5.0 or 10.0, Exploit Code Maturity (E) of High (H), Remediation Level (RL) of Unavailable (U) and Report Confidence (RC) of Unknown (U) is 0.1 lower in CVSS v3.1 than for 3.0.
21
+ * Some combinations of metrics have Environmental Scores that differ when scored with CVSS v3.1 rather than v3.0. This is due to a combination of the redefinition of Roundup and the change to the ModifiedImpact sub-formula. Less than 7% of metric combinations are 0.1 higher in CVSS v3.1 than v3.0, and less than 1% are 0.1 lower. No Environmental Scores differ by more than 0.1.
22
+ * Other implementations of the CVSS formulas may see different scoring changes between CVSS v3.0 and v3.1 if they previously generated different CVSS v3.0 scores due to the problems that the CVSS v3.1 formula changes are intended to fix.
23
+
5
24
  ## [1.1.2] - 2018-12-28
6
25
 
7
26
  ### Fixes
data/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  [![Gem Version](http://img.shields.io/gem/v/cvss-suite.svg)](https://rubygems.org/gems/cvss-suite)
4
4
  [![Ruby Version](https://img.shields.io/badge/Ruby-2.x-brightgreen.svg)](https://rubygems.org/gems/cvss-suite)
5
- [![Cvss Support](https://img.shields.io/badge/CVSS-v2-brightgreen.svg)](https://www.first.org/cvss/cvss-v2-guide.pdf)
6
- [![Cvss Support](https://img.shields.io/badge/CVSS-v3.0-brightgreen.svg)](https://www.first.org/cvss/cvss-v3-guide.pdf)
5
+ [![Cvss Support](https://img.shields.io/badge/CVSS-v2-brightgreen.svg)](https://www.first.org/cvss/v2/guide)
6
+ [![Cvss Support](https://img.shields.io/badge/CVSS-v3.0-brightgreen.svg)](https://www.first.org/cvss/v3.0/user-guide)
7
+ [![Cvss Support](https://img.shields.io/badge/CVSS-v3.1-brightgreen.svg)](https://www.first.org/cvss/v3.1/user-guide)
7
8
 
8
9
  This Ruby gem helps you to process the vector of the [**Common Vulnerability Scoring System**](https://www.first.org/cvss/specification-document).
9
10
  Besides calculating the Base, Temporal and Environmental Score, you are able to extract the selected option.
@@ -31,15 +32,24 @@ require 'cvss_suite'
31
32
 
32
33
  cvss3 = CvssSuite.new('CVSS:3.0/AV:L/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/CR:L/IR:M/AR:H/MAV:N/MAC:H/MPR:N/MUI:R/MS:U/MC:N/MI:L/MA:H')
33
34
 
34
- vector = cvss3.vector # 'CVSS:3.0/AV:L/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/CR:L/IR:M/AR:H/MAV:N/MAC:H/MPR:N/MUI:R/MS:U/MC:N/MI:L/MA:H"'
35
- version = cvss3.version # 3
36
- valid = cvss3.valid? # true
35
+ vector = cvss3.vector # 'CVSS:3.0/AV:L/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/CR:L/IR:M/AR:H/MAV:N/MAC:H/MPR:N/MUI:R/MS:U/MC:N/MI:L/MA:H'
36
+ version = cvss3.version # 3.0
37
+ valid = cvss3.valid? # true
38
+ severity = cvss3.severity # 'High'
39
+
40
+ cvss31 = CvssSuite.new('CVSS:3.1/AV:P/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:H/E:H/RL:U/RC:U')
41
+
42
+ vector = cvss31.vector # 'CVSS:3.1/AV:P/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:H/E:H/RL:U/RC:U'
43
+ version = cvss31.version # 3.1
44
+ valid = cvss31.valid? # true
45
+ severity = cvss31.severity # 'Medium'
37
46
 
38
47
  cvss = CvssSuite.new('AV:A/AC:M/Au:S/C:P/I:P/A:P/E:POC/RL:TF/RC:UC/CDP:L/TD:M/CR:M/IR:M/AR:M')
39
48
 
40
- vector = cvss.vector # 'AV:A/AC:M/Au:S/C:P/I:P/A:P/E:POC/RL:TF/RC:UC/CDP:L/TD:M/CR:M/IR:M/AR:M'
41
- version = cvss.version # 2
42
- valid = cvss.valid? # true
49
+ vector = cvss.vector # 'AV:A/AC:M/Au:S/C:P/I:P/A:P/E:POC/RL:TF/RC:UC/CDP:L/TD:M/CR:M/IR:M/AR:M'
50
+ version = cvss.version # 2
51
+ valid = cvss.valid? # true
52
+ severity = cvss.severity # 'Low'
43
53
 
44
54
  # Scores
45
55
  base_score = cvss.base_score # 4.9
@@ -73,7 +83,7 @@ valid = cvss.valid? # false
73
83
  version = cvss.version # will throw CvssSuite::Errors::InvalidVector: Vector is not valid!
74
84
  cvss.base_score # will throw CvssSuite::Errors::InvalidVector: Vector is not valid!
75
85
 
76
- CvssSuite.new() # will throw a ArgumentError
86
+ CvssSuite.new() # will throw a ArgumentError
77
87
 
78
88
  cvss = CvssSuite.new('AV:N/AC:P/C:P/AV:U/RL:OF/RC:C') # invalid vector, authentication is missing
79
89
  version = cvss.version # 2
@@ -91,6 +101,12 @@ Currently it is not possible to leave an attribute blank instead of ND/X. If you
91
101
 
92
102
  Because the documentation isn't clear on how to calculate the score if Modified Scope (CVSS 3.0 Environmental) is not defined, Modified Scope has to have a valid value (S/U).
93
103
 
104
+ There is a possibility of implementations generating different scores (+/- 0,1) due to small floating-point inaccuracies. This can happen due to differences in floating point arithmetic between different languages and hardware platforms.
105
+
106
+ ## Changelog
107
+
108
+ [Click here to see all changes.](https://raw.githubusercontent.com/siemens/cvss-suite/master/CHANGES.md)
109
+
94
110
  ## Contributing
95
111
 
96
112
  Bug reports and pull requests are welcome on GitHub at https://github.com/siemens/cvss-suite. This project is intended to be a safe, welcoming space for collaboration.
@@ -10,6 +10,7 @@
10
10
 
11
11
  require 'cvss_suite/cvss2/cvss2'
12
12
  require 'cvss_suite/cvss3/cvss3'
13
+ require 'cvss_suite/cvss31/cvss31'
13
14
  require 'cvss_suite/version'
14
15
  require 'cvss_suite/helpers/extensions'
15
16
  require 'cvss_suite/errors'
@@ -19,7 +20,11 @@ require 'cvss_suite/invalid_cvss'
19
20
  # Module of this gem.
20
21
 
21
22
  module CvssSuite
22
- CVSS_VECTOR_BEGINNINGS = [{:string => 'AV:', :version => 2}, {:string => 'CVSS:3.0/', :version => 3}]
23
+ CVSS_VECTOR_BEGINNINGS = [
24
+ {:string => 'AV:', :version => 2},
25
+ {:string => 'CVSS:3.0/', :version => 3.0},
26
+ {:string => 'CVSS:3.1/', :version => 3.1}
27
+ ]
23
28
 
24
29
  ##
25
30
  # Returns a CVSS class by a +vector+.
@@ -30,8 +35,10 @@ module CvssSuite
30
35
  case version
31
36
  when 2
32
37
  Cvss2.new(@vector_string, version)
33
- when 3
38
+ when 3.0
34
39
  Cvss3.new(@vector_string, version)
40
+ when 3.1
41
+ Cvss31.new(@vector_string, version)
35
42
  else
36
43
  InvalidCvss.new
37
44
  end
@@ -57,6 +57,29 @@ class Cvss
57
57
  end
58
58
  end
59
59
 
60
+ ##
61
+ # Returns the severity of the CVSS vector.
62
+
63
+ def severity
64
+ check_validity
65
+
66
+ score = overall_score
67
+
68
+ if 0.0 == score
69
+ "None"
70
+ elsif (0.1..3.9).include? score
71
+ "Low"
72
+ elsif (4.0..6.9).include? score
73
+ "Medium"
74
+ elsif (7.0..8.9).include? score
75
+ "High"
76
+ elsif (9.0..10.0).include? score
77
+ "Critical"
78
+ else
79
+ "None"
80
+ end
81
+ end
82
+
60
83
  ##
61
84
  # Returns the Overall Score of the CVSS vector.
62
85
 
@@ -0,0 +1,52 @@
1
+ # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
+ #
3
+ # Copyright (c) Siemens AG, 2019
4
+ #
5
+ # Authors:
6
+ # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ #
8
+ # This work is licensed under the terms of the MIT license.
9
+ # See the LICENSE.md file in the top-level directory.
10
+
11
+ require_relative '../../../lib/cvss_suite/cvss'
12
+ require_relative 'cvss31_base'
13
+ require_relative 'cvss31_temporal'
14
+ require_relative 'cvss31_environmental'
15
+
16
+ ##
17
+ # This class represents a CVSS vector in version 3.1.
18
+
19
+ class Cvss31 < Cvss
20
+
21
+ ##
22
+ # Returns the Base Score of the CVSS vector.
23
+
24
+ def base_score
25
+ check_validity
26
+ @base.score.roundup
27
+ end
28
+
29
+ ##
30
+ # Returns the Temporal Score of the CVSS vector.
31
+
32
+ def temporal_score
33
+ (@base.score.roundup * @temporal.score).roundup
34
+ end
35
+
36
+ ##
37
+ # Returns the Environmental Score of the CVSS vector.
38
+
39
+ def environmental_score
40
+ return temporal_score unless @environmental.valid?
41
+ (@environmental.score @temporal.score).roundup
42
+ end
43
+
44
+ private
45
+
46
+ def init_metrics
47
+ @base = Cvss31Base.new(@properties)
48
+ @temporal = Cvss31Temporal.new(@properties)
49
+ @environmental = Cvss31Environmental.new(@properties)
50
+ end
51
+
52
+ end
@@ -0,0 +1,95 @@
1
+ # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
+ #
3
+ # Copyright (c) Siemens AG, 2019
4
+ #
5
+ # Authors:
6
+ # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ #
8
+ # This work is licensed under the terms of the MIT license.
9
+ # See the LICENSE.md file in the top-level directory.
10
+
11
+ require_relative '../cvss_property'
12
+ require_relative '../cvss_metric'
13
+ require_relative '../helpers/cvss3_helper'
14
+
15
+ ##
16
+ # This class represents a CVSS Base metric in version 3.1.
17
+
18
+ class Cvss31Base < 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
+
26
+ ##
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
41
+ end
42
+
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
49
+ end
50
+ 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
+ end
95
+
@@ -0,0 +1,144 @@
1
+ # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
+ #
3
+ # Copyright (c) Siemens AG, 2019
4
+ #
5
+ # Authors:
6
+ # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ #
8
+ # This work is licensed under the terms of the MIT license.
9
+ # See the LICENSE.md file in the top-level directory.
10
+
11
+ require_relative '../cvss_property'
12
+ require_relative '../cvss_metric'
13
+ require_relative '../helpers/cvss3_helper'
14
+
15
+ ##
16
+ # This class represents a CVSS Environmental metric in version 3.1.
17
+
18
+ class Cvss31Environmental < CvssMetric
19
+
20
+ ##
21
+ # Property of this metric
22
+
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
27
+
28
+ ##
29
+ # Returns score of this metric
30
+
31
+ def score(temporal_score)
32
+
33
+ privilege_score = Cvss3Helper.privileges_required_score @modified_privileges_required, @modified_scope
34
+
35
+ modified_exploitability_sub_score = modified_exploitability_sub privilege_score
36
+
37
+ isc_modified_score = isc_modified
38
+
39
+ modified_impact_sub_score = modified_impact_sub isc_modified_score
40
+
41
+ return 0 if modified_impact_sub_score <= 0
42
+
43
+ calculate_score modified_impact_sub_score, modified_exploitability_sub_score, temporal_score
44
+ end
45
+
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
114
+
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.9731 - 0.02)**13
118
+ else
119
+ 6.42 * isc_modified
120
+ end
121
+ end
122
+
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
127
+
128
+ [0.915, (1 - confidentiality_score * integrity_score * availability_score)].min
129
+ end
130
+
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
137
+
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
140
+
141
+ ([factor * (modified_impact_sub_score + modified_exploitability_sub_score), 10].min.round_up(1) * temporal_score)
142
+
143
+ end
144
+ end
@@ -0,0 +1,57 @@
1
+ # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
+ #
3
+ # Copyright (c) Siemens AG, 2019
4
+ #
5
+ # Authors:
6
+ # Oliver Hambörger <oliver.hamboerger@siemens.com>
7
+ #
8
+ # This work is licensed under the terms of the MIT license.
9
+ # See the LICENSE.md file in the top-level directory.
10
+
11
+ require_relative '../cvss_property'
12
+ require_relative '../cvss_metric'
13
+
14
+ ##
15
+ # This class represents a CVSS Temporal metric in version 3.1.
16
+
17
+ class Cvss31Temporal < CvssMetric
18
+
19
+ ##
20
+ # Property of this metric
21
+
22
+ attr_reader :exploit_code_maturity, :remediation_level, :report_confidence
23
+
24
+ ##
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 }]))
56
+ end
57
+ end
@@ -19,6 +19,18 @@ class Float
19
19
  def round_up(decimal_paces = 0)
20
20
  (self * 10.0**decimal_paces).ceil / 10.0**decimal_paces
21
21
  end
22
+
23
+ ##
24
+ # The “Round up” function in CVSS v3.0 has been renamed Roundup and is now defined more precisely to minimize the possibility of implementations generating different scores due to small floating-point inaccuracies. This can happen due to differences in floating point arithmetic between different languages and hardware platforms.
25
+
26
+ def roundup
27
+ output = (self * 100000).round
28
+ if (output % 10000) == 0
29
+ return output / 100000.0
30
+ else
31
+ return ((output / 10000).floor + 1) / 10.0
32
+ end
33
+ end
22
34
  end
23
35
 
24
36
  class Integer
@@ -29,4 +41,16 @@ class Integer
29
41
  def round_up(decimal_paces = 0)
30
42
  (self * 10.0**decimal_paces).ceil / 10.0**decimal_paces
31
43
  end
44
+
45
+ ##
46
+ # The “Round up” function in CVSS v3.0 has been renamed Roundup and is now defined more precisely to minimize the possibility of implementations generating different scores due to small floating-point inaccuracies. This can happen due to differences in floating point arithmetic between different languages and hardware platforms.
47
+
48
+ def roundup
49
+ output = (self * 100000).round
50
+ if (output % 10000) == 0
51
+ return output / 100000.0
52
+ else
53
+ return ((output / 10000).floor + 1) / 10.0
54
+ end
55
+ end
32
56
  end
@@ -1,6 +1,6 @@
1
1
  # CVSS-Suite, a Ruby gem to manage the CVSS vector
2
2
  #
3
- # Copyright (c) Siemens AG, 2016
3
+ # Copyright (c) Siemens AG, 2019
4
4
  #
5
5
  # Authors:
6
6
  # Oliver Hambörger <oliver.hamboerger@siemens.com>
@@ -9,5 +9,5 @@
9
9
  # See the LICENSE.md file in the top-level directory.
10
10
 
11
11
  module CvssSuite
12
- VERSION = "1.1.2"
12
+ VERSION = "1.2.0"
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cvss-suite
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oliver Hamboerger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-28 00:00:00.000000000 Z
11
+ date: 2019-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -115,6 +115,10 @@ files:
115
115
  - lib/cvss_suite/cvss3/cvss3_base.rb
116
116
  - lib/cvss_suite/cvss3/cvss3_environmental.rb
117
117
  - lib/cvss_suite/cvss3/cvss3_temporal.rb
118
+ - lib/cvss_suite/cvss31/cvss31.rb
119
+ - lib/cvss_suite/cvss31/cvss31_base.rb
120
+ - lib/cvss_suite/cvss31/cvss31_environmental.rb
121
+ - lib/cvss_suite/cvss31/cvss31_temporal.rb
118
122
  - lib/cvss_suite/cvss_metric.rb
119
123
  - lib/cvss_suite/cvss_property.rb
120
124
  - lib/cvss_suite/errors.rb
@@ -141,8 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
145
  - !ruby/object:Gem::Version
142
146
  version: '0'
143
147
  requirements: []
144
- rubyforge_project:
145
- rubygems_version: 2.5.1
148
+ rubygems_version: 3.0.3
146
149
  signing_key:
147
150
  specification_version: 4
148
151
  summary: Ruby gem for processing cvss vectors.