From 840bcac4b233f3aa987d05ecdb50c5058068f087 Mon Sep 17 00:00:00 2001 From: miko37 Date: Tue, 30 Apr 2024 16:43:54 +0200 Subject: [PATCH] first steps for cvss 4.0 calc --- lib/cvss_4_0.ts | 554 +++++++++++++++++++++++++++++++++++++++--------- lib/score.ts | 303 +++++++++++++++++++++++++- lib/testFile.ts | 11 +- 3 files changed, 759 insertions(+), 109 deletions(-) diff --git a/lib/cvss_4_0.ts b/lib/cvss_4_0.ts index 3839010..8062c0c 100644 --- a/lib/cvss_4_0.ts +++ b/lib/cvss_4_0.ts @@ -8,9 +8,9 @@ export const definitions = { mandatory: true, metrics: [ { name: "Network", abbr: "N", numerical: 0 }, - { name: "Adjacent", abbr: "A", numerical: 0 }, - { name: "Local", abbr: "L", numerical: 0 }, - { name: "Physical", abbr: "P", numerical: 0 } + { name: "Adjacent", abbr: "A", numerical: 0.1 }, + { name: "Local", abbr: "L", numerical: 0.2 }, + { name: "Physical", abbr: "P", numerical: 0.3 } ] }, { @@ -20,7 +20,7 @@ export const definitions = { mandatory: true, metrics: [ { name: "Low", abbr: "L", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 } + { name: "High", abbr: "H", numerical: 0.1 } ] }, { @@ -30,7 +30,7 @@ export const definitions = { mandatory: true, metrics: [ { name: "None", abbr: "N", numerical: 0 }, - { name: "Present", abbr: "P", numerical: 0 } + { name: "Present", abbr: "P", numerical: 0.1 } ] }, { @@ -40,8 +40,8 @@ export const definitions = { mandatory: true, metrics: [ { name: "None", abbr: "N", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 } + { name: "Low", abbr: "L", numerical: 0.1 }, + { name: "High", abbr: "H", numerical: 0.2 } ] }, { @@ -51,8 +51,8 @@ export const definitions = { mandatory: true, metrics: [ { name: "None", abbr: "N", numerical: 0 }, - { name: "Passive", abbr: "P", numerical: 0 }, - { name: "Active", abbr: "A", numerical: 0 } + { name: "Passive", abbr: "P", numerical: 0.1 }, + { name: "Active", abbr: "A", numerical: 0.2 } ] }, { @@ -61,8 +61,8 @@ export const definitions = { abbr: "VC", mandatory: true, metrics: [ - { name: "None", abbr: "N", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, + { name: "None", abbr: "N", numerical: 0.2 }, + { name: "Low", abbr: "L", numerical: 0.1 }, { name: "High", abbr: "H", numerical: 0 } ] }, @@ -72,8 +72,8 @@ export const definitions = { abbr: "VI", mandatory: true, metrics: [ - { name: "None", abbr: "N", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, + { name: "None", abbr: "N", numerical: 0.2 }, + { name: "Low", abbr: "L", numerical: 0.1 }, { name: "High", abbr: "H", numerical: 0 } ] }, @@ -83,8 +83,8 @@ export const definitions = { abbr: "VA", mandatory: true, metrics: [ - { name: "None", abbr: "N", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, + { name: "None", abbr: "N", numerical: 0.2 }, + { name: "Low", abbr: "L", numerical: 0.1 }, { name: "High", abbr: "H", numerical: 0 } ] }, @@ -94,9 +94,9 @@ export const definitions = { abbr: "SC", mandatory: true, metrics: [ - { name: "None", abbr: "N", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 } + { name: "None", abbr: "N", numerical: 0.3 }, + { name: "Low", abbr: "L", numerical: 0.2 }, + { name: "High", abbr: "H", numerical: 0.1 } ] }, { @@ -105,9 +105,10 @@ export const definitions = { abbr: "SI", mandatory: true, metrics: [ - { name: "None", abbr: "N", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 } + { name: "None", abbr: "N", numerical: 0.3 }, + { name: "Low", abbr: "L", numerical: 0.2 }, + { name: "High", abbr: "H", numerical: 0.1 }, + { name: "", abbr: "S", numerical: 0 } // no mentioned in the definitions but is in the max_composed.js ] }, { @@ -116,9 +117,10 @@ export const definitions = { abbr: "SA", mandatory: true, metrics: [ - { name: "None", abbr: "N", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 } + { name: "None", abbr: "N", numerical: 0.3 }, + { name: "Low", abbr: "L", numerical: 0.2 }, + { name: "High", abbr: "H", numerical: 0.1 }, + { name: "", abbr: "S", numerical: 0 } // no mentioned in the definitions but is in the max_composed.js ] }, { @@ -129,8 +131,8 @@ export const definitions = { metrics: [ { name: "Not Defined", abbr: "X", numerical: 0 }, { name: "Attacked", abbr: "A", numerical: 0 }, - { name: "POC", abbr: "P", numerical: 0 }, - { name: "Unreported", abbr: "U", numerical: 0 } + { name: "POC", abbr: "P", numerical: 0.1 }, + { name: "Unreported", abbr: "U", numerical: 0.2 } ] }, { @@ -141,8 +143,8 @@ export const definitions = { metrics: [ { name: "Not Defined", abbr: "X", numerical: 0 }, { name: "High", abbr: "H", numerical: 0 }, - { name: "Medium", abbr: "M", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 } + { name: "Medium", abbr: "M", numerical: 0.1 }, + { name: "Low", abbr: "L", numerical: 0.2 } ] }, { @@ -153,8 +155,8 @@ export const definitions = { metrics: [ { name: "Not Defined", abbr: "X", numerical: 0 }, { name: "High", abbr: "H", numerical: 0 }, - { name: "Medium", abbr: "M", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 } + { name: "Medium", abbr: "M", numerical: 0.1 }, + { name: "Low", abbr: "L", numerical: 0.2 } ] }, { @@ -165,8 +167,8 @@ export const definitions = { metrics: [ { name: "Not Defined", abbr: "X", numerical: 0 }, { name: "High", abbr: "H", numerical: 0 }, - { name: "Medium", abbr: "M", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 } + { name: "Medium", abbr: "M", numerical: 0.1 }, + { name: "Low", abbr: "L", numerical: 0.2 } ] }, { @@ -175,11 +177,11 @@ export const definitions = { abbr: "MAV", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "Network", abbr: "N", numerical: 0 }, - { name: "Adjacent", abbr: "A", numerical: 0 }, - { name: "Local", abbr: "L", numerical: 0 }, - { name: "Physical", abbr: "P", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "Network", abbr: "N" }, + { name: "Adjacent", abbr: "A" }, + { name: "Local", abbr: "L" }, + { name: "Physical", abbr: "P" } ] }, { @@ -188,9 +190,9 @@ export const definitions = { abbr: "MAC", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "High", abbr: "H" }, + { name: "Low", abbr: "L" } ] }, { @@ -199,9 +201,9 @@ export const definitions = { abbr: "MAT", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "None", abbr: "N", numerical: 0 }, - { name: "Present", abbr: "P", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "None", abbr: "N" }, + { name: "Present", abbr: "P" } ] }, { @@ -210,10 +212,10 @@ export const definitions = { abbr: "MPR", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "None", abbr: "N", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "High", abbr: "H" }, + { name: "Low", abbr: "L" }, + { name: "None", abbr: "N" } ] }, { @@ -222,10 +224,10 @@ export const definitions = { abbr: "MUI", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "None", abbr: "N", numerical: 0 }, - { name: "Passive", abbr: "P", numerical: 0 }, - { name: "Active", abbr: "A", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "None", abbr: "N" }, + { name: "Passive", abbr: "P" }, + { name: "Active", abbr: "A" } ] }, { @@ -234,10 +236,10 @@ export const definitions = { abbr: "MVC", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "None", abbr: "N", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "High", abbr: "H" }, + { name: "Low", abbr: "L" }, + { name: "None", abbr: "N" } ] }, { @@ -246,10 +248,10 @@ export const definitions = { abbr: "MVI", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "None", abbr: "N", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "High", abbr: "H" }, + { name: "Low", abbr: "L" }, + { name: "None", abbr: "N" } ] }, { @@ -258,10 +260,10 @@ export const definitions = { abbr: "MVA", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "None", abbr: "N", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "High", abbr: "H" }, + { name: "Low", abbr: "L" }, + { name: "None", abbr: "N" } ] }, { @@ -270,10 +272,10 @@ export const definitions = { abbr: "MSC", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "Negligible", abbr: "N", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "High", abbr: "H" }, + { name: "Low", abbr: "L" }, + { name: "None", abbr: "N" } ] }, { @@ -282,11 +284,11 @@ export const definitions = { abbr: "MSI", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "Negligible", abbr: "N", numerical: 0 }, - { name: "Safety", abbr: "S", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "High", abbr: "H" }, + { name: "Low", abbr: "L" }, + { name: "Negligible", abbr: "N" }, + { name: "Safety", abbr: "S" } ] }, { @@ -295,11 +297,11 @@ export const definitions = { abbr: "MSA", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "Negligible", abbr: "N", numerical: 0 }, - { name: "Safety", abbr: "S", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "High", abbr: "H" }, + { name: "Low", abbr: "L" }, + { name: "Negligible", abbr: "N" }, + { name: "Safety", abbr: "S" } ] }, { @@ -308,9 +310,9 @@ export const definitions = { abbr: "S", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "Negligible", abbr: "N", numerical: 0 }, - { name: "Present", abbr: "P", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "Negligible", abbr: "N" }, + { name: "Present", abbr: "P" } ] }, { @@ -319,9 +321,9 @@ export const definitions = { abbr: "Au", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "No", abbr: "N", numerical: 0 }, - { name: "Yes", abbr: "Y", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "No", abbr: "N" }, + { name: "Yes", abbr: "Y" } ] }, { @@ -330,10 +332,10 @@ export const definitions = { abbr: "R", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "Automatic", abbr: "A", numerical: 0 }, - { name: "User", abbr: "U", numerical: 0 }, - { name: "Irrecoverable", abbr: "I", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "Automatic", abbr: "A" }, + { name: "User", abbr: "U" }, + { name: "Irrecoverable", abbr: "I" } ] }, { @@ -342,9 +344,9 @@ export const definitions = { abbr: "V", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "Diffuse", abbr: "D", numerical: 0 }, - { name: "Concentrated", abbr: "C", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "Diffuse", abbr: "D" }, + { name: "Concentrated", abbr: "C" } ] }, { @@ -353,10 +355,10 @@ export const definitions = { abbr: "RE", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "Low", abbr: "L", numerical: 0 }, - { name: "Moderate", abbr: "M", numerical: 0 }, - { name: "High", abbr: "H", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "Low", abbr: "L" }, + { name: "Moderate", abbr: "M" }, + { name: "High", abbr: "H" } ] }, { @@ -365,12 +367,366 @@ export const definitions = { abbr: "U", mandatory: false, metrics: [ - { name: "Not Defined", abbr: "X", numerical: 0 }, - { name: "Clear", abbr: "Clear", numerical: 0 }, - { name: "Green", abbr: "Green", numerical: 0 }, - { name: "Amber", abbr: "Amber", numerical: 0 }, - { name: "Red", abbr: "Red", numerical: 0 } + { name: "Not Defined", abbr: "X" }, + { name: "Clear", abbr: "Clear" }, + { name: "Green", abbr: "Green" }, + { name: "Amber", abbr: "Amber" }, + { name: "Red", abbr: "Red" } ] } ] }; + +// Copyright FIRST, Red Hat, and contributors +// SPDX-License-Identifier: BSD-2-Clause + +export const cvssLookup_global = { + "000000": 10, + "000001": 9.9, + "000010": 9.8, + "000011": 9.5, + "000020": 9.5, + "000021": 9.2, + "000100": 10, + "000101": 9.6, + "000110": 9.3, + "000111": 8.7, + "000120": 9.1, + "000121": 8.1, + "000200": 9.3, + "000201": 9, + "000210": 8.9, + "000211": 8, + "000220": 8.1, + "000221": 6.8, + "001000": 9.8, + "001001": 9.5, + "001010": 9.5, + "001011": 9.2, + "001020": 9, + "001021": 8.4, + "001100": 9.3, + "001101": 9.2, + "001110": 8.9, + "001111": 8.1, + "001120": 8.1, + "001121": 6.5, + "001200": 8.8, + "001201": 8, + "001210": 7.8, + "001211": 7, + "001220": 6.9, + "001221": 4.8, + "002001": 9.2, + "002011": 8.2, + "002021": 7.2, + "002101": 7.9, + "002111": 6.9, + "002121": 5, + "002201": 6.9, + "002211": 5.5, + "002221": 2.7, + "010000": 9.9, + "010001": 9.7, + "010010": 9.5, + "010011": 9.2, + "010020": 9.2, + "010021": 8.5, + "010100": 9.5, + "010101": 9.1, + "010110": 9, + "010111": 8.3, + "010120": 8.4, + "010121": 7.1, + "010200": 9.2, + "010201": 8.1, + "010210": 8.2, + "010211": 7.1, + "010220": 7.2, + "010221": 5.3, + "011000": 9.5, + "011001": 9.3, + "011010": 9.2, + "011011": 8.5, + "011020": 8.5, + "011021": 7.3, + "011100": 9.2, + "011101": 8.2, + "011110": 8, + "011111": 7.2, + "011120": 7, + "011121": 5.9, + "011200": 8.4, + "011201": 7, + "011210": 7.1, + "011211": 5.2, + "011220": 5, + "011221": 3, + "012001": 8.6, + "012011": 7.5, + "012021": 5.2, + "012101": 7.1, + "012111": 5.2, + "012121": 2.9, + "012201": 6.3, + "012211": 2.9, + "012221": 1.7, + 100000: 9.8, + 100001: 9.5, + 100010: 9.4, + 100011: 8.7, + 100020: 9.1, + 100021: 8.1, + 100100: 9.4, + 100101: 8.9, + 100110: 8.6, + 100111: 7.4, + 100120: 7.7, + 100121: 6.4, + 100200: 8.7, + 100201: 7.5, + 100210: 7.4, + 100211: 6.3, + 100220: 6.3, + 100221: 4.9, + 101000: 9.4, + 101001: 8.9, + 101010: 8.8, + 101011: 7.7, + 101020: 7.6, + 101021: 6.7, + 101100: 8.6, + 101101: 7.6, + 101110: 7.4, + 101111: 5.8, + 101120: 5.9, + 101121: 5, + 101200: 7.2, + 101201: 5.7, + 101210: 5.7, + 101211: 5.2, + 101220: 5.2, + 101221: 2.5, + 102001: 8.3, + 102011: 7, + 102021: 5.4, + 102101: 6.5, + 102111: 5.8, + 102121: 2.6, + 102201: 5.3, + 102211: 2.1, + 102221: 1.3, + 110000: 9.5, + 110001: 9, + 110010: 8.8, + 110011: 7.6, + 110020: 7.6, + 110021: 7, + 110100: 9, + 110101: 7.7, + 110110: 7.5, + 110111: 6.2, + 110120: 6.1, + 110121: 5.3, + 110200: 7.7, + 110201: 6.6, + 110210: 6.8, + 110211: 5.9, + 110220: 5.2, + 110221: 3, + 111000: 8.9, + 111001: 7.8, + 111010: 7.6, + 111011: 6.7, + 111020: 6.2, + 111021: 5.8, + 111100: 7.4, + 111101: 5.9, + 111110: 5.7, + 111111: 5.7, + 111120: 4.7, + 111121: 2.3, + 111200: 6.1, + 111201: 5.2, + 111210: 5.7, + 111211: 2.9, + 111220: 2.4, + 111221: 1.6, + 112001: 7.1, + 112011: 5.9, + 112021: 3, + 112101: 5.8, + 112111: 2.6, + 112121: 1.5, + 112201: 2.3, + 112211: 1.3, + 112221: 0.6, + 200000: 9.3, + 200001: 8.7, + 200010: 8.6, + 200011: 7.2, + 200020: 7.5, + 200021: 5.8, + 200100: 8.6, + 200101: 7.4, + 200110: 7.4, + 200111: 6.1, + 200120: 5.6, + 200121: 3.4, + 200200: 7, + 200201: 5.4, + 200210: 5.2, + 200211: 4, + 200220: 4, + 200221: 2.2, + 201000: 8.5, + 201001: 7.5, + 201010: 7.4, + 201011: 5.5, + 201020: 6.2, + 201021: 5.1, + 201100: 7.2, + 201101: 5.7, + 201110: 5.5, + 201111: 4.1, + 201120: 4.6, + 201121: 1.9, + 201200: 5.3, + 201201: 3.6, + 201210: 3.4, + 201211: 1.9, + 201220: 1.9, + 201221: 0.8, + 202001: 6.4, + 202011: 5.1, + 202021: 2, + 202101: 4.7, + 202111: 2.1, + 202121: 1.1, + 202201: 2.4, + 202211: 0.9, + 202221: 0.4, + 210000: 8.8, + 210001: 7.5, + 210010: 7.3, + 210011: 5.3, + 210020: 6, + 210021: 5, + 210100: 7.3, + 210101: 5.5, + 210110: 5.9, + 210111: 4, + 210120: 4.1, + 210121: 2, + 210200: 5.4, + 210201: 4.3, + 210210: 4.5, + 210211: 2.2, + 210220: 2, + 210221: 1.1, + 211000: 7.5, + 211001: 5.5, + 211010: 5.8, + 211011: 4.5, + 211020: 4, + 211021: 2.1, + 211100: 6.1, + 211101: 5.1, + 211110: 4.8, + 211111: 1.8, + 211120: 2, + 211121: 0.9, + 211200: 4.6, + 211201: 1.8, + 211210: 1.7, + 211211: 0.7, + 211220: 0.8, + 211221: 0.2, + 212001: 5.3, + 212011: 2.4, + 212021: 1.4, + 212101: 2.4, + 212111: 1.2, + 212121: 0.5, + 212201: 1, + 212211: 0.3, + 212221: 0.1 +}; + +// Copyright FIRST, Red Hat, and contributors +// SPDX-License-Identifier: BSD-2-Clause + +export const maxComposed = { + // EQ1 + eq1: { + 0: ["AV:N/PR:N/UI:N/"], + 1: ["AV:A/PR:N/UI:N/", "AV:N/PR:L/UI:N/", "AV:N/PR:N/UI:P/"], + 2: ["AV:P/PR:N/UI:N/", "AV:A/PR:L/UI:P/"] + }, + // EQ2 + eq2: { + 0: ["AC:L/AT:N/"], + 1: ["AC:H/AT:N/", "AC:L/AT:P/"] + }, + // EQ3+EQ6 + eq3: { + 0: { + "0": ["VC:H/VI:H/VA:H/CR:H/IR:H/AR:H/"], + "1": ["VC:H/VI:H/VA:L/CR:M/IR:M/AR:H/", "VC:H/VI:H/VA:H/CR:M/IR:M/AR:M/"] + }, + 1: { + "0": ["VC:L/VI:H/VA:H/CR:H/IR:H/AR:H/", "VC:H/VI:L/VA:H/CR:H/IR:H/AR:H/"], + "1": [ + "VC:L/VI:H/VA:L/CR:H/IR:M/AR:H/", + "VC:L/VI:H/VA:H/CR:H/IR:M/AR:M/", + "VC:H/VI:L/VA:H/CR:M/IR:H/AR:M/", + "VC:H/VI:L/VA:L/CR:M/IR:H/AR:H/", + "VC:L/VI:L/VA:H/CR:H/IR:H/AR:M/" + ] + }, + 2: { "1": ["VC:L/VI:L/VA:L/CR:H/IR:H/AR:H/"] } + }, + // EQ4 + eq4: { + 0: ["SC:H/SI:S/SA:S/"], + 1: ["SC:H/SI:H/SA:H/"], + 2: ["SC:L/SI:L/SA:L/"] + }, + // EQ5 + eq5: { + 0: ["E:A/"], + 1: ["E:P/"], + 2: ["E:U/"] + } +}; + +// Copyright FIRST, Red Hat, and contributors +// SPDX-License-Identifier: BSD-2-Clause + +// max severity distances in EQs MacroVectors (+1) +export const maxSeverity = { + eq1: { + 0: 1, + 1: 4, + 2: 5 + }, + eq2: { + 0: 1, + 1: 2 + }, + eq3eq6: { + 0: { 0: 7, 1: 6 }, + 1: { 0: 8, 1: 8 }, + 2: { 1: 10 } + }, + eq4: { + 0: 6, + 1: 5, + 2: 4 + }, + eq5: { + 0: 1, + 1: 1, + 2: 1 + } +}; diff --git a/lib/score.ts b/lib/score.ts index e118a5c..92c6177 100644 --- a/lib/score.ts +++ b/lib/score.ts @@ -1,4 +1,10 @@ -import { CvssVectorObject, Metric, MetricPrivilegesRequired } from "./types"; +import { + CvssVectorObject, + MetricPrivilegesRequired, + Metric, + MetricScope, + MetricUnion +} from "./types"; import { util } from "./util"; /** @@ -262,10 +268,303 @@ function getExploitabilitySubScore(vector: string) { return Number(calculateExploitability(vectorObject, S === "C").toFixed(1)); } +// testing 4.0 score calc +// +// +// +// +// +// +// +// + +import { definitions, cvssLookup_global, maxComposed, maxSeverity } from "./cvss_4_0"; + +const findMetric4_0 = function (abbr: string) { + return definitions.definitions.find((def) => def.abbr === abbr); +}; + +const findMetricValue = function ( + abbr: string, + vectorObject: CvssVectorObject +) { + const definition = findMetric4_0(abbr); + const value = definition.metrics.find((metric) => metric.abbr === vectorObject[definition.abbr]); + + return value as T; +}; + +function getVectorObject(vector: string) { + const vectorArray = vector.split("/"); + const vectorObject = definitions.definitions + .map((definition) => definition.abbr) + .reduce((acc, curr) => { + acc[curr] = "X"; + return acc; + }, {} as CvssVectorObject); + + for (const entry of vectorArray) { + const values = entry.split(":"); + vectorObject[values[0]] = values[1]; + } + return vectorObject; +} + +function cvss4_0scoring(vector: string) { + const vectorObj = getVectorObject(vector); + + // EQ1 + const AVmetric = findMetricValue("AV", vectorObj); + const PRmetric = findMetricValue("PR", vectorObj); + const UImetric = findMetricValue("UI", vectorObj); + + // EQ2 + const ACmetric = findMetricValue("AC", vectorObj); + const ATmetric = findMetricValue("AT", vectorObj); + + // EQ3 + half of EQ6 + const VCmetric = findMetricValue("VC", vectorObj); + const VImetric = findMetricValue("VI", vectorObj); + const VAmetric = findMetricValue("VA", vectorObj); + + // EQ4 + const SCmetric = findMetricValue("SC", vectorObj); + const SImetric = findMetricValue("SI", vectorObj); + const SAmetric = findMetricValue("SA", vectorObj); + const MSImetric = findMetricValue("MSI", vectorObj); + const MSAmetric = findMetricValue("MSA", vectorObj); + + // EQ5 + const Emetric = findMetricValue("E", vectorObj); + + // half of EQ6 + const CRmetric = findMetricValue("CR", vectorObj); + const IRmetric = findMetricValue("IR", vectorObj); + const ARmetric = findMetricValue("AR", vectorObj); + + // calculate EQ levels + let eq1 = "0"; + let eq2 = "0"; + let eq3 = "0"; + let eq4 = "0"; + let eq5 = "0"; + let eq6 = "0"; + + // EQ1 + // 0 AV:N and PR:N and UI:N + // 1 (AV:N or PR:N or UI:N) and not (AV:N and PR:N and UI:N) and not AV:P + // 2 AV:P or not(AV:N or PR:N or UI:N) + if (AVmetric.abbr === "N" && PRmetric.abbr === "N" && UImetric.abbr === "N") eq1 = "0"; + else if ( + (AVmetric.abbr === "N" || PRmetric.abbr === "N" || UImetric.abbr === "N") && + !(AVmetric.abbr === "N" && PRmetric.abbr === "N" && UImetric.abbr === "N") && + !(AVmetric.abbr = "P") + ) + eq1 = "1"; + else if ( + AVmetric.abbr === "P" || + !(AVmetric.abbr === "N" || PRmetric.abbr === "N" || UImetric.abbr === "N") + ) + eq1 = "2"; + + // EQ2 + // 0 AC:L and AT:N + // 1 not (AC:L and AT:N) + if (ACmetric.abbr === "L" && ATmetric.abbr === "N") eq2 = "0"; + else if (!(ACmetric.abbr === "L" && ATmetric.abbr === "N")) eq2 = "1"; + + // EQ3 + // 0 VC:H and VI:H + // 1 not (VC:H and VI:H) and (VC:H or VI:H or VA:H) + // 2 not (VC:H or VI:H or VA:H) + if (VCmetric.abbr === "H" && VImetric.abbr === "H") eq3 = "0"; + else if ( + !(VCmetric.abbr === "H" && VImetric.abbr === "H") && + (VCmetric.abbr === "H" || VImetric.abbr === "H" || VAmetric.abbr === "H") + ) + eq3 = "1"; + else if (!(VCmetric.abbr === "H" || VImetric.abbr === "H" || VAmetric.abbr === "H")) eq3 = "2"; + + // EQ4 + // 0 MSI:S or MSA:S + // 1 not (MSI:S or MSA:S) and (SC:H or SI:H or SA:H) + // 2 not (MSI:S or MSA:S) and not (SC:H or SI:H or SA:H) + // If MSI=X or MSA=X they will default to the corresponding value of SI and SA according to the rules of Modified Base Metrics in section 4.2 (See Table 15). + // So if there are no modified base metrics, the highest value that EQ4 can reach is 1. + if (MSImetric.abbr === "S" || MSAmetric.abbr === "S") eq4 = "0"; + else if ( + !(MSImetric.abbr === "S" || MSAmetric.abbr === "S") && + (SCmetric.abbr === "H" || SImetric.abbr === "H" || SAmetric.abbr === "H") + ) + eq4 = "1"; + else if ( + !( + MSImetric.abbr === "S" || + MSImetric.abbr === "X" || + MSAmetric.abbr === "S" || + MSAmetric.abbr === "X" + ) && + !(SCmetric.abbr === "H" || SImetric.abbr === "H" || SAmetric.abbr === "H") + ) + eq4 = "2"; + + // EQ5 + // 0 E:A + // 1 E:P + // 2 E:U + // If E=X it will default to the worst case (i.e., E=A). + if (Emetric.abbr === "A" || Emetric.abbr === "X") eq5 = "0"; + else if (Emetric.abbr === "P") eq5 = "1"; + else if (Emetric.abbr === "U") eq5 = "2"; + + // EQ6 + // 0 (CR:H and VC:H) or (IR:H and VI:H) or (AR:H and VA:H) + // 1 not (CR:H and VC:H) and not (IR:H and VI:H) and not (AR:H and VA:H) + // If CR=X, IR=X or AR=X they will default to the worst case (i.e., CR=H, IR=H and AR=H). + if ( + ((CRmetric.abbr === "H" || CRmetric.abbr === "X") && VCmetric.abbr === "H") || + ((IRmetric.abbr === "H" || IRmetric.abbr === "X") && VImetric.abbr === "H") || + ((ARmetric.abbr === "H" || ARmetric.abbr === "X") && VAmetric.abbr === "H") + ) + eq6 = "0"; + else if ( + !((CRmetric.abbr === "H" || CRmetric.abbr === "X") && VCmetric.abbr === "H") && + !((IRmetric.abbr === "H" || IRmetric.abbr === "X") && VImetric.abbr === "H") && + !((ARmetric.abbr === "H" || ARmetric.abbr === "X") && VAmetric.abbr === "H") + ) + eq6 = "1"; + + // For each of the EQs + // The maximal scoring difference is determined as the difference between the current MacroVector and the lower MacroVector + // there is no lower MacroVector the available distance is set to NaN and then ignored in the further calculations + // The scores of each MacroVector can be found in the cvssLookup table + + const eq1NextLowerMarcoVectorScore = + cvssLookup_global["".concat("" + (parseInt(eq1) + 1), eq2, eq3, eq4, eq5, eq6)]; + const eq2NextLowerMarcoVectorScore = + cvssLookup_global["".concat(eq1, "" + (parseInt(eq2) + 1), eq3, eq4, eq5, eq6)]; + const eq4NextLowerMarcoVectorScore = + cvssLookup_global["".concat(eq1, eq2, eq3, "" + (parseInt(eq4) + 1), eq5, eq6)]; + const eq5NextLowerMarcoVectorScore = + cvssLookup_global["".concat(eq1, eq2, eq3, eq4, "" + (parseInt(eq5) + 1), eq6)]; + + // // EQ3 and EQ6 are joint see Table 30, an if case represents an change in level constraint f.e 11 -> 21 + let eq3eq6NextLowerMarcoVector = 0; + let eq3eq6NextLowerLeftMarcoVector = 0; + let eq3eq6NextLowerRightMarcoVector = 0; + if (eq3 === "1" && eq6 === "1") { + eq3eq6NextLowerMarcoVector = + cvssLookup_global["".concat(eq1, eq2, "" + (parseInt(eq3) + 1), eq4, eq5, eq6)]; + } else if (eq3 === "1" && eq6 === "0") { + eq3eq6NextLowerMarcoVector = + cvssLookup_global["".concat(eq1, eq2, eq3, eq4, eq5, "" + (parseInt(eq6) + 1))]; + } else if (eq3 === "0" && eq6 === "1") { + eq3eq6NextLowerMarcoVector = + cvssLookup_global["".concat(eq1, eq2, "" + (parseInt(eq3) + 1), eq4, eq5, eq6)]; + } else if (eq3 === "0" && eq6 === "0") { + eq3eq6NextLowerLeftMarcoVector = + cvssLookup_global["".concat(eq1, eq2, eq3, eq4, eq5, "" + (parseInt(eq6) + 1))]; + eq3eq6NextLowerRightMarcoVector = + cvssLookup_global["".concat(eq1, eq2, "" + (parseInt(eq3) + 1), eq4, eq5, eq6)]; + } // cannot exist path + else + eq3eq6NextLowerMarcoVector = + cvssLookup_global[ + "".concat(eq1, eq2, "" + (parseInt(eq3) + 1), eq4, eq5, "" + (parseInt(eq6) + 1)) + ]; + + // The severity distance of the to-be scored vector from a highest severity vector in the same MacroVector is determined + const eq1Maxima = maxComposed["eq1"][eq1]; + const eq2Maxima = maxComposed["eq2"][eq2]; + const eq3eq6Maxima = maxComposed["eq3"][eq3][eq6]; + const eq4Maxima = maxComposed["eq4"][eq4]; + const eq5Maxima = maxComposed["eq5"][eq5]; + + // combine all vector maximas to create all possible maximums + const possibleMaximumVectorString = []; + for (const eq1Max of eq1Maxima) { + for (const eq2Max of eq2Maxima) { + for (const eq3eq6Max of eq3eq6Maxima) { + for (const eq4Max of eq4Maxima) { + for (const eq5Max of eq5Maxima) { + possibleMaximumVectorString.push(eq1Max + eq2Max + eq3eq6Max + eq4Max + eq5Max); + } + } + } + } + } + + let max = ""; + for (let i = 0; i < possibleMaximumVectorString.length; i++) { + max = possibleMaximumVectorString[i]; + console.log(max); + const maxVectorObj = getVectorObject(max); + + const severity_distance_AV = + AVmetric.numerical - findMetricValue("AV", maxVectorObj).numerical; + const severity_distance_PR = + PRmetric.numerical - findMetricValue("PR", maxVectorObj).numerical; + const severity_distance_UI = + UImetric.numerical - findMetricValue("UI", maxVectorObj).numerical; + + const severity_distance_AC = + ACmetric.numerical - findMetricValue("AC", maxVectorObj).numerical; + const severity_distance_AT = + ATmetric.numerical - findMetricValue("AT", maxVectorObj).numerical; + + const severity_distance_VC = + VCmetric.numerical - findMetricValue("VC", maxVectorObj).numerical; + const severity_distance_VI = + VImetric.numerical - findMetricValue("VI", maxVectorObj).numerical; + const severity_distance_VA = + VAmetric.numerical - findMetricValue("VA", maxVectorObj).numerical; + + const severity_distance_SC = + SCmetric.numerical - findMetricValue("SC", maxVectorObj).numerical; + const severity_distance_SI = + SImetric.numerical - findMetricValue("SI", maxVectorObj).numerical; + const severity_distance_SA = + SAmetric.numerical - findMetricValue("SA", maxVectorObj).numerical; + + const severity_distance_CR = + CRmetric.numerical - findMetricValue("CR", maxVectorObj).numerical; + const severity_distance_IR = + IRmetric.numerical - findMetricValue("IR", maxVectorObj).numerical; + const severity_distance_AR = + ARmetric.numerical - findMetricValue("AR", maxVectorObj).numerical; + + if ( + [ + severity_distance_AV, + severity_distance_PR, + severity_distance_UI, + severity_distance_AC, + severity_distance_AT, + severity_distance_VC, + severity_distance_VI, + severity_distance_VA, + severity_distance_SC, + severity_distance_SI, + severity_distance_SA, + severity_distance_CR, + severity_distance_IR, + severity_distance_AR + ].some((met) => met < 0) + ) { + continue; + } + break; + } + console.log(max); + + // TODO : https://www.first.org/cvss/v4.0/specification-document#New-Scoring-System-Development step 1.3 +} + export const score = { getScore, getTemporalScore, getEnvironmentalScore, getImpactSubScore, - getExploitabilitySubScore + getExploitabilitySubScore, + cvss4_0scoring }; diff --git a/lib/testFile.ts b/lib/testFile.ts index 3291c0f..497a3f1 100644 --- a/lib/testFile.ts +++ b/lib/testFile.ts @@ -1,10 +1,5 @@ -import { util } from "./util"; -import { CVSS } from "../lib/cvss"; -// TODO: delete this file -console.log("Test File delete before merge"); +import { score } from "./score"; -const testVector = CVSS( - "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N/E:X/RL:X/RC:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X" -).getVersion(); +// TODO: delete this file -console.log(testVector); +score.cvss4_0scoring("CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:P/VC:N/VI:N/VA:N/SC:N/SI:N/SA:N");