dradis-calculator_cvss 3.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.github/issue_template.md +16 -0
  3. data/.github/pull_request_template.md +36 -0
  4. data/.gitignore +10 -0
  5. data/CHANGELOG.md +64 -0
  6. data/CONTRIBUTING.md +3 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +339 -0
  9. data/README.md +40 -0
  10. data/Rakefile +1 -0
  11. data/app/assets/javascripts/dradis/plugins/calculators/cvss/calculator.js.coffee +135 -0
  12. data/app/assets/javascripts/dradis/plugins/calculators/cvss/manifests/application.js +7 -0
  13. data/app/assets/javascripts/dradis/plugins/calculators/cvss/manifests/tylium.js +2 -0
  14. data/app/assets/javascripts/dradis/plugins/calculators/cvss/vendor/cvsscalc30.js +689 -0
  15. data/app/assets/stylesheets/dradis/plugins/calculators/cvss/manifests/application.css.scss +4 -0
  16. data/app/controllers/dradis/plugins/calculators/cvss/base_controller.rb +8 -0
  17. data/app/controllers/dradis/plugins/calculators/cvss/issues_controller.rb +37 -0
  18. data/app/models/dradis/plugins/calculators/cvss/v3.rb +38 -0
  19. data/app/views/dradis/plugins/calculators/cvss/_addons_menu.html.erb +1 -0
  20. data/app/views/dradis/plugins/calculators/cvss/_addons_menu_bs4.html.erb +1 -0
  21. data/app/views/dradis/plugins/calculators/cvss/base/_base.html.erb +123 -0
  22. data/app/views/dradis/plugins/calculators/cvss/base/_environmental.html.erb +192 -0
  23. data/app/views/dradis/plugins/calculators/cvss/base/_temporal.html.erb +67 -0
  24. data/app/views/dradis/plugins/calculators/cvss/base/index.html.erb +79 -0
  25. data/app/views/dradis/plugins/calculators/cvss/issues/_show-content.html.erb +20 -0
  26. data/app/views/dradis/plugins/calculators/cvss/issues/_show-tabs.html.erb +3 -0
  27. data/app/views/dradis/plugins/calculators/cvss/issues/edit.html.erb +103 -0
  28. data/app/views/layouts/dradis/plugins/calculators/cvss/base.html.erb +27 -0
  29. data/config/routes.rb +12 -0
  30. data/dradis-calculator_cvss.gemspec +27 -0
  31. data/lib/dradis-calculator_cvss.rb +13 -0
  32. data/lib/dradis/plugins/calculators/cvss/engine.rb +26 -0
  33. data/lib/dradis/plugins/calculators/cvss/gem_version.rb +21 -0
  34. data/lib/dradis/plugins/calculators/cvss/version.rb +15 -0
  35. metadata +118 -0
@@ -0,0 +1,40 @@
1
+ # CVSS score calculator for Dradis
2
+
3
+ This simple add-on adds a new page under `/calculators/cvss` for you to perform CVSS score calculations:
4
+
5
+ ![cvss_calculator](https://cloud.githubusercontent.com/assets/53006/12947493/f01cb53a-cffb-11e5-8f48-19072a3bd8c8.png)
6
+
7
+ The Common Vulnerability Scoring System Version 3.0 (CVSSv3) Calculator is heavily inspired in the one provided by [FIRST](https://www.first.org/cvss/calculator/3.0).
8
+
9
+
10
+ ## Install
11
+
12
+ Add this to your `Gemfile.plugins`:
13
+
14
+ gem 'dradis-calculator_cvss'
15
+
16
+ And
17
+
18
+ bundle install
19
+
20
+ Restart your Dradis server and you should be good to go.
21
+
22
+
23
+ ## More information
24
+
25
+ See the Dradis Framework's [README.md](https://github.com/dradis/dradisframework/blob/master/README.md)
26
+
27
+
28
+ ## Contributing
29
+
30
+ See the Dradis Framework's [CONTRIBUTING.md](https://github.com/dradis/dradisframework/blob/master/CONTRIBUTING.md)
31
+
32
+
33
+ ## License
34
+
35
+ Dradis Framework and all its components are released under [GNU General Public License version 2.0](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.
36
+
37
+
38
+ ## Feature requests and bugs
39
+
40
+ Please use the [Dradis Framework issue tracker](https://github.com/dradis/dradis-ce/issues) for add-on improvements and bug reports.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,135 @@
1
+ @CVSSCalculator =
2
+ calculate: ->
3
+ av = $("input[name=av]").val()
4
+ ac = $("input[name=ac]").val()
5
+ pr = $("input[name=pr]").val()
6
+ ui = $("input[name=ui]").val()
7
+ s = $("input[name=s]").val()
8
+ c = $("input[name=c]").val()
9
+ i = $("input[name=i]").val()
10
+ a = $("input[name=a]").val()
11
+
12
+ e = $("input[name=e]").val()
13
+ rl = $("input[name=rl]").val()
14
+ rc = $("input[name=rc]").val()
15
+
16
+ cr = $("input[name=cr]").val()
17
+ ir = $("input[name=ir]").val()
18
+ ar = $("input[name=ar]").val()
19
+ mav = $("input[name=mav]").val()
20
+ mac = $("input[name=mac]").val()
21
+ mpr = $("input[name=mpr]").val()
22
+ mui = $("input[name=mui]").val()
23
+ ms = $("input[name=ms]").val()
24
+ mc = $("input[name=mc]").val()
25
+ mi = $("input[name=mi]").val()
26
+ ma = $("input[name=ma]").val()
27
+
28
+ # AttackVector, AttackComplexity, PrivilegesRequired, UserInteraction, Scope,
29
+ # Confidentiality, Integrity, Availability, Exploitability, RemediationLevel,
30
+ # ReportConfidence, ConfidentialityRequirement, IntegrityRequirement,
31
+ # AvailabilityRequirement, ModifiedAttackVector, ModifiedAttackComplexity,
32
+ # ModifiedPrivilegesRequired, ModifiedUserInteraction, ModifiedScope,
33
+ # ModifiedConfidentiality, ModifiedIntegrity, ModifiedAvailability
34
+ output = CVSS.calculateCVSSFromMetrics(av, ac, pr, ui, s, c, i, a,
35
+ e, rl, rc,
36
+ cr, ir, ar, mav, mac, mpr, mui, ms, mc, mi, ma);
37
+
38
+
39
+ if output.success == true
40
+ $('input[type=submit]').attr('disabled', null)
41
+ $('[data-behavior~=cvss-error]').addClass('d-none').text('')
42
+ $('#base-score').text("#{output.baseMetricScore} (#{output.baseSeverity})")
43
+ $('#temporal-score').text("#{output.temporalMetricScore} (#{output.temporalSeverity})")
44
+ $('#environmental-score').text("#{output.environmentalMetricScore} (#{output.environmentalSeverity})")
45
+
46
+ issue_cvss = "#[CVSSv3.Vector]#\n"
47
+ issue_cvss += "#{output.vectorString}\n\n"
48
+ issue_cvss += "#[CVSSv3.BaseScore]#\n"
49
+ issue_cvss += "#{output.baseMetricScore}\n\n"
50
+ issue_cvss += "#[CVSSv3.BaseSeverity]#\n"
51
+ issue_cvss += "#{output.baseSeverity}\n\n"
52
+ issue_cvss += "#[CVSSv3.TemporalScore]#\n"
53
+ issue_cvss += "#{output.temporalMetricScore}\n\n"
54
+ issue_cvss += "#[CVSSv3.TemporalSeverity]#\n"
55
+ issue_cvss += "#{output.temporalSeverity}\n\n"
56
+ issue_cvss += "#[CVSSv3.EnvironmentalScore]#\n"
57
+ issue_cvss += "#{output.environmentalMetricScore}\n\n"
58
+ issue_cvss += "#[CVSSv3.EnvironmentalSeverity]#\n"
59
+ issue_cvss += "#{output.environmentalSeverity}\n\n"
60
+
61
+ # Base metrics
62
+ issue_cvss += "#[CVSSv3.BaseAttackVector]#\n"
63
+ issue_cvss += "#{$("button[name=av].btn-primary").data('label')}\n\n"
64
+ issue_cvss += "#[CVSSv3.BaseAttackComplexity]#\n"
65
+ issue_cvss += "#{$("button[name=ac].btn-primary").data('label')}\n\n"
66
+ issue_cvss += "#[CVSSv3.BasePrivilegesRequired]#\n"
67
+ issue_cvss += "#{$("button[name=pr].btn-primary").data('label')}\n\n"
68
+ issue_cvss += "#[CVSSv3.BaseUserInteraction]#\n"
69
+ issue_cvss += "#{$("button[name=ui].btn-primary").data('label')}\n\n"
70
+ issue_cvss += "#[CVSSv3.BaseScope]#\n"
71
+ issue_cvss += "#{$("button[name=s].btn-primary").data('label')}\n\n"
72
+ issue_cvss += "#[CVSSv3.BaseConfidentiality]#\n"
73
+ issue_cvss += "#{$("button[name=c].btn-primary").data('label')}\n\n"
74
+ issue_cvss += "#[CVSSv3.BaseIntegrity]#\n"
75
+ issue_cvss += "#{$("button[name=i].btn-primary").data('label')}\n\n"
76
+ issue_cvss += "#[CVSSv3.BaseAvailability]#\n"
77
+ issue_cvss += "#{$("button[name=a].btn-primary").data('label')}\n\n"
78
+
79
+ # Temporal metrics
80
+ issue_cvss += "#[CVSSv3.TemporalExploitCodeMaturity]#\n"
81
+ issue_cvss += "#{$("button[name=e].btn-primary").data('label')}\n\n"
82
+ issue_cvss += "#[CVSSv3.TemporalRemediationLevel]#\n"
83
+ issue_cvss += "#{$("button[name=rl].btn-primary").data('label')}\n\n"
84
+ issue_cvss += "#[CVSSv3.TemporalReportConfidence]#\n"
85
+ issue_cvss += "#{$("button[name=rc].btn-primary").data('label')}\n\n"
86
+
87
+ # Environmental metrics
88
+ issue_cvss += "#[CVSSv3.EnvironmentalConfidentialityRequirement]#\n"
89
+ issue_cvss += "#{$("button[name=cr].btn-primary").data('label')}\n\n"
90
+ issue_cvss += "#[CVSSv3.EnvironmentalIntegrityRequirement]#\n"
91
+ issue_cvss += "#{$("button[name=ir].btn-primary").data('label')}\n\n"
92
+ issue_cvss += "#[CVSSv3.EnvironmentalAvailabilityRequirement]#\n"
93
+ issue_cvss += "#{$("button[name=ar].btn-primary").data('label')}\n\n"
94
+
95
+ issue_cvss += "#[CVSSv3.ModifiedAttackVector]#\n"
96
+ issue_cvss += "#{$("button[name=mav].btn-primary").data('label')}\n\n"
97
+ issue_cvss += "#[CVSSv3.ModifiedAttackComplexity]#\n"
98
+ issue_cvss += "#{$("button[name=mac].btn-primary").data('label')}\n\n"
99
+ issue_cvss += "#[CVSSv3.ModifiedPrivilegesRequired]#\n"
100
+ issue_cvss += "#{$("button[name=mpr].btn-primary").data('label')}\n\n"
101
+ issue_cvss += "#[CVSSv3.ModifiedUserInteraction]#\n"
102
+ issue_cvss += "#{$("button[name=mui].btn-primary").data('label')}\n\n"
103
+ issue_cvss += "#[CVSSv3.ModifiedScope]#\n"
104
+ issue_cvss += "#{$("button[name=ms].btn-primary").data('label')}\n\n"
105
+ issue_cvss += "#[CVSSv3.ModifiedConfidentiality]#\n"
106
+ issue_cvss += "#{$("button[name=mc].btn-primary").data('label')}\n\n"
107
+ issue_cvss += "#[CVSSv3.ModifiedIntegrity]#\n"
108
+ issue_cvss += "#{$("button[name=mi].btn-primary").data('label')}\n\n"
109
+ issue_cvss += "#[CVSSv3.ModifiedAvailability]#\n"
110
+ issue_cvss += "#{$("button[name=ma].btn-primary").data('label')}\n\n"
111
+
112
+ $('textarea[name=cvss_fields]').val(issue_cvss)
113
+ else
114
+ errorMessage = ''
115
+
116
+ if output.errorType == 'MissingBaseMetric'
117
+ errorMessage = "The error type is '#{output.errorType}' and the metrics with errors are #{output.errorMetrics}."
118
+ else
119
+ errorMessage = "All Base metrics are required"
120
+
121
+ $('input[type=submit]').attr('disabled', 'disabled')
122
+ $('[data-behavior~=cvss-error]').removeClass('d-none').text(errorMessage)
123
+
124
+ document.addEventListener "turbolinks:load", ->
125
+ if $('[data-behavior~=cvss-buttons]').length
126
+ CVSSCalculator.calculate()
127
+ $('[data-behavior~=cvss-error]').addClass('d-none')
128
+
129
+ $('[data-behavior~=cvss-buttons] button').on 'click', ->
130
+
131
+ $this = $(this)
132
+ $this.parent().find('button').removeClass('active btn-primary');
133
+ $this.addClass('active btn-primary');
134
+ $("input[name=#{$this.attr('name')}]").val($this.val())
135
+ CVSSCalculator.calculate()
@@ -0,0 +1,7 @@
1
+ //= require jquery3
2
+ //= require popper
3
+ //= require bootstrap
4
+ //= require turbolinks
5
+
6
+ //= require dradis/plugins/calculators/cvss/vendor/cvsscalc30
7
+ //= require dradis/plugins/calculators/cvss/calculator
@@ -0,0 +1,2 @@
1
+ //= require dradis/plugins/calculators/cvss/vendor/cvsscalc30
2
+ //= require dradis/plugins/calculators/cvss/calculator
@@ -0,0 +1,689 @@
1
+ /* Copyright (c) 2015, FIRST.ORG, INC.
2
+ * All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
5
+ * following conditions are met:
6
+ * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
7
+ * disclaimer.
8
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
9
+ * following disclaimer in the documentation and/or other materials provided with the distribution.
10
+ * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
11
+ * products derived from this software without specific prior written permission.
12
+ *
13
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
14
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
16
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
18
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
19
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20
+ */
21
+
22
+ /* This JavaScript contains two main functions. Both take CVSS metric values and calculate CVSS scores for Base,
23
+ * Temporal and Environmental metric groups, their associated severity ratings, and an overall Vector String.
24
+ *
25
+ * Use CVSS.calculateCVSSFromMetrics if you wish to pass metric values as individual parameters.
26
+ * Use CVSS.calculateCVSSFromVector if you wish to pass metric values as a single Vector String.
27
+ *
28
+ * Changelog
29
+ *
30
+ * 2018-02-15 Darius Wiles Added a missing pair of parantheses in the Environmental score, specifically
31
+ * in the code setting envScore in the main clause (not the else clause). It was changed
32
+ * from "min (...), 10" to "min ((...), 10)". This correction does not alter any final
33
+ * Environmental scores.
34
+ *
35
+ * 2015-08-04 Darius Wiles Added CVSS.generateXMLFromMetrics and CVSS.generateXMLFromVector functions to return
36
+ * XML string representations of: a set of metric values; or a Vector String respectively.
37
+ * Moved all constants and functions to an object named "CVSS" to
38
+ * reduce the chance of conflicts in global variables when this file is combined with
39
+ * other JavaScript code. This will break all existing code that uses this file until
40
+ * the string "CVSS." is prepended to all references. The "Exploitability" metric has been
41
+ * renamed "Exploit Code Maturity" in the specification, so the same change has been made
42
+ * in the code in this file.
43
+ *
44
+ * 2015-04-24 Darius Wiles Environmental formula modified to eliminate undesirable behavior caused by subtle
45
+ * differences in rounding between Temporal and Environmental formulas that often
46
+ * caused the latter to be 0.1 lower than than the former when all Environmental
47
+ * metrics are "Not defined". Also added a RoundUp1 function to simplify formulas.
48
+ *
49
+ * 2015-04-09 Darius Wiles Added calculateCVSSFromVector function, license information, cleaned up code and improved
50
+ * comments.
51
+ *
52
+ * 2014-12-12 Darius Wiles Initial release for CVSS 3.0 Preview 2.
53
+ */
54
+
55
+ // Constants used in the formula. They are not declared as "const" to avoid problems in older browsers.
56
+
57
+ var CVSS = {};
58
+
59
+ CVSS.CVSSVersionIdentifier = "CVSS:3.0";
60
+ CVSS.exploitabilityCoefficient = 8.22;
61
+ CVSS.scopeCoefficient = 1.08;
62
+
63
+ // A regular expression to validate that a CVSS 3.0 vector string is well formed. It checks metrics and metric
64
+ // values. It does not check that a metric is specified more than once and it does not check that all base
65
+ // metrics are present. These checks need to be performed separately.
66
+
67
+ CVSS.vectorStringRegex_30 = /^CVSS:3\.0\/((AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])\/)*(AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$/;
68
+
69
+
70
+ // Associative arrays mapping each metric value to the constant defined in the CVSS scoring formula in the CVSS v3.0
71
+ // specification.
72
+
73
+ CVSS.Weight = {
74
+ AV: { N: 0.85, A: 0.62, L: 0.55, P: 0.2},
75
+ AC: { H: 0.44, L: 0.77},
76
+ PR: { U: {N: 0.85, L: 0.62, H: 0.27}, // These values are used if Scope is Unchanged
77
+ C: {N: 0.85, L: 0.68, H: 0.5}}, // These values are used if Scope is Changed
78
+ UI: { N: 0.85, R: 0.62},
79
+ S: { U: 6.42, C: 7.52}, // Note: not defined as constants in specification
80
+ CIA: { N: 0, L: 0.22, H: 0.56}, // C, I and A have the same weights
81
+
82
+ E: { X: 1, U: 0.91, P: 0.94, F: 0.97, H: 1},
83
+ RL: { X: 1, O: 0.95, T: 0.96, W: 0.97, U: 1},
84
+ RC: { X: 1, U: 0.92, R: 0.96, C: 1},
85
+
86
+ CIAR: { X: 1, L: 0.5, M: 1, H: 1.5} // CR, IR and AR have the same weights
87
+ };
88
+
89
+
90
+ // Severity rating bands, as defined in the CVSS v3.0 specification.
91
+
92
+ CVSS.severityRatings = [ { name: "None", bottom: 0.0, top: 0.0},
93
+ { name: "Low", bottom: 0.1, top: 3.9},
94
+ { name: "Medium", bottom: 4.0, top: 6.9},
95
+ { name: "High", bottom: 7.0, top: 8.9},
96
+ { name: "Critical", bottom: 9.0, top: 10.0} ];
97
+
98
+
99
+
100
+
101
+ /* ** CVSS.calculateCVSSFromMetrics **
102
+ *
103
+ * Takes Base, Temporal and Environmental metric values as individual parameters. Their values are in the short format
104
+ * defined in the CVSS v3.0 standard definition of the Vector String. For example, the AttackComplexity parameter
105
+ * should be either "H" or "L".
106
+ *
107
+ * Returns Base, Temporal and Environmental scores, severity ratings, and an overall Vector String. All Base metrics
108
+ * are required to generate this output. All Temporal and Environmental metric values are optional. Any that are not
109
+ * passed default to "X" ("Not Defined").
110
+ *
111
+ * The output is an object which always has a property named "success".
112
+ *
113
+ * If no errors are encountered, success is Boolean "true", and the following other properties are defined containing
114
+ * scores, severities and a vector string:
115
+ * baseMetricScore, baseSeverity,
116
+ * temporalMetricScore, temporalSeverity,
117
+ * environmentalMetricScore, environmentalSeverity,
118
+ * vectorString
119
+ *
120
+ * If errors are encountered, success is Boolean "false", and the following other properties are defined:
121
+ * errorType - a string indicating the error. Either:
122
+ * "MissingBaseMetric", if at least one Base metric has not been defined; or
123
+ * "UnknownMetricValue", if at least one metric value is invalid.
124
+ * errorMetrics - an array of strings representing the metrics at fault. The strings are abbreviated versions of the
125
+ * metrics, as defined in the CVSS v3.0 standard definition of the Vector String.
126
+ */
127
+ CVSS.calculateCVSSFromMetrics = function (
128
+ AttackVector, AttackComplexity, PrivilegesRequired, UserInteraction, Scope, Confidentiality, Integrity, Availability,
129
+ ExploitCodeMaturity, RemediationLevel, ReportConfidence,
130
+ ConfidentialityRequirement, IntegrityRequirement, AvailabilityRequirement,
131
+ ModifiedAttackVector, ModifiedAttackComplexity, ModifiedPrivilegesRequired, ModifiedUserInteraction, ModifiedScope,
132
+ ModifiedConfidentiality, ModifiedIntegrity, ModifiedAvailability) {
133
+
134
+ // If input validation fails, this array is populated with strings indicating which metrics failed validation.
135
+ var badMetrics = [];
136
+
137
+ // ENSURE ALL BASE METRICS ARE DEFINED
138
+ //
139
+ // We need values for all Base Score metrics to calculate scores.
140
+ // If any Base Score parameters are undefined, create an array of missing metrics and return it with an error.
141
+
142
+ if (typeof AttackVector === "undefined" || AttackVector === "") { badMetrics.push("AV"); }
143
+ if (typeof AttackComplexity === "undefined" || AttackComplexity === "") { badMetrics.push("AC"); }
144
+ if (typeof PrivilegesRequired === "undefined" || PrivilegesRequired === "") { badMetrics.push("PR"); }
145
+ if (typeof UserInteraction === "undefined" || UserInteraction === "") { badMetrics.push("UI"); }
146
+ if (typeof Scope === "undefined" || Scope === "") { badMetrics.push("S"); }
147
+ if (typeof Confidentiality === "undefined" || Confidentiality === "") { badMetrics.push("C"); }
148
+ if (typeof Integrity === "undefined" || Integrity === "") { badMetrics.push("I"); }
149
+ if (typeof Availability === "undefined" || Availability === "") { badMetrics.push("A"); }
150
+
151
+ if (badMetrics.length > 0) {
152
+ return { success: false, errorType: "MissingBaseMetric", errorMetrics: badMetrics };
153
+ }
154
+
155
+
156
+ // STORE THE METRIC VALUES THAT WERE PASSED AS PARAMETERS
157
+ //
158
+ // Temporal and Environmental metrics are optional, so set them to "X" ("Not Defined") if no value was passed.
159
+
160
+ var AV = AttackVector;
161
+ var AC = AttackComplexity;
162
+ var PR = PrivilegesRequired;
163
+ var UI = UserInteraction;
164
+ var S = Scope;
165
+ var C = Confidentiality;
166
+ var I = Integrity;
167
+ var A = Availability;
168
+
169
+ var E = ExploitCodeMaturity || "X";
170
+ var RL = RemediationLevel || "X";
171
+ var RC = ReportConfidence || "X";
172
+
173
+ var CR = ConfidentialityRequirement || "X";
174
+ var IR = IntegrityRequirement || "X";
175
+ var AR = AvailabilityRequirement || "X";
176
+ var MAV = ModifiedAttackVector || "X";
177
+ var MAC = ModifiedAttackComplexity || "X";
178
+ var MPR = ModifiedPrivilegesRequired || "X";
179
+ var MUI = ModifiedUserInteraction || "X";
180
+ var MS = ModifiedScope || "X";
181
+ var MC = ModifiedConfidentiality || "X";
182
+ var MI = ModifiedIntegrity || "X";
183
+ var MA = ModifiedAvailability || "X";
184
+
185
+
186
+ // CHECK VALIDITY OF METRIC VALUES
187
+ //
188
+ // Use the Weight object to ensure that, for every metric, the metric value passed is valid.
189
+ // If any invalid values are found, create an array of their metrics and return it with an error.
190
+ //
191
+ // The Privileges Required (PR) weight depends on Scope, but when checking the validity of PR we must not assume
192
+ // that the given value for Scope is valid. We therefore always look at the weights for Unchanged Scope when
193
+ // performing this check. The same applies for validation of Modified Privileges Required (MPR).
194
+ //
195
+ // The Weights object does not contain "X" ("Not Defined") values for Environmental metrics because we replace them
196
+ // with their Base metric equivalents later in the function. For example, an MAV of "X" will be replaced with the
197
+ // value given for AV. We therefore need to explicitly allow a value of "X" for Environmental metrics.
198
+
199
+ if (!CVSS.Weight.AV.hasOwnProperty(AV)) { badMetrics.push("AV"); }
200
+ if (!CVSS.Weight.AC.hasOwnProperty(AC)) { badMetrics.push("AC"); }
201
+ if (!CVSS.Weight.PR.U.hasOwnProperty(PR)) { badMetrics.push("PR"); }
202
+ if (!CVSS.Weight.UI.hasOwnProperty(UI)) { badMetrics.push("UI"); }
203
+ if (!CVSS.Weight.S.hasOwnProperty(S)) { badMetrics.push("S"); }
204
+ if (!CVSS.Weight.CIA.hasOwnProperty(C)) { badMetrics.push("C"); }
205
+ if (!CVSS.Weight.CIA.hasOwnProperty(I)) { badMetrics.push("I"); }
206
+ if (!CVSS.Weight.CIA.hasOwnProperty(A)) { badMetrics.push("A"); }
207
+
208
+ if (!CVSS.Weight.E.hasOwnProperty(E)) { badMetrics.push("E"); }
209
+ if (!CVSS.Weight.RL.hasOwnProperty(RL)) { badMetrics.push("RL"); }
210
+ if (!CVSS.Weight.RC.hasOwnProperty(RC)) { badMetrics.push("RC"); }
211
+
212
+ if (!(CR === "X" || CVSS.Weight.CIAR.hasOwnProperty(CR))) { badMetrics.push("CR"); }
213
+ if (!(IR === "X" || CVSS.Weight.CIAR.hasOwnProperty(IR))) { badMetrics.push("IR"); }
214
+ if (!(AR === "X" || CVSS.Weight.CIAR.hasOwnProperty(AR))) { badMetrics.push("AR"); }
215
+ if (!(MAV === "X" || CVSS.Weight.AV.hasOwnProperty(MAV))) { badMetrics.push("MAV"); }
216
+ if (!(MAC === "X" || CVSS.Weight.AC.hasOwnProperty(MAC))) { badMetrics.push("MAC"); }
217
+ if (!(MPR === "X" || CVSS.Weight.PR.U.hasOwnProperty(MPR))) { badMetrics.push("MPR"); }
218
+ if (!(MUI === "X" || CVSS.Weight.UI.hasOwnProperty(MUI))) { badMetrics.push("MUI"); }
219
+ if (!(MS === "X" || CVSS.Weight.S.hasOwnProperty(MS))) { badMetrics.push("MS"); }
220
+ if (!(MC === "X" || CVSS.Weight.CIA.hasOwnProperty(MC))) { badMetrics.push("MC"); }
221
+ if (!(MI === "X" || CVSS.Weight.CIA.hasOwnProperty(MI))) { badMetrics.push("MI"); }
222
+ if (!(MA === "X" || CVSS.Weight.CIA.hasOwnProperty(MA))) { badMetrics.push("MA"); }
223
+
224
+ if (badMetrics.length > 0) {
225
+ return { success: false, errorType: "UnknownMetricValue", errorMetrics: badMetrics };
226
+ }
227
+
228
+
229
+
230
+ // GATHER WEIGHTS FOR ALL METRICS
231
+
232
+ var metricWeightAV = CVSS.Weight.AV [AV];
233
+ var metricWeightAC = CVSS.Weight.AC [AC];
234
+ var metricWeightPR = CVSS.Weight.PR [S][PR]; // PR depends on the value of Scope (S).
235
+ var metricWeightUI = CVSS.Weight.UI [UI];
236
+ var metricWeightS = CVSS.Weight.S [S];
237
+ var metricWeightC = CVSS.Weight.CIA [C];
238
+ var metricWeightI = CVSS.Weight.CIA [I];
239
+ var metricWeightA = CVSS.Weight.CIA [A];
240
+
241
+ var metricWeightE = CVSS.Weight.E [E];
242
+ var metricWeightRL = CVSS.Weight.RL [RL];
243
+ var metricWeightRC = CVSS.Weight.RC [RC];
244
+
245
+ // For metrics that are modified versions of Base Score metrics, e.g. Modified Attack Vector, use the value of
246
+ // the Base Score metric if the modified version value is "X" ("Not Defined").
247
+ var metricWeightCR = CVSS.Weight.CIAR [CR];
248
+ var metricWeightIR = CVSS.Weight.CIAR [IR];
249
+ var metricWeightAR = CVSS.Weight.CIAR [AR];
250
+ var metricWeightMAV = CVSS.Weight.AV [MAV !== "X" ? MAV : AV];
251
+ var metricWeightMAC = CVSS.Weight.AC [MAC !== "X" ? MAC : AC];
252
+ var metricWeightMPR = CVSS.Weight.PR [MS !== "X" ? MS : S] [MPR !== "X" ? MPR : PR]; // Depends on MS.
253
+ var metricWeightMUI = CVSS.Weight.UI [MUI !== "X" ? MUI : UI];
254
+ var metricWeightMS = CVSS.Weight.S [MS !== "X" ? MS : S];
255
+ var metricWeightMC = CVSS.Weight.CIA [MC !== "X" ? MC : C];
256
+ var metricWeightMI = CVSS.Weight.CIA [MI !== "X" ? MI : I];
257
+ var metricWeightMA = CVSS.Weight.CIA [MA !== "X" ? MA : A];
258
+
259
+
260
+
261
+ // CALCULATE THE CVSS BASE SCORE
262
+
263
+ var baseScore;
264
+ var impactSubScore;
265
+ var exploitabalitySubScore = CVSS.exploitabilityCoefficient * metricWeightAV * metricWeightAC * metricWeightPR * metricWeightUI;
266
+ var impactSubScoreMultiplier = (1 - ((1 - metricWeightC) * (1 - metricWeightI) * (1 - metricWeightA)));
267
+
268
+ if (S === 'U') {
269
+ impactSubScore = metricWeightS * impactSubScoreMultiplier;
270
+ } else {
271
+ impactSubScore = metricWeightS * (impactSubScoreMultiplier - 0.029) - 3.25 * Math.pow(impactSubScoreMultiplier - 0.02, 15);
272
+ }
273
+
274
+ if (impactSubScore <= 0) {
275
+ baseScore = 0;
276
+ } else {
277
+ if (S === 'U') {
278
+ baseScore = CVSS.roundUp1(Math.min((exploitabalitySubScore + impactSubScore), 10));
279
+ } else {
280
+ baseScore = CVSS.roundUp1(Math.min((exploitabalitySubScore + impactSubScore) * CVSS.scopeCoefficient, 10));
281
+ }
282
+ }
283
+
284
+
285
+
286
+ // CALCULATE THE CVSS TEMPORAL SCORE
287
+
288
+ var temporalScore = CVSS.roundUp1(baseScore * metricWeightE * metricWeightRL * metricWeightRC);
289
+
290
+
291
+ // CALCULATE THE CVSS ENVIRONMENTAL SCORE
292
+ //
293
+ // - envExploitabalitySubScore recalculates the Base Score Exploitability sub-score using any modified values from the
294
+ // Environmental metrics group in place of the values specified in the Base Score, if any have been defined.
295
+ // - envAdjustedImpactSubScore recalculates the Base Score Impact sub-score using any modified values from the
296
+ // Environmental metrics group in place of the values specified in the Base Score, and any additional weightings
297
+ // given in the Environmental metrics group.
298
+
299
+ var envScore;
300
+ var envModifiedImpactSubScore;
301
+ var envModifiedExploitabalitySubScore = CVSS.exploitabilityCoefficient * metricWeightMAV * metricWeightMAC * metricWeightMPR * metricWeightMUI;
302
+
303
+ var envImpactSubScoreMultiplier = Math.min (1 - (
304
+ (1 - metricWeightMC * metricWeightCR) *
305
+ (1 - metricWeightMI * metricWeightIR) *
306
+ (1 - metricWeightMA * metricWeightAR)), 0.915);
307
+
308
+ if (MS === "U" ||
309
+ (MS === "X" && S === "U")) {
310
+ envModifiedImpactSubScore = metricWeightMS * envImpactSubScoreMultiplier;
311
+ envScore = CVSS.roundUp1(CVSS.roundUp1(Math.min((envModifiedImpactSubScore + envModifiedExploitabalitySubScore), 10)) *
312
+ metricWeightE * metricWeightRL * metricWeightRC);
313
+ } else {
314
+ envModifiedImpactSubScore = metricWeightMS * (envImpactSubScoreMultiplier - 0.029) - 3.25 * Math.pow(envImpactSubScoreMultiplier - 0.02, 15);
315
+ envScore = CVSS.roundUp1(CVSS.roundUp1(Math.min(CVSS.scopeCoefficient * (envModifiedImpactSubScore + envModifiedExploitabalitySubScore), 10)) *
316
+ metricWeightE * metricWeightRL * metricWeightRC);
317
+ }
318
+
319
+ if (envModifiedImpactSubScore <= 0) {
320
+ envScore = 0;
321
+ }
322
+
323
+
324
+ // CONSTRUCT THE VECTOR STRING
325
+
326
+ var vectorString =
327
+ CVSS.CVSSVersionIdentifier +
328
+ "/AV:" + AV +
329
+ "/AC:" + AC +
330
+ "/PR:" + PR +
331
+ "/UI:" + UI +
332
+ "/S:" + S +
333
+ "/C:" + C +
334
+ "/I:" + I +
335
+ "/A:" + A;
336
+
337
+ if (E !== "X") {vectorString = vectorString + "/E:" + E;}
338
+ if (RL !== "X") {vectorString = vectorString + "/RL:" + RL;}
339
+ if (RC !== "X") {vectorString = vectorString + "/RC:" + RC;}
340
+
341
+ if (CR !== "X") {vectorString = vectorString + "/CR:" + CR;}
342
+ if (IR !== "X") {vectorString = vectorString + "/IR:" + IR;}
343
+ if (AR !== "X") {vectorString = vectorString + "/AR:" + AR;}
344
+ if (MAV !== "X") {vectorString = vectorString + "/MAV:" + MAV;}
345
+ if (MAC !== "X") {vectorString = vectorString + "/MAC:" + MAC;}
346
+ if (MPR !== "X") {vectorString = vectorString + "/MPR:" + MPR;}
347
+ if (MUI !== "X") {vectorString = vectorString + "/MUI:" + MUI;}
348
+ if (MS !== "X") {vectorString = vectorString + "/MS:" + MS;}
349
+ if (MC !== "X") {vectorString = vectorString + "/MC:" + MC;}
350
+ if (MI !== "X") {vectorString = vectorString + "/MI:" + MI;}
351
+ if (MA !== "X") {vectorString = vectorString + "/MA:" + MA;}
352
+
353
+
354
+ // Return an object containing the scores for all three metric groups, and an overall vector string.
355
+
356
+ return {
357
+ success: true,
358
+ baseMetricScore: baseScore.toFixed(1),
359
+ baseSeverity: CVSS.severityRating( baseScore.toFixed(1) ),
360
+
361
+ temporalMetricScore: temporalScore.toFixed(1),
362
+ temporalSeverity: CVSS.severityRating( temporalScore.toFixed(1) ),
363
+
364
+ environmentalMetricScore: envScore.toFixed(1),
365
+ environmentalSeverity: CVSS.severityRating( envScore.toFixed(1) ),
366
+
367
+ vectorString: vectorString
368
+ };
369
+ };
370
+
371
+
372
+
373
+
374
+ /* ** CVSS.calculateCVSSFromVector **
375
+ *
376
+ * Takes Base, Temporal and Environmental metric values as a single string in the Vector String format defined
377
+ * in the CVSS v3.0 standard definition of the Vector String.
378
+ *
379
+ * Returns Base, Temporal and Environmental scores, severity ratings, and an overall Vector String. All Base metrics
380
+ * are required to generate this output. All Temporal and Environmental metric values are optional. Any that are not
381
+ * passed default to "X" ("Not Defined").
382
+ *
383
+ * See the comment for the CVSS.calculateCVSSFromMetrics function for details on the function output. In addition to
384
+ * the error conditions listed for that function, this function can also return:
385
+ * "MalformedVectorString", if the Vector String passed is does not conform to the format in the standard; or
386
+ * "MultipleDefinitionsOfMetric", if the Vector String is well formed but defines the same metric (or metrics),
387
+ * more than once.
388
+ */
389
+ CVSS.calculateCVSSFromVector = function ( vectorString ) {
390
+
391
+ var metricValues = {
392
+ AV: undefined, AC: undefined, PR: undefined, UI: undefined, S: undefined,
393
+ C: undefined, I: undefined, A: undefined,
394
+ E: undefined, RL: undefined, RC: undefined,
395
+ CR: undefined, IR: undefined, AR: undefined,
396
+ MAV: undefined, MAC: undefined, MPR: undefined, MUI: undefined, MS: undefined,
397
+ MC: undefined, MI: undefined, MA: undefined
398
+ };
399
+
400
+ // If input validation fails, this array is populated with strings indicating which metrics failed validation.
401
+ var badMetrics = [];
402
+
403
+ if (!CVSS.vectorStringRegex_30.test(vectorString)) {
404
+ return { success: false, errorType: "MalformedVectorString" };
405
+ }
406
+
407
+ var metricNameValue = vectorString.substring(CVSS.CVSSVersionIdentifier.length).split("/");
408
+
409
+ for (var i in metricNameValue) {
410
+ if (metricNameValue.hasOwnProperty(i)) {
411
+
412
+ var singleMetric = metricNameValue[i].split(":");
413
+
414
+ if (typeof metricValues[singleMetric[0]] === "undefined") {
415
+ metricValues[singleMetric[0]] = singleMetric[1];
416
+ } else {
417
+ badMetrics.push(singleMetric[0]);
418
+ }
419
+ }
420
+ }
421
+
422
+ if (badMetrics.length > 0) {
423
+ return { success: false, errorType: "MultipleDefinitionsOfMetric", errorMetrics: badMetrics };
424
+ }
425
+
426
+ return CVSS.calculateCVSSFromMetrics (
427
+ metricValues.AV, metricValues.AC, metricValues.PR, metricValues.UI, metricValues.S,
428
+ metricValues.C, metricValues.I, metricValues.A,
429
+ metricValues.E, metricValues.RL, metricValues.RC,
430
+ metricValues.CR, metricValues.IR, metricValues.AR,
431
+ metricValues.MAV, metricValues.MAC, metricValues.MPR, metricValues.MUI, metricValues.MS,
432
+ metricValues.MC, metricValues.MI, metricValues.MA);
433
+ };
434
+
435
+
436
+
437
+
438
+ /* ** CVSS.roundUp1 **
439
+ *
440
+ * Rounds up the number passed as a parameter to 1 decimal place and returns the result.
441
+ *
442
+ * Standard JavaScript errors thrown when arithmetic operations are performed on non-numbers will be returned if the
443
+ * given input is not a number.
444
+ */
445
+ CVSS.roundUp1 = function (d) {
446
+ return Math.ceil (d * 10) / 10;
447
+ };
448
+
449
+
450
+
451
+
452
+ /* ** CVSS.severityRating **
453
+ *
454
+ * Given a CVSS score, returns the name of the severity rating as defined in the CVSS standard.
455
+ * The input needs to be a number between 0.0 to 10.0, to one decimal place of precision.
456
+ *
457
+ * The following error values may be returned instead of a severity rating name:
458
+ * NaN (JavaScript "Not a Number") - if the input is not a number.
459
+ * undefined - if the input is a number that is not within the range of any defined severity rating.
460
+ */
461
+ CVSS.severityRating = function (score) {
462
+ var severityRatingLength = CVSS.severityRatings.length;
463
+
464
+ var validatedScore = Number(score);
465
+
466
+ if (isNaN(validatedScore)) {
467
+ return validatedScore;
468
+ }
469
+
470
+ for (var i = 0; i < severityRatingLength; i++) {
471
+ if (score >= CVSS.severityRatings[i].bottom && score <= CVSS.severityRatings[i].top) {
472
+ return CVSS.severityRatings[i].name;
473
+ }
474
+ }
475
+
476
+ return undefined;
477
+ };
478
+
479
+
480
+
481
+ ///////////////////////////////////////////////////////////////////////////
482
+ // DATA AND FUNCTIONS FOR CREATING AN XML REPRESENTATION OF A CVSS SCORE //
483
+ ///////////////////////////////////////////////////////////////////////////
484
+
485
+ // A mapping between abbreviated metric values and the string used in the XML representation.
486
+ // For example, a Remediation Level (RL) abbreviated metric value of "W" maps to "WORKAROUND".
487
+ // For brevity, Base metric values their modified equivalents in the Environmental metric group. We can do this
488
+ // because the latter is the same as the former, except it also includes a "NOT_DEFINED" value.
489
+
490
+ CVSS.XML_MetricNames = {
491
+ E: { X: "NOT_DEFINED", U: "UNPROVEN", P: "PROOF_OF_CONCEPT", F: "FUNCTIONAL", H: "HIGH"},
492
+ RL: { X: "NOT_DEFINED", O: "OFFICIAL_FIX", T: "TEMPORARY_FIX", W: "WORKAROUND", U: "UNAVAILABLE"},
493
+ RC: { X: "NOT_DEFINED", U: "UNKNOWN", R: "REASONABLE", C: "CONFIRMED"},
494
+
495
+ CIAR: { X: "NOT_DEFINED", L: "LOW", M: "MEDIUM", H: "HIGH"}, // CR, IR and AR use the same metric names
496
+ MAV: { N: "NETWORK", A: "ADJACENT_NETWORK", L: "LOCAL", P: "PHYSICAL", X: "NOT_DEFINED" },
497
+ MAC: { H: "HIGH", L: "LOW", X: "NOT_DEFINED" },
498
+ MPR: { N: "NONE", L: "LOW", H: "HIGH", X: "NOT_DEFINED" },
499
+ MUI: { N: "NONE", R: "REQUIRED", X: "NOT_DEFINED" },
500
+ MS: { U: "UNCHANGED", C: "CHANGED", X: "NOT_DEFINED" },
501
+ MCIA: { N: "NONE", L: "LOW", H: "HIGH", X: "NOT_DEFINED" } // C, I and A use the same metric names
502
+ };
503
+
504
+
505
+
506
+ /* ** CVSS.generateXMLFromMetrics **
507
+ *
508
+ * Takes Base, Temporal and Environmental metric values as individual parameters. Their values are in the short format
509
+ * defined in the CVSS v3.0 standard definition of the Vector String. For example, the AttackComplexity parameter
510
+ * should be either "H" or "L".
511
+ *
512
+ * Returns a single string containing the metric values in XML form. All Base metrics are required to generate this
513
+ * output. All Temporal and Environmental metric values are optional. Any that are not passed will be represented in
514
+ * the XML as NOT_DEFINED. The function returns a string for simplicity. It is arguably better to return the XML as
515
+ * a DOM object, but at the time of writing this leads to complexity due to older browsers using different JavaScript
516
+ * interfaces to do this. Also for simplicity, all Temporal and Environmental metrics are include in the string,
517
+ * even though those with a value of "Not Defined" do not need to be included.
518
+ *
519
+ * The output of this function is an object which always has a property named "success".
520
+ *
521
+ * If no errors are encountered, success is Boolean "true", and the "xmlString" property contains the XML string
522
+ * representation.
523
+ *
524
+ * If errors are encountered, success is Boolean "false", and other properties are defined as per the
525
+ * CVSS.calculateCVSSFromMetrics function. Refer to the comment for that function for more details.
526
+ */
527
+ CVSS.generateXMLFromMetrics = function (
528
+ AttackVector, AttackComplexity, PrivilegesRequired, UserInteraction, Scope, Confidentiality, Integrity, Availability,
529
+ ExploitCodeMaturity, RemediationLevel, ReportConfidence,
530
+ ConfidentialityRequirement, IntegrityRequirement, AvailabilityRequirement,
531
+ ModifiedAttackVector, ModifiedAttackComplexity, ModifiedPrivilegesRequired, ModifiedUserInteraction, ModifiedScope,
532
+ ModifiedConfidentiality, ModifiedIntegrity, ModifiedAvailability) {
533
+
534
+ // A string containing the XML we wish to output, with placeholders for the CVSS metrics we will substitute for
535
+ // their values, based on the inputs passed to this function.
536
+ var xmlTemplate =
537
+ '<?xml version="1.0" encoding="UTF-8"?>\n' +
538
+ '<cvssv3.0 xmlns="https://www.first.org/cvss/cvss-v3.0.xsd"\n' +
539
+ ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' +
540
+ ' xsi:schemaLocation="https://www.first.org/cvss/cvss-v3.0.xsd https://www.first.org/cvss/cvss-v3.0.xsd"\n' +
541
+ ' >\n' +
542
+ '\n' +
543
+ ' <base_metrics>\n' +
544
+ ' <attack-vector>__AttackVector__</attack-vector>\n' +
545
+ ' <attack-complexity>__AttackComplexity__</attack-complexity>\n' +
546
+ ' <privileges-required>__PrivilegesRequired__</privileges-required>\n' +
547
+ ' <user-interaction>__UserInteraction__</user-interaction>\n' +
548
+ ' <scope>__Scope__</scope>\n' +
549
+ ' <confidentiality-impact>__Confidentiality__</confidentiality-impact>\n' +
550
+ ' <integrity-impact>__Integrity__</integrity-impact>\n' +
551
+ ' <availability-impact>__Availability__</availability-impact>\n' +
552
+ ' <base-score>__BaseScore__</base-score>\n' +
553
+ ' <base-severity>__BaseSeverityRating__</base-severity>\n' +
554
+ ' </base_metrics>\n' +
555
+ '\n' +
556
+ ' <temporal_metrics>\n' +
557
+ ' <exploit-code-maturity>__ExploitCodeMaturity__</exploit-code-maturity>\n' +
558
+ ' <remediation-level>__RemediationLevel__</remediation-level>\n' +
559
+ ' <report-confidence>__ReportConfidence__</report-confidence>\n' +
560
+ ' <temporal-score>__TemporalScore__</temporal-score>\n' +
561
+ ' <temporal-severity>__TemporalSeverityRating__</temporal-severity>\n' +
562
+ ' </temporal_metrics>\n' +
563
+ '\n' +
564
+ ' <environmental_metrics>\n' +
565
+ ' <confidentiality-requirement>__ConfidentialityRequirement__</confidentiality-requirement>\n' +
566
+ ' <integrity-requirement>__IntegrityRequirement__</integrity-requirement>\n' +
567
+ ' <availability-requirement>__AvailabilityRequirement__</availability-requirement>\n' +
568
+ ' <modified-attack-vector>__ModifiedAttackVector__</modified-attack-vector>\n' +
569
+ ' <modified-attack-complexity>__ModifiedAttackComplexity__</modified-attack-complexity>\n' +
570
+ ' <modified-privileges-required>__ModifiedPrivilegesRequired__</modified-privileges-required>\n' +
571
+ ' <modified-user-interaction>__ModifiedUserInteraction__</modified-user-interaction>\n' +
572
+ ' <modified-scope>__ModifiedScope__</modified-scope>\n' +
573
+ ' <modified-confidentiality-impact>__ModifiedConfidentiality__</modified-confidentiality-impact>\n' +
574
+ ' <modified-integrity-impact>__ModifiedIntegrity__</modified-integrity-impact>\n' +
575
+ ' <modified-availability-impact>__ModifiedAvailability__</modified-availability-impact>\n' +
576
+ ' <environmental-score>__EnvironmentalScore__</environmental-score>\n' +
577
+ ' <environmental-severity>__EnvironmentalSeverityRating__</environmental-severity>\n' +
578
+ ' </environmental_metrics>\n' +
579
+ '\n' +
580
+ '</cvssv3.0>\n';
581
+
582
+
583
+ // Call CVSS.calculateCVSSFromMetrics to validate all the parameters and generate scores and severity ratings.
584
+ // If that function returns an error, immediately return it to the caller of this function.
585
+ var result = CVSS.calculateCVSSFromMetrics (
586
+ AttackVector, AttackComplexity, PrivilegesRequired, UserInteraction, Scope, Confidentiality, Integrity, Availability,
587
+ ExploitCodeMaturity, RemediationLevel, ReportConfidence,
588
+ ConfidentialityRequirement, IntegrityRequirement, AvailabilityRequirement,
589
+ ModifiedAttackVector, ModifiedAttackComplexity, ModifiedPrivilegesRequired, ModifiedUserInteraction, ModifiedScope,
590
+ ModifiedConfidentiality, ModifiedIntegrity, ModifiedAvailability);
591
+
592
+ if (result.success !== true) {
593
+ return result;
594
+ }
595
+
596
+ var xmlOutput = xmlTemplate;
597
+ xmlOutput = xmlOutput.replace ("__AttackVector__", CVSS.XML_MetricNames["MAV"][AttackVector]);
598
+ xmlOutput = xmlOutput.replace ("__AttackComplexity__", CVSS.XML_MetricNames["MAC"][AttackComplexity]);
599
+ xmlOutput = xmlOutput.replace ("__PrivilegesRequired__", CVSS.XML_MetricNames["MPR"][PrivilegesRequired]);
600
+ xmlOutput = xmlOutput.replace ("__UserInteraction__", CVSS.XML_MetricNames["MUI"][UserInteraction]);
601
+ xmlOutput = xmlOutput.replace ("__Scope__", CVSS.XML_MetricNames["MS"][Scope]);
602
+ xmlOutput = xmlOutput.replace ("__Confidentiality__", CVSS.XML_MetricNames["MCIA"][Confidentiality]);
603
+ xmlOutput = xmlOutput.replace ("__Integrity__", CVSS.XML_MetricNames["MCIA"][Integrity]);
604
+ xmlOutput = xmlOutput.replace ("__Availability__", CVSS.XML_MetricNames["MCIA"][Availability]);
605
+ xmlOutput = xmlOutput.replace ("__BaseScore__", result.baseMetricScore);
606
+ xmlOutput = xmlOutput.replace ("__BaseSeverityRating__", result.baseSeverity);
607
+
608
+ xmlOutput = xmlOutput.replace ("__ExploitCodeMaturity__", CVSS.XML_MetricNames["E"][ExploitCodeMaturity || "X"]);
609
+ xmlOutput = xmlOutput.replace ("__RemediationLevel__", CVSS.XML_MetricNames["RL"][RemediationLevel || "X"]);
610
+ xmlOutput = xmlOutput.replace ("__ReportConfidence__", CVSS.XML_MetricNames["RC"][ReportConfidence || "X"]);
611
+ xmlOutput = xmlOutput.replace ("__TemporalScore__", result.temporalMetricScore);
612
+ xmlOutput = xmlOutput.replace ("__TemporalSeverityRating__", result.temporalSeverity);
613
+
614
+ xmlOutput = xmlOutput.replace ("__ConfidentialityRequirement__", CVSS.XML_MetricNames["CIAR"][ConfidentialityRequirement || "X"]);
615
+ xmlOutput = xmlOutput.replace ("__IntegrityRequirement__", CVSS.XML_MetricNames["CIAR"][IntegrityRequirement || "X"]);
616
+ xmlOutput = xmlOutput.replace ("__AvailabilityRequirement__", CVSS.XML_MetricNames["CIAR"][AvailabilityRequirement || "X"]);
617
+ xmlOutput = xmlOutput.replace ("__ModifiedAttackVector__", CVSS.XML_MetricNames["MAV"][ModifiedAttackVector || "X"]);
618
+ xmlOutput = xmlOutput.replace ("__ModifiedAttackComplexity__", CVSS.XML_MetricNames["MAC"][ModifiedAttackComplexity || "X"]);
619
+ xmlOutput = xmlOutput.replace ("__ModifiedPrivilegesRequired__", CVSS.XML_MetricNames["MPR"][ModifiedPrivilegesRequired || "X"]);
620
+ xmlOutput = xmlOutput.replace ("__ModifiedUserInteraction__", CVSS.XML_MetricNames["MUI"][ModifiedUserInteraction || "X"]);
621
+ xmlOutput = xmlOutput.replace ("__ModifiedScope__", CVSS.XML_MetricNames["MS"][ModifiedScope || "X"]);
622
+ xmlOutput = xmlOutput.replace ("__ModifiedConfidentiality__", CVSS.XML_MetricNames["MCIA"][ModifiedConfidentiality || "X"]);
623
+ xmlOutput = xmlOutput.replace ("__ModifiedIntegrity__", CVSS.XML_MetricNames["MCIA"][ModifiedIntegrity || "X"]);
624
+ xmlOutput = xmlOutput.replace ("__ModifiedAvailability__", CVSS.XML_MetricNames["MCIA"][ModifiedAvailability || "X"]);
625
+ xmlOutput = xmlOutput.replace ("__EnvironmentalScore__", result.environmentalMetricScore);
626
+ xmlOutput = xmlOutput.replace ("__EnvironmentalSeverityRating__", result.environmentalSeverity);
627
+
628
+ return { success: true, xmlString: xmlOutput };
629
+ };
630
+
631
+
632
+
633
+ /* ** CVSS.generateXMLFromVector **
634
+ *
635
+ * Takes Base, Temporal and Environmental metric values as a single string in the Vector String format defined
636
+ * in the CVSS v3.0 standard definition of the Vector String.
637
+ *
638
+ * Returns an XML string representation of this input. See the comment for CVSS.generateXMLFromMetrics for more
639
+ * detail on inputs, return values and errors. In addition to the error conditions listed for that function, this
640
+ * function can also return:
641
+ * "MalformedVectorString", if the Vector String passed is does not conform to the format in the standard; or
642
+ * "MultipleDefinitionsOfMetric", if the Vector String is well formed but defines the same metric (or metrics),
643
+ * more than once.
644
+ */
645
+ CVSS.generateXMLFromVector = function ( vectorString ) {
646
+
647
+ var metricValues = {
648
+ AV: undefined, AC: undefined, PR: undefined, UI: undefined, S: undefined,
649
+ C: undefined, I: undefined, A: undefined,
650
+ E: undefined, RL: undefined, RC: undefined,
651
+ CR: undefined, IR: undefined, AR: undefined,
652
+ MAV: undefined, MAC: undefined, MPR: undefined, MUI: undefined, MS: undefined,
653
+ MC: undefined, MI: undefined, MA: undefined
654
+ };
655
+
656
+ // If input validation fails, this array is populated with strings indicating which metrics failed validation.
657
+ var badMetrics = [];
658
+
659
+ if (!CVSS.vectorStringRegex_30.test(vectorString)) {
660
+ return { success: false, errorType: "MalformedVectorString" };
661
+ }
662
+
663
+ var metricNameValue = vectorString.substring(CVSS.CVSSVersionIdentifier.length).split("/");
664
+
665
+ for (var i in metricNameValue) {
666
+ if (metricNameValue.hasOwnProperty(i)) {
667
+
668
+ var singleMetric = metricNameValue[i].split(":");
669
+
670
+ if (typeof metricValues[singleMetric[0]] === "undefined") {
671
+ metricValues[singleMetric[0]] = singleMetric[1];
672
+ } else {
673
+ badMetrics.push(singleMetric[0]);
674
+ }
675
+ }
676
+ }
677
+
678
+ if (badMetrics.length > 0) {
679
+ return { success: false, errorType: "MultipleDefinitionsOfMetric", errorMetrics: badMetrics };
680
+ }
681
+
682
+ return CVSS.generateXMLFromMetrics (
683
+ metricValues.AV, metricValues.AC, metricValues.PR, metricValues.UI, metricValues.S,
684
+ metricValues.C, metricValues.I, metricValues.A,
685
+ metricValues.E, metricValues.RL, metricValues.RC,
686
+ metricValues.CR, metricValues.IR, metricValues.AR,
687
+ metricValues.MAV, metricValues.MAC, metricValues.MPR, metricValues.MUI, metricValues.MS,
688
+ metricValues.MC, metricValues.MI, metricValues.MA);
689
+ };