cvss_rating 0.1.1
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 +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +27 -0
- data/Rakefile +22 -0
- data/cvss_rating.gemspec +23 -0
- data/lib/cvss_rating/version.rb +5 -0
- data/lib/cvss_rating.rb +453 -0
- data/test/cvss_rating_test.rb +61 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 86710948607aed7404a2f0fe021a0cb734cf1a6b
|
4
|
+
data.tar.gz: 8a98d94e813c4a0be0afe2b22b5f6fd66f5d5b63
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e1c0f19932a291bb805fd5c784ccc0d685bad189aab48ae5b2f2aed4bd56330c345cd3100a2530d12aff54259ea5499ca048f3137a2447e0c8423a829a860abe
|
7
|
+
data.tar.gz: 77af3c98596f4ad2d7f0a429f8275c7c487c91947ab88eb4a099187e84a0cb145518fc9829726bc6849fb78432957af850299934cce8f371494eff136d7719c6
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Stephen Kapp
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Cvss Rating
|
2
|
+
|
3
|
+
Implements CVSS Risk Rating version 2.0
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'cvss_rating'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install cvss_rating
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Check out the unit tests for examples of usage
|
22
|
+
|
23
|
+
## TODO
|
24
|
+
|
25
|
+
* CVSS 3.0 Support
|
26
|
+
* Code and API clean up
|
27
|
+
* More Unit Tests
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rdoc/task'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the app_version plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the app_version plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Cvss Rating'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
data/cvss_rating.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cvss_rating/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "cvss_rating"
|
8
|
+
spec.version = Cvss::Rating::VERSION
|
9
|
+
spec.authors = ["Stephen Kapp"]
|
10
|
+
spec.email = ["mort666@virus.org"]
|
11
|
+
spec.summary = %q{CVSS Risk Rating Calucation and Vector parsing}
|
12
|
+
spec.description = %q{CVSS Risk Rating Calucation and Vector parsing, implements CVSS 2.0 rating}
|
13
|
+
spec.homepage = "https://github.com/mort666/cvss_rating"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "minitest"
|
23
|
+
end
|
data/lib/cvss_rating.rb
ADDED
@@ -0,0 +1,453 @@
|
|
1
|
+
require "cvss_rating/version"
|
2
|
+
|
3
|
+
module Cvss
|
4
|
+
class Rating
|
5
|
+
|
6
|
+
attr_accessor :av, :ac, :au, :ci, :ii, :ai, :ex, :rl, :rc, :cdp, :td, :cr, :ir, :ar
|
7
|
+
attr_accessor :base, :temporal, :overall, :environmental, :impact, :exploitability, :adjimpact, :key
|
8
|
+
|
9
|
+
ACCESS_VECTOR = { :local => 0.395, :adjacent_network => 0.646, :network => 1.0 }
|
10
|
+
ACCESS_COMPLEXITY = { :high => 0.35, :medium => 0.61, :low => 0.71 }
|
11
|
+
AUTHENTICATION = { :none => 0.704, :single => 0.56, :multiple => 0.45 }
|
12
|
+
|
13
|
+
CONFIDENTIALITY_IMPACT = { :none => 0.0, :partial => 0.275, :complete => 0.660 }
|
14
|
+
INTEGRITY_IMPACT = { :none => 0.0, :partial => 0.275, :complete => 0.660 }
|
15
|
+
AVAILABILITY_IMPACT = { :none => 0.0, :partial => 0.275, :complete => 0.660 }
|
16
|
+
|
17
|
+
CONFIDENTIALITY_REQUIREMENT = { :low => 0.5, :medium => 1.0, :high => 1.51, :notdefined => -1.0 }
|
18
|
+
INTEGRITY_REQUIREMENT = { :low => 0.5, :medium => 1.0, :high => 1.51, :notdefined => -1.0 }
|
19
|
+
AVAILABILITY_REQUIREMENT = { :low => 0.5, :medium => 1.0, :high => 1.51, :notdefined => -1.0 }
|
20
|
+
|
21
|
+
EXPLOITABILITY = { :unproven => 0.85, :poc => 0.9, :functional => 0.95, :high => 1.0, :notdefined => -1.0 }
|
22
|
+
REMEDIATION_LEVEL = { :official => 0.87, :temporary => 0.9, :workaround => 0.95, :unavailable => 1.0, :notdefined => -1.0 }
|
23
|
+
REPORT_CONFIDENCE = { :unconfirmed => 0.90, :uncorroborated => 0.95, :confirmed => 1.0, :notdefined => -1.0 }
|
24
|
+
|
25
|
+
COLLATERAL_DAMAGE = { :none => 0.0, :low => 0.1, :low_medium => 0.3, :medium_high => 0.4, :high => 0.5, :notdefined => -1.0 }
|
26
|
+
TARGET_DISTRIBUTION = { :none => 0.0, :low => 0.25, :medium => 0.75, :high => 1.0, :notdefined => -1.0 }
|
27
|
+
|
28
|
+
ACCESS_VECTOR_KEY = { :local => 'L', :adjacent_network => 'A', :network => 'N' }
|
29
|
+
ACCESS_COMPLEXITY_KEY = { :high => 'H', :medium => 'M', :low => 'L' }
|
30
|
+
AUTHENTICATION_KEY = { :none => 'N', :single => 'S', :multiple => 'M' }
|
31
|
+
|
32
|
+
CONFIDENTIALITY_IMPACT_KEY = { :none => 'N', :partial => 'P', :complete => 'C' }
|
33
|
+
INTEGRITY_IMPACT_KEY = { :none => 'N', :partial => 'P', :complete => 'C' }
|
34
|
+
AVAILABILITY_IMPACT_KEY = { :none => 'N', :partial => 'P', :complete => 'C' }
|
35
|
+
|
36
|
+
CONFIDENTIALITY_REQUIREMENT_KEY = { :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
37
|
+
INTEGRITY_REQUIREMENT_KEY = { :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
38
|
+
AVAILABILITY_REQUIREMENT_KEY = { :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
39
|
+
|
40
|
+
EXPLOITABILITY_KEY = { :unproven => 'U', :poc => 'P', :functional => 'F', :high => 'H', :notdefined => 'ND' }
|
41
|
+
REMEDIATION_LEVEL_KEY = { :official => 'OF', :temporary => "TF", :workaround => 'W', :unavailable => 'U', :notdefined => 'ND' }
|
42
|
+
REPORT_CONFIDENCE_KEY = { :unconfirmed => 'UC', :uncorroborated => 'UR', :confirmed => 'C', :notdefined => 'ND' }
|
43
|
+
|
44
|
+
COLLATERAL_DAMAGE_KEY = { :none => 'N', :low => 'L', :low_medium => 'LM', :medium_high => 'MH', :high => 'H', :notdefined => 'ND' }
|
45
|
+
TARGET_DISTRIBUTION_KEY = { :none => 'N', :low => 'L', :medium => 'M', :high => 'H', :notdefined => 'ND' }
|
46
|
+
|
47
|
+
def initialize(attributes = {})
|
48
|
+
@base = nil
|
49
|
+
@temporal = nil
|
50
|
+
@environmental = nil
|
51
|
+
|
52
|
+
self.init
|
53
|
+
|
54
|
+
attributes.each do |name, value|
|
55
|
+
send("#{name}=", value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def init(ex = "ND", rl = "ND", rc = "ND", cd = "ND", td = "ND", cr = "ND", ir = "ND", ar = "ND")
|
60
|
+
self.ex = ex
|
61
|
+
self.rl = rl
|
62
|
+
self.rc = rc
|
63
|
+
|
64
|
+
self.cdp = cd
|
65
|
+
self.td = td
|
66
|
+
self.cr = cr
|
67
|
+
self.ir = ir
|
68
|
+
self.ar = ar
|
69
|
+
end
|
70
|
+
|
71
|
+
def scores(av, ac, au, ci, ii, ai, ex = "ND", rl = "ND", rc = "ND", cd = "ND", td = "ND", cr = "ND", ir = "ND", ar = "ND")
|
72
|
+
self.av = av
|
73
|
+
self.ac = ac
|
74
|
+
self.au = au
|
75
|
+
self.ci = ci
|
76
|
+
self.ii = ii
|
77
|
+
self.ai = ai
|
78
|
+
|
79
|
+
self.ex = ex
|
80
|
+
self.rl = rl
|
81
|
+
self.rc = rc
|
82
|
+
|
83
|
+
self.cd = cd
|
84
|
+
self.td = td
|
85
|
+
self.cr = cr
|
86
|
+
self.ir = ir
|
87
|
+
self.ar = ar
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_key(vector, value)
|
91
|
+
get_key = eval(vector + "_KEY")[(eval(vector).select { |k,v| v == value }).keys[0]]
|
92
|
+
end
|
93
|
+
|
94
|
+
def noenvironmental
|
95
|
+
if get_key("COLLATERAL_DAMAGE", @cdp) == "ND" && get_key("TARGET_DISTRIBUTION", @td) == "ND" && get_key("CONFIDENTIALITY_REQUIREMENT", @cr) == "ND" && get_key("INTEGRITY_REQUIREMENT", @ir) == "ND" && get_key("AVAILABILITY_REQUIREMENT", @ar) == "ND"
|
96
|
+
return true
|
97
|
+
else
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def notemporal
|
103
|
+
if get_key("EXPLOITABILITY", @ex) == "ND" && get_key("REMEDIATION_LEVEL", @rl) == "ND" && get_key("REPORT_CONFIDENCE", @rc) == "ND"
|
104
|
+
return true
|
105
|
+
else
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_key
|
111
|
+
@key = "AV:%s/AC:%s/Au:%s/C:%s/I:%s/A:%s" % [ get_key("ACCESS_VECTOR", @av),
|
112
|
+
get_key("ACCESS_COMPLEXITY", @ac),
|
113
|
+
get_key("AUTHENTICATION", @au),
|
114
|
+
get_key("CONFIDENTIALITY_IMPACT", @ci),
|
115
|
+
get_key("INTEGRITY_IMPACT", @ii),
|
116
|
+
get_key("AVAILABILITY_IMPACT", @ai)]
|
117
|
+
|
118
|
+
if !notemporal
|
119
|
+
@key += "/E:%s/RL:%s/RC:%s" % [ get_key("EXPLOITABILITY", @ex),
|
120
|
+
get_key("REMEDIATION_LEVEL", @rl),
|
121
|
+
get_key("REPORT_CONFIDENCE", @rc)]
|
122
|
+
end
|
123
|
+
|
124
|
+
if !noenvironmental
|
125
|
+
@key += "/CDP:%s/TD:%s/CR:%s/IR:%s/AR:%s" % [ get_key("COLLATERAL_DAMAGE", @cdp),
|
126
|
+
get_key("TARGET_DISTRIBUTION", @td),
|
127
|
+
get_key("CONFIDENTIALITY_REQUIREMENT", @cr),
|
128
|
+
get_key("INTEGRITY_REQUIREMENT", @ir),
|
129
|
+
get_key("AVAILABILITY_REQUIREMENT", @ar)]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def av=(av)
|
134
|
+
@av = case av
|
135
|
+
when "local", "L" then ACCESS_VECTOR[:local]
|
136
|
+
when "adjacent network", "A" then ACCESS_VECTOR[:adjacent_network]
|
137
|
+
when "network", "N" then ACCESS_VECTOR[:network]
|
138
|
+
else
|
139
|
+
raise "Bad Argument"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def av
|
144
|
+
av = get_key("ACCESS_VECTOR", @av) if !@av.nil?
|
145
|
+
end
|
146
|
+
|
147
|
+
def ac=(ac)
|
148
|
+
@ac = case ac
|
149
|
+
when "high", "H" then ACCESS_COMPLEXITY[:high]
|
150
|
+
when "medium", "M" then ACCESS_COMPLEXITY[:medium]
|
151
|
+
when "low", "L" then ACCESS_COMPLEXITY[:low]
|
152
|
+
else
|
153
|
+
raise "Bad Argument"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def ac
|
158
|
+
ac = get_key("ACCESS_COMPLEXITY", @ac) if !@ac.nil?
|
159
|
+
end
|
160
|
+
|
161
|
+
def au=(au)
|
162
|
+
@au = case au
|
163
|
+
when "none", "N" then AUTHENTICATION[:none]
|
164
|
+
when "single instance", "S" then AUTHENTICATION[:single]
|
165
|
+
when "multiple instance", "M" then AUTHENTICATION[:multiple]
|
166
|
+
else
|
167
|
+
raise "Bad Argument"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def au
|
172
|
+
au = get_key("AUTHENTICATION", @au) if !@au.nil?
|
173
|
+
end
|
174
|
+
|
175
|
+
def ci=(ci)
|
176
|
+
@ci = case ci
|
177
|
+
when "none", "N" then CONFIDENTIALITY_IMPACT[:none]
|
178
|
+
when "partial", "P" then CONFIDENTIALITY_IMPACT[:partial]
|
179
|
+
when "complete", "C" then CONFIDENTIALITY_IMPACT[:complete]
|
180
|
+
else
|
181
|
+
raise "Bad Argument"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def ci
|
186
|
+
ci = get_key("CONFIDENTIALITY_IMPACT", @ci) if !@ci.nil?
|
187
|
+
end
|
188
|
+
|
189
|
+
def ii=(ii)
|
190
|
+
@ii = case ii
|
191
|
+
when "none", "N" then INTEGRITY_IMPACT[:none]
|
192
|
+
when "partial", "P" then INTEGRITY_IMPACT[:partial]
|
193
|
+
when "complete", "C" then INTEGRITY_IMPACT[:complete]
|
194
|
+
else
|
195
|
+
raise "Bad Argument"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def ii
|
200
|
+
ii = get_key("INTEGRITY_IMPACT", @ii) if !@ii.nil?
|
201
|
+
end
|
202
|
+
|
203
|
+
def ai=(ai)
|
204
|
+
@ai = case ai
|
205
|
+
when "none", "N" then AVAILABILITY_IMPACT[:none]
|
206
|
+
when "partial", "P" then AVAILABILITY_IMPACT[:partial]
|
207
|
+
when "complete", "C" then AVAILABILITY_IMPACT[:complete]
|
208
|
+
else
|
209
|
+
raise "Bad Argument"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def ai
|
214
|
+
ai = get_key("AVAILABILITY_IMPACT", @ai) if !@ai.nil?
|
215
|
+
end
|
216
|
+
|
217
|
+
def ex=(ex)
|
218
|
+
@ex = case ex
|
219
|
+
when "unproven", "U" then EXPLOITABILITY[:unproven]
|
220
|
+
when "proof-of-concept", "P", "POC" then EXPLOITABILITY[:poc]
|
221
|
+
when "functional", "F" then EXPLOITABILITY[:functional]
|
222
|
+
when "high", "H" then EXPLOITABILITY[:high]
|
223
|
+
when "not defined", "ND" then EXPLOITABILITY[:notdefined]
|
224
|
+
else
|
225
|
+
raise "Bad Argument"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def ex
|
230
|
+
ex = get_key("EXPLOITABILITY", @ex) if !@ex.nil?
|
231
|
+
end
|
232
|
+
|
233
|
+
def rl=(rl)
|
234
|
+
@rl = case rl
|
235
|
+
when "official-fix", "O" then REMEDIATION_LEVEL[:official]
|
236
|
+
when "temporary-fix", "T", "TF" then REMEDIATION_LEVEL[:temporary]
|
237
|
+
when "workaround", "W" then REMEDIATION_LEVEL[:workaround]
|
238
|
+
when "unavailable", "U" then REMEDIATION_LEVEL[:unavailable]
|
239
|
+
when "not defined", "ND" then REMEDIATION_LEVEL[:notdefined]
|
240
|
+
else
|
241
|
+
raise "Bad Argument"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def rl
|
246
|
+
rl = get_key("REMEDIATION_LEVEL", @rl) if !@rl.nil?
|
247
|
+
end
|
248
|
+
|
249
|
+
def rc=(rc)
|
250
|
+
@rc = case rc
|
251
|
+
when "unconfirmed", "UC" then REPORT_CONFIDENCE[:unconfirmed]
|
252
|
+
when "uncorroborated", "UR" then REPORT_CONFIDENCE[:uncorroborated]
|
253
|
+
when "confirmed", "C" then REPORT_CONFIDENCE[:confirmed]
|
254
|
+
when "not defined", "ND" then REPORT_CONFIDENCE[:notdefined]
|
255
|
+
else
|
256
|
+
raise "Bad Argument"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def rc
|
261
|
+
rc = get_key("REPORT_CONFIDENCE", @rc) if !@av.nil?
|
262
|
+
end
|
263
|
+
|
264
|
+
def cdp=(cd)
|
265
|
+
@cdp = case cd
|
266
|
+
when "none", "N" then COLLATERAL_DAMAGE[:none]
|
267
|
+
when "low", "L" then COLLATERAL_DAMAGE[:low]
|
268
|
+
when "low-medium", "LM" then COLLATERAL_DAMAGE[:low_medium]
|
269
|
+
when "medium-high", "MH" then COLLATERAL_DAMAGE[:medium_high]
|
270
|
+
when "high", "H" then COLLATERAL_DAMAGE[:high]
|
271
|
+
when "not defined", "ND" then COLLATERAL_DAMAGE[:notdefined]
|
272
|
+
else
|
273
|
+
raise "Bad Argument"
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def cdp
|
278
|
+
cdp = get_key("COLLATERAL_DAMAGE", @cdp) if !@cdp.nil?
|
279
|
+
end
|
280
|
+
|
281
|
+
def td=(td)
|
282
|
+
@td = case td
|
283
|
+
when "none", "N" then TARGET_DISTRIBUTION[:none]
|
284
|
+
when "low", "L" then TARGET_DISTRIBUTION[:low]
|
285
|
+
when "medium", "M" then TARGET_DISTRIBUTION[:medium]
|
286
|
+
when "high", "H" then TARGET_DISTRIBUTION[:high]
|
287
|
+
when "not defined", "ND" then TARGET_DISTRIBUTION[:notdefined]
|
288
|
+
else
|
289
|
+
raise "Bad Argument"
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def td
|
294
|
+
td = get_key("TARGET_DISTRIBUTION", @td) if !@td.nil?
|
295
|
+
end
|
296
|
+
|
297
|
+
def cr=(cr)
|
298
|
+
@cr = case cr
|
299
|
+
when "low", "L" then CONFIDENTIALITY_REQUIREMENT[:low]
|
300
|
+
when "medium", "M" then CONFIDENTIALITY_REQUIREMENT[:medium]
|
301
|
+
when "high", "H" then CONFIDENTIALITY_REQUIREMENT[:high]
|
302
|
+
when "not defined", "ND" then CONFIDENTIALITY_REQUIREMENT[:notdefined]
|
303
|
+
else
|
304
|
+
raise "Bad Argument"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def cr
|
309
|
+
cr = get_key("CONFIDENTIALITY_REQUIREMENT", @cr) if !@cr.nil?
|
310
|
+
end
|
311
|
+
|
312
|
+
def ir=(ir)
|
313
|
+
@ir = case ir
|
314
|
+
when "low", "L" then INTEGRITY_REQUIREMENT[:low]
|
315
|
+
when "medium", "M" then INTEGRITY_REQUIREMENT[:medium]
|
316
|
+
when "high", "H" then INTEGRITY_REQUIREMENT[:high]
|
317
|
+
when "not defined", "ND" then INTEGRITY_REQUIREMENT[:notdefined]
|
318
|
+
else
|
319
|
+
raise "Bad Argument"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def ir
|
324
|
+
ir = get_key("INTEGRITY_REQUIREMENT", @ir) if !@ir.nil?
|
325
|
+
end
|
326
|
+
|
327
|
+
def ar=(ar)
|
328
|
+
@ar = case ar
|
329
|
+
when "low", "L" then AVAILABILITY_REQUIREMENT[:low]
|
330
|
+
when "medium", "M" then AVAILABILITY_REQUIREMENT[:medium]
|
331
|
+
when "high", "H" then AVAILABILITY_REQUIREMENT[:high]
|
332
|
+
when "not defined", "ND" then AVAILABILITY_REQUIREMENT[:notdefined]
|
333
|
+
else
|
334
|
+
raise "Bad Argument"
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def ar
|
339
|
+
ar = get_key("AVAILABILITY_REQUIREMENT", @ar) if !@ar.nil?
|
340
|
+
end
|
341
|
+
|
342
|
+
VECTORS = {
|
343
|
+
"av" => "av=",
|
344
|
+
"ac" => "ac=",
|
345
|
+
"au" => "au=",
|
346
|
+
"c" => "ci=",
|
347
|
+
"i" => "ii=",
|
348
|
+
"a" => "ai=",
|
349
|
+
"e" => "ex=",
|
350
|
+
"rl" => "rl=",
|
351
|
+
"rc" => "rc=",
|
352
|
+
"cdp" => "cdp=",
|
353
|
+
"td" => "td=",
|
354
|
+
"cr" => "cr=",
|
355
|
+
"ir" => "ir=",
|
356
|
+
"ar" => "ar="
|
357
|
+
}
|
358
|
+
|
359
|
+
def parse(vector)
|
360
|
+
string = vector.split("/")
|
361
|
+
len = string.length
|
362
|
+
|
363
|
+
self.init
|
364
|
+
|
365
|
+
@originalkey = vector
|
366
|
+
|
367
|
+
string.each do |section|
|
368
|
+
tmp = section.split(":")
|
369
|
+
send(VECTORS[tmp[0].downcase].to_sym, tmp[1])
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
def key
|
374
|
+
self.set_key
|
375
|
+
return @key
|
376
|
+
end
|
377
|
+
|
378
|
+
def to_s
|
379
|
+
printf "Base Score:\t\t\t%3.1f\n", @base
|
380
|
+
printf " Impact Subscore:\t\t%3.1f\n", @impact
|
381
|
+
printf " Exploitability Subscore:\t%3.1f\n", @exploitability
|
382
|
+
printf "Temporal Score:\t\t\t%3.1f\n", @temporal if !self.notemporal
|
383
|
+
printf "Environmental Score:\t\t%3.1f\n", @environmental if !self.noenvironmental
|
384
|
+
printf " Adjusted Impact Score:\t%3.1f\n", @adjimpact if !self.noenvironmental
|
385
|
+
printf "Overall Score:\t\t\t%3.1f\n", overallscore
|
386
|
+
end
|
387
|
+
|
388
|
+
def calculate
|
389
|
+
@impact = self.impactscore
|
390
|
+
@adjimpact = self.adjustedimpactscore
|
391
|
+
@exploitability = self.exploitabilityscore
|
392
|
+
@base = self.basescore
|
393
|
+
@temporal = self.temporalscore
|
394
|
+
@environmental = self.environmentalscore(self.adjustedtemporalscore(self.adjustedbasescore(@adjimpact, @exploitability)))
|
395
|
+
end
|
396
|
+
|
397
|
+
def adjustedimpactscore
|
398
|
+
tmp = []
|
399
|
+
tmp[0] = 10
|
400
|
+
tmp[1] = 10.41*(1-(1-@ci.abs*@cr.abs)*(1-@ii.abs*@ir.abs)*(1-@ai.abs*@ar.abs))
|
401
|
+
adjustedimpactscore = tmp.min
|
402
|
+
end
|
403
|
+
|
404
|
+
def adjustedbasescore(adjustedimpact, exploitabilityscore)
|
405
|
+
adjustedbasescore = (0.6*adjustedimpact + 0.4 * exploitabilityscore - 1.5) * impactfunction(adjustedimpact)
|
406
|
+
end
|
407
|
+
|
408
|
+
def adjustedtemporalscore(adjustedbasescore)
|
409
|
+
adjustedtemporalscore = adjustedbasescore * @ex.abs * @rl.abs * @rc.abs
|
410
|
+
end
|
411
|
+
|
412
|
+
def exploitabilityscore
|
413
|
+
exploitability = 20 * @ac.abs * @au.abs * @av.abs
|
414
|
+
end
|
415
|
+
|
416
|
+
def environmentalscore(adjustedtemporalscore)
|
417
|
+
environmentalscore = (adjustedtemporalscore + (10 - adjustedtemporalscore) * (@cdp == -1 ? 0 : @cdp.abs)) * @td.abs
|
418
|
+
|
419
|
+
return environmentalscore == 0.0 ? "Undefined" : environmentalscore
|
420
|
+
end
|
421
|
+
|
422
|
+
def overallscore
|
423
|
+
if self.noenvironmental
|
424
|
+
if self.notemporal
|
425
|
+
overallscore = @base
|
426
|
+
else
|
427
|
+
overallscore = @temporal
|
428
|
+
end
|
429
|
+
else
|
430
|
+
overallscore = @environmental
|
431
|
+
end
|
432
|
+
return overallscore
|
433
|
+
end
|
434
|
+
|
435
|
+
def impactfunction(impact)
|
436
|
+
return impact != 0 ? 1.176 : 0.0
|
437
|
+
end
|
438
|
+
|
439
|
+
def impactscore
|
440
|
+
impact = 10.41*(1.0-(1.0-@ci.abs)*(1.0-@ii.abs)*(1.0-@ai.abs))
|
441
|
+
end
|
442
|
+
|
443
|
+
def basescore
|
444
|
+
basescore = (0.6 * @impact + 0.4 * @exploitability - 1.5) * impactfunction(@impact)
|
445
|
+
end
|
446
|
+
|
447
|
+
def temporalscore
|
448
|
+
temporalscore = @base * @ex.abs * @rl.abs * @rc.abs
|
449
|
+
|
450
|
+
return temporalscore == 0.0 ? "Undefined" : temporalscore
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'active_support'
|
3
|
+
require 'cvss_rating'
|
4
|
+
|
5
|
+
class CvssRatingTest < MiniTest::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@cvss = Cvss::Rating.new
|
8
|
+
@cvss.av = "N"
|
9
|
+
@cvss.ac = "M"
|
10
|
+
@cvss.au = "N"
|
11
|
+
@cvss.ci = "P"
|
12
|
+
@cvss.ii = "P"
|
13
|
+
@cvss.ai = "P"
|
14
|
+
@cvss.set_key
|
15
|
+
|
16
|
+
@cvss_2 = Cvss::Rating.new
|
17
|
+
@cvss_2.av = "L"
|
18
|
+
@cvss_2.ac = "M"
|
19
|
+
@cvss_2.au = "M"
|
20
|
+
@cvss_2.ci = "P"
|
21
|
+
@cvss_2.ii = "C"
|
22
|
+
@cvss_2.ai = "C"
|
23
|
+
@cvss_2.cdp = "L"
|
24
|
+
@cvss_2.td = "H"
|
25
|
+
@cvss_2.cr = "M"
|
26
|
+
@cvss_2.ir = "M"
|
27
|
+
@cvss_2.ar = "M"
|
28
|
+
@cvss_2.set_key
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_cvss_rating_from_vector
|
32
|
+
cvss = Cvss::Rating.new
|
33
|
+
cvss.parse("AV:N/AC:M/Au:N/C:P/I:P/A:P")
|
34
|
+
assert_equal @cvss.key, cvss.key
|
35
|
+
|
36
|
+
assert_equal @cvss.base, cvss.base
|
37
|
+
|
38
|
+
assert_equal @cvss.overallscore, cvss.overallscore
|
39
|
+
|
40
|
+
cvss.init
|
41
|
+
cvss.parse("AV:L/AC:M/Au:M/C:P/I:C/A:C/CDP:L/TD:H/CR:M/IR:M/AR:M")
|
42
|
+
assert_equal @cvss_2.key, cvss.key
|
43
|
+
|
44
|
+
assert_equal @cvss_2.base, cvss.base
|
45
|
+
|
46
|
+
assert_equal @cvss_2.overallscore, cvss.overallscore
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_cvss_rating_parameters
|
50
|
+
cvss = Cvss::Rating.new
|
51
|
+
cvss.init
|
52
|
+
|
53
|
+
cvss.av = "local"
|
54
|
+
|
55
|
+
assert_equal @cvss_2.av, cvss.av
|
56
|
+
|
57
|
+
cvss.cdp = 'low'
|
58
|
+
|
59
|
+
assert_equal @cvss_2.cdp, cvss.cdp
|
60
|
+
end
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cvss_rating
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Kapp
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: CVSS Risk Rating Calucation and Vector parsing, implements CVSS 2.0 rating
|
42
|
+
email:
|
43
|
+
- mort666@virus.org
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- cvss_rating.gemspec
|
54
|
+
- lib/cvss_rating.rb
|
55
|
+
- lib/cvss_rating/version.rb
|
56
|
+
- test/cvss_rating_test.rb
|
57
|
+
homepage: https://github.com/mort666/cvss_rating
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.2.2
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: CVSS Risk Rating Calucation and Vector parsing
|
81
|
+
test_files:
|
82
|
+
- test/cvss_rating_test.rb
|