cvss-suite 1.1.2 → 1.2.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.
- checksums.yaml +5 -5
- data/CHANGES.md +19 -0
- data/README.md +25 -9
- data/lib/cvss_suite.rb +9 -2
- data/lib/cvss_suite/cvss.rb +23 -0
- data/lib/cvss_suite/cvss31/cvss31.rb +52 -0
- data/lib/cvss_suite/cvss31/cvss31_base.rb +95 -0
- data/lib/cvss_suite/cvss31/cvss31_environmental.rb +144 -0
- data/lib/cvss_suite/cvss31/cvss31_temporal.rb +57 -0
- data/lib/cvss_suite/helpers/extensions.rb +24 -0
- data/lib/cvss_suite/version.rb +2 -2
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6aacfd5bb6fb48310c6c6c5cb2821a247971ef6115cb7c4c86dddb4335d8dafd
|
4
|
+
data.tar.gz: 5c881abb0186de84cb10596ff12333a9e8934ed290b8fe762471aaf82f008177
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
[](https://rubygems.org/gems/cvss-suite)
|
4
4
|
[](https://rubygems.org/gems/cvss-suite)
|
5
|
-
[](https://www.first.org/cvss/
|
6
|
-
[](https://www.first.org/cvss/
|
5
|
+
[](https://www.first.org/cvss/v2/guide)
|
6
|
+
[](https://www.first.org/cvss/v3.0/user-guide)
|
7
|
+
[](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
|
35
|
-
version = cvss3.version
|
36
|
-
valid = cvss3.valid?
|
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
|
41
|
-
version = cvss.version
|
42
|
-
valid = cvss.valid?
|
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()
|
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.
|
data/lib/cvss_suite.rb
CHANGED
@@ -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 = [
|
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
|
data/lib/cvss_suite/cvss.rb
CHANGED
@@ -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
|
data/lib/cvss_suite/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# CVSS-Suite, a Ruby gem to manage the CVSS vector
|
2
2
|
#
|
3
|
-
# Copyright (c) Siemens AG,
|
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.
|
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.
|
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:
|
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
|
-
|
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.
|