def test_calculate_cvss2_basescore(self): severity = { 'confidentialityImpact': 0, 'integrityImpact': 0.275, 'availabilityImpact': 0, 'accessComplexity': 0.61, 'authentication': 0.704, 'accessVector': 1 } cvss_version = '2' cvss_basescore = cvss.calculate_cvss_basescore( severity, finding_utils.CVSS_PARAMETERS['2'], cvss_version) cvss_basescore_test = Decimal(4.3).quantize(Decimal('0.1')) assert cvss_basescore == cvss_basescore_test
def test_calculate_cvss3_scope_unchanged_basescore(self): severity = { 'confidentialityImpact': 0.22, 'integrityImpact': 0.22, 'availabilityImpact': 0, 'severityScope': 0, 'attackVector': 0.85, 'attackComplexity': 0.77, 'privilegesRequired': 0.62, 'userInteraction': 0.85 } cvss_version = '3.1' cvss_basescore = cvss.calculate_cvss_basescore( severity, finding_utils.CVSS_PARAMETERS['3.1'], cvss_version) cvss_basescore_test = Decimal(5.4).quantize(Decimal('0.1')) assert cvss_basescore == cvss_basescore_test
def test_calculate_cvss2_temporal(self): severity = { 'confidentialityImpact': 0, 'integrityImpact': 0.275, 'availabilityImpact': 0, 'accessComplexity': 0.61, 'authentication': 0.704, 'accessVector': 1, 'exploitability': 0.95, 'resolutionLevel': 0.95, 'confidenceLevel': 0.95 } cvss_version = '2' cvss_basescore = cvss.calculate_cvss_basescore( severity, finding_utils.CVSS_PARAMETERS['2'], cvss_version) cvss_temporal = cvss.calculate_cvss_temporal(severity, cvss_basescore, cvss_version) cvss_temporal_test = Decimal(3.7).quantize(Decimal('0.1')) assert cvss_temporal == cvss_temporal_test
def test_calculate_cvss3_scope_unchanged_temporal(self): severity = { 'confidentialityImpact': 0.22, 'integrityImpact': 0.22, 'availabilityImpact': 0, 'severityScope': 0, 'attackVector': 0.85, 'attackComplexity': 0.77, 'privilegesRequired': 0.62, 'userInteraction': 0.85, 'exploitability': 0.97, 'remediationLevel': 0.97, 'reportConfidence': 1 } cvss_version = '3.1' cvss_basescore = cvss.calculate_cvss_basescore( severity, finding_utils.CVSS_PARAMETERS['3.1'], cvss_version) cvss_temporal = cvss.calculate_cvss_temporal(severity, float(cvss_basescore), cvss_version) cvss_temporal_test = Decimal(5.1).quantize(Decimal('0.1')) assert cvss_temporal == cvss_temporal_test
def format_data(finding: Dict[str, FindingType]) -> Dict[str, FindingType]: finding = { util.snakecase_to_camelcase(attribute): finding.get(attribute) for attribute in finding } is_draft = 'releaseDate' not in finding if is_draft: finding['age'] = 0 finding['cvssVersion'] = finding.get('cvssVersion', '2') else: finding['age'] = util.calculate_datediff_since( cast(datetime, finding['releaseDate'])).days finding['exploitable'] = forms_utils.is_exploitable( float(str(finding.get('exploitability', ''))), str(finding.get('cvssVersion', ''))) == 'Si' historic_verification = cast(List[Dict[str, str]], finding.get('historicVerification', [{}])) finding['remediated'] = \ (historic_verification[-1].get('status') == 'REQUESTED' and not historic_verification[-1].get('vulns', [])) vulns = vuln_dal.get_vulnerabilities(str(finding.get('findingId', ''))) open_vulns = \ [vuln for vuln in vulns if cast(List[Dict[str, str]], vuln.get('historic_state', [{}]))[-1].get( 'state') == 'open'] remediated_vulns = \ [vuln for vuln in open_vulns if cast(List[Dict[str, str]], vuln.get('historic_verification', [{}]))[-1].get( 'status') == 'REQUESTED'] finding['newRemediated'] = len(open_vulns) == len(remediated_vulns) finding['verified'] = len(remediated_vulns) == 0 finding_files = cast(List[Dict[str, str]], finding.get('files')) finding['evidence'] = { 'animation': _get_evidence('animation', finding_files), 'evidence1': _get_evidence('evidence_route_1', finding_files), 'evidence2': _get_evidence('evidence_route_2', finding_files), 'evidence3': _get_evidence('evidence_route_3', finding_files), 'evidence4': _get_evidence('evidence_route_4', finding_files), 'evidence5': _get_evidence('evidence_route_5', finding_files), 'exploitation': _get_evidence('exploitation', finding_files) } finding['compromisedAttrs'] = finding.get('records', '') finding['records'] = _get_evidence('fileRecords', finding_files) finding['exploit'] = _get_evidence('exploit', finding_files) cvss_fields = { '2': ['accessComplexity', 'accessVector', 'authentication', 'availabilityImpact', 'availabilityRequirement', 'collateralDamagePotential', 'confidenceLevel', 'confidentialityImpact', 'confidentialityRequirement', 'exploitability', 'findingDistribution', 'integrityImpact', 'integrityRequirement', 'resolutionLevel'], '3.1': ['attackComplexity', 'attackVector', 'availabilityImpact', 'availabilityRequirement', 'confidentialityImpact', 'confidentialityRequirement', 'exploitability', 'integrityImpact', 'integrityRequirement', 'modifiedAttackComplexity', 'modifiedAttackVector', 'modifiedAvailabilityImpact', 'modifiedConfidentialityImpact', 'modifiedIntegrityImpact', 'modifiedPrivilegesRequired', 'modifiedUserInteraction', 'modifiedSeverityScope', 'privilegesRequired', 'remediationLevel', 'reportConfidence', 'severityScope', 'userInteraction'] } finding['severity'] = { field: cast(str, float(str(finding.get(field, 0)))) for field in cvss_fields[str(finding['cvssVersion'])] } base_score = cvss.calculate_cvss_basescore( cast(Dict[str, float], finding['severity']), CVSS_PARAMETERS[str(finding['cvssVersion'])], str(finding['cvssVersion'])) finding['severityCvss'] = cvss.calculate_cvss_temporal( cast(Dict[str, float], finding['severity']), base_score, str(finding['cvssVersion'])) return finding
def save_severity(finding: Dict[str, FindingType]) -> bool: """Organize severity metrics to save in dynamo.""" cvss_version: str = str(finding.get('cvssVersion', '')) cvss_parameters = finding_utils.CVSS_PARAMETERS[cvss_version] if cvss_version == '3.1': severity_fields = [ 'attackVector', 'attackComplexity', 'privilegesRequired', 'userInteraction', 'severityScope', 'confidentialityImpact', 'integrityImpact', 'availabilityImpact', 'exploitability', 'remediationLevel', 'reportConfidence', 'confidentialityRequirement', 'integrityRequirement', 'availabilityRequirement', 'modifiedAttackVector', 'modifiedAttackComplexity', 'modifiedPrivilegesRequired', 'modifiedUserInteraction', 'modifiedSeverityScope', 'modifiedConfidentialityImpact', 'modifiedIntegrityImpact', 'modifiedAvailabilityImpact' ] severity: Dict[str, FindingType] = \ {util.camelcase_to_snakecase(k): Decimal(str(finding.get(k))) for k in severity_fields} unformatted_severity = { k: float(str(finding.get(k))) for k in severity_fields } privileges = cvss.calculate_privileges( unformatted_severity['privilegesRequired'], unformatted_severity['severityScope']) unformatted_severity['privilegesRequired'] = privileges severity['privileges_required'] = \ Decimal(privileges).quantize(Decimal('0.01')) modified_priviles = cvss.calculate_privileges( unformatted_severity['modifiedPrivilegesRequired'], unformatted_severity['modifiedSeverityScope']) unformatted_severity['modifiedPrivilegesRequired'] = modified_priviles severity['modified_privileges_required'] = \ Decimal(modified_priviles).quantize(Decimal('0.01')) else: severity_fields = [ 'accessVector', 'accessComplexity', 'authentication', 'exploitability', 'confidentialityImpact', 'integrityImpact', 'availabilityImpact', 'resolutionLevel', 'confidenceLevel', 'collateralDamagePotential', 'findingDistribution', 'confidentialityRequirement', 'integrityRequirement', 'availabilityRequirement' ] severity = { util.camelcase_to_snakecase(k): Decimal(str(finding.get(k))) for k in severity_fields } unformatted_severity = { k: float(str(finding.get(k))) for k in severity_fields } severity['cvss_basescore'] = cvss.calculate_cvss_basescore( unformatted_severity, cvss_parameters, cvss_version) severity['cvss_temporal'] = cvss.calculate_cvss_temporal( unformatted_severity, float(cast(Decimal, severity['cvss_basescore'])), cvss_version) severity['cvss_env'] = cvss.calculate_cvss_environment( unformatted_severity, cvss_parameters, cvss_version) severity['cvss_version'] = cvss_version response = finding_dal.update(str(finding.get('id', '')), severity) return response