UNPKG

@turingpointde/cvss.js

Version:

A tiny library to work with cvss vectors

265 lines (228 loc) 8.02 kB
import { CvssVectorObject, MetricPrivilegesRequired, Metric } from "./types"; import { util } from "./util"; /** * Parses the vector to a number score */ function getScore(vector: string) { const vectorObject = util.getVectorObject(vector); const scopeChanged = vectorObject.S === "C"; const ISCBase = calculateISCBase(vectorObject); const ISC = calculateISC(ISCBase, scopeChanged, vector); if (ISC <= 0) return 0; const exploitability = calculateExploitability(vectorObject, scopeChanged); if (scopeChanged) { return roundUp(Math.min(1.08 * (ISC + exploitability), 10), 1, vector); } return roundUp(Math.min(ISC + exploitability, 10), 1, vector); } /** * Parses the vector to the temporal score */ function getTemporalScore(vector: string) { const vectorObject = util.getVectorObject(vector); const baseScore = getScore(vector); const eMetric = util.findMetricValue<Metric>("E", vectorObject); const exploitCodeMaturity = eMetric ? eMetric.numerical : 1; const rMetric = util.findMetricValue<Metric>("RL", vectorObject); const remediationLevel = rMetric ? rMetric.numerical : 1; const rcMetric = util.findMetricValue<Metric>("RC", vectorObject); const reportConfidence = rcMetric ? rcMetric.numerical : 1; return roundUp( baseScore * exploitCodeMaturity * remediationLevel * reportConfidence, 1, vector ); } /** * Calculate the ISC base based on the cvss vector object */ function calculateISCBase(vectorObject: CvssVectorObject) { const cValue = util.findMetricValue<Metric>("C", vectorObject).numerical; const iValue = util.findMetricValue<Metric>("I", vectorObject).numerical; const aValue = util.findMetricValue<Metric>("A", vectorObject).numerical; return 1 - (1 - cValue) * (1 - iValue) * (1 - aValue); } /** * Parses the vector to the environmental score */ function getEnvironmentalScore(vector: string) { const vectorObject = util.getVectorObject(vector); const scopeChanged = vectorObject.MS === "X" ? vectorObject.S === "C" : vectorObject.MS === "C"; const modifiedISCBase = calculateISCModifiedBase(vectorObject); const modifiedExploitability = calculateModifiedExploitability( vectorObject, scopeChanged ); const modifiedISC = calculateModifiedISC( modifiedISCBase, scopeChanged, vector ); if (modifiedISC <= 0) return 0; const e = util.findMetricValue<Metric>("E", vectorObject); const rl = util.findMetricValue<Metric>("RL", vectorObject); const rc = util.findMetricValue<Metric>("RC", vectorObject); const eValue = e ? e.numerical : 1; const rlValue = rl ? rl.numerical : 1; const rcValue = rc ? rc.numerical : 1; if (!scopeChanged) { return roundUp( roundUp(Math.min(modifiedISC + modifiedExploitability, 10), 1, vector) * eValue * rlValue * rcValue, 1, vector ); } return roundUp( roundUp( Math.min(1.08 * (modifiedISC + modifiedExploitability), 10), 1, vector ) * eValue * rlValue * rcValue, 1, vector ); } /** * Calculates the ISC value based on the ISC base, whether the scope has changed and the vector string */ function calculateISC(iscBase: number, scopeChanged: boolean, vector: string) { if (!scopeChanged) return 6.42 * iscBase; if (util.getVersion(vector) === "3.0") { return 7.52 * (iscBase - 0.029) - 3.25 * Math.pow(iscBase - 0.02, 15); } return 7.52 * (iscBase - 0.029) - 3.25 * Math.pow(iscBase - 0.02, 15); } /** * Calculates the modified ISC value based on the ISC base, whether the scope has changed and the vector string */ function calculateModifiedISC( iscBase: number, scopeChanged: boolean, vector: string ) { if (!scopeChanged) return 6.42 * iscBase; if (util.getVersion(vector) === "3.0") { return 7.52 * (iscBase - 0.029) - 3.25 * Math.pow(iscBase - 0.02, 15); } return ( 7.52 * (iscBase - 0.029) - 3.25 * Math.pow(iscBase * 0.9731 - 0.02, 13) ); } /** * Calculates the exploitability value based on the cvss vector object and whether the scope has changed */ function calculateExploitability( vectorObject: CvssVectorObject, scopeChanged: boolean ) { const avValue = util.findMetricValue<Metric>("AV", vectorObject).numerical; const acValue = util.findMetricValue<Metric>("AC", vectorObject).numerical; const prMetrics = util.findMetricValue<MetricPrivilegesRequired>( "PR", vectorObject ).numerical; const uiValue = util.findMetricValue<Metric>("UI", vectorObject).numerical; const prValue = scopeChanged ? prMetrics.changed : prMetrics.unchanged; return 8.22 * avValue * acValue * prValue * uiValue; } /** * Calculates the ISC modified base value based on the cvss vector object */ function calculateISCModifiedBase(vectorObject: CvssVectorObject) { let mcValue = util.findMetricValue<Metric>("MC", vectorObject); let miValue = util.findMetricValue<Metric>("MI", vectorObject); let maValue = util.findMetricValue<Metric>("MA", vectorObject); const crValue = util.findMetricValue<Metric>("CR", vectorObject).numerical; const irValue = util.findMetricValue<Metric>("IR", vectorObject).numerical; const arValue = util.findMetricValue<Metric>("AR", vectorObject).numerical; if (!mcValue || mcValue.abbr === "X") mcValue = util.findMetricValue("C", vectorObject); if (!miValue || miValue.abbr === "X") miValue = util.findMetricValue("I", vectorObject); if (!maValue || maValue.abbr === "X") maValue = util.findMetricValue("A", vectorObject); return Math.min( 1 - (1 - mcValue.numerical * crValue) * (1 - miValue.numerical * irValue) * (1 - maValue.numerical * arValue), 0.915 ); } function calculateModifiedExploitability( vectorObject: CvssVectorObject, scopeChanged: boolean ) { let mavValue = util.findMetricValue<Metric>("MAV", vectorObject); let macValue = util.findMetricValue<Metric>("MAC", vectorObject); let mprMetrics = util.findMetricValue<MetricPrivilegesRequired>( "MPR", vectorObject ); let muiValue = util.findMetricValue<Metric>("MUI", vectorObject); if (!mavValue || mavValue.abbr === "X") mavValue = util.findMetricValue("AV", vectorObject); if (!macValue || macValue.abbr === "X") macValue = util.findMetricValue("AC", vectorObject); if (!mprMetrics || mprMetrics.abbr === "X") mprMetrics = util.findMetricValue("PR", vectorObject); if (!muiValue || muiValue.abbr === "X") muiValue = util.findMetricValue("UI", vectorObject); const mprValue = scopeChanged ? mprMetrics.numerical.changed : mprMetrics.numerical.unchanged; return ( 8.22 * mavValue.numerical * macValue.numerical * mprValue * muiValue.numerical ); } /** * Chooses the correct way to round numbers depending on the CVSS version number */ function roundUp(num: number, precision: number, vector: string) { if (util.getVersion(vector) === "3.0") { return util.roundUpApprox(num, precision); } return util.roundUpExact(num); } /** * Returns an Impact sub score * * ISCBase = 1 − [(1 − ImpactConf) × (1 − ImpactInteg) × (1 − ImpactAvail)] * * Scope Unchanged 6.42 × ISCBase * Scope Changed 7.52 × [ISCBase − 0.029] − 3.25 × [ISCBase - 0.02]15 */ function getImpactSubScore(vector: string) { const vectorObject = util.getVectorObject(vector); const { S } = vectorObject; const ISCBase = calculateISCBase(vectorObject); return Number(calculateISC(ISCBase, S === "C", vector).toFixed(1)); } /** * Returns an Exploitability sub score * * 8.22 x AttackVector x AttackComplexity x PrivilegeRequired x UserInteraction */ function getExploitabilitySubScore(vector: string) { const vectorObject = util.getVectorObject(vector); const { S } = vectorObject; return Number(calculateExploitability(vectorObject, S === "C").toFixed(1)); } export const score = { getScore, getTemporalScore, getEnvironmentalScore, getImpactSubScore, getExploitabilitySubScore, };