def test_serialize_all_values(self): reference_date = datetime.now() schema = VulnerabilitySchema() vuln = Vulnerability(id="1234", title="Multiple XSS", reported_type="XSS", created_at=reference_date, updated_at=reference_date + timedelta(days=6)) vuln.add_affected_version(VersionRange(fixed_in="1.3")) vuln.add_unaffected_version(VersionRange(fixed_in="2.4")) vuln.references.append( Reference(type="other", url="http://example.com/test")) data = serialize(schema, vuln, indent=None)[0] self.assertIn(reference_date.strftime("%Y-%m-%d"), data) self.assertIn( (reference_date + timedelta(days=6)).strftime("%Y-%m-%d"), data) self.assertIn('"reported_type": "XSS"', data) self.assertIn('1.3', data) self.assertIn('example.com', data) out, errors = schema.loads(data) self.assertEqual("1.3", out.affected_versions[0].fixed_in) self.assertEqual("2.4", out.unaffected_versions[0].fixed_in) self.assertEqual("other", out.references[0].type)
def test_list_vulnerabilities_return_vulnerabilities_with_introduced_in_lower_than_version_and_fixed_in_upper_than_version( self): vuln0 = Vulnerability(id="12345", title="Vulnerability0", affected_versions=[ VersionRange(introduced_in="2.5.9", fixed_in="4.7.2") ]) vuln1 = Vulnerability(id="23456", title="Vulnerability1", affected_versions=[ VersionRange(introduced_in="1.6.2", fixed_in="4.9") ]) vuln_list = VulnerabilityList(key="wordpress", producer="producer", vulnerabilities=[vuln0, vuln1]) applicable_vuln0 = self.vulnerability_lister.list_vulnerabilities( "4.7", vuln_list) applicable_vuln1 = self.vulnerability_lister.list_vulnerabilities( "3.5.8", vuln_list) applicable_vuln2 = self.vulnerability_lister.list_vulnerabilities( "2.4.8", vuln_list) self.assertIn(vuln0, applicable_vuln0) self.assertIn(vuln1, applicable_vuln0) self.assertIn(vuln0, applicable_vuln1) self.assertIn(vuln1, applicable_vuln1) self.assertNotIn(vuln0, applicable_vuln2) self.assertIn(vuln1, applicable_vuln2)
def test_multiple_ranges(self): v = Vulnerability(id="1") v.add_affected_version(VersionRange(fixed_in="1.2")) v.add_affected_version(VersionRange(fixed_in="1.3")) self.assertEqual(v.affected_versions, [ VersionRange(fixed_in="1.2"), VersionRange(fixed_in="1.3"), ])
def test_multiple_ranges(self): v = Vulnerability(id="1") v.add_affected_version( VersionRange(introduced_in="1.0", fixed_in="1.2")) v.add_affected_version( VersionRange(introduced_in="2.0", fixed_in="2.3")) v.add_affected_version( VersionRange(introduced_in="3.0", fixed_in="3.1")) self.assertFalse(v.applies_to("0.9")) self.assertTrue(v.applies_to("2.1")) self.assertTrue(v.applies_to("3.0")) self.assertFalse(v.applies_to("3.1"))
def test_vulnerability_introduced_in_only(self): v = Vulnerability(id="1") v.add_affected_version(VersionRange(introduced_in="2.0")) self.assertFalse(v.applies_to("1.0")) self.assertFalse(v.applies_to("1.9")) self.assertFalse(v.applies_to("2.0-beta3")) self.assertTrue(v.applies_to("2.0")) self.assertTrue(v.applies_to("2.1"))
def test_list_vulnerabilities_return_all_vulnerabilities_if_version_is_none_and_no_version_match_all_is_true( self): vuln0 = Vulnerability( id="12345", title="Vulnerability0", affected_versions=[VersionRange(introduced_in="2.3.4")]) vuln1 = Vulnerability( id="23456", title="Vulnerability1", affected_versions=[VersionRange(introduced_in="1.5.6")]) vuln_list = VulnerabilityList(key="wordpress", producer="producer", vulnerabilities=[vuln0, vuln1]) applicable_vuln = self.vulnerability_lister.list_vulnerabilities( None, vuln_list, no_version_match_all=True) self.assertEqual(len(applicable_vuln), 2)
def test_affected_version(self): schema = VersionRangeSchema() ver = VersionRange(introduced_in="1.2.3", fixed_in="1.3.4") self.assertEqual('{"introduced_in": "1.2.3", "fixed_in": "1.3.4"}', serialize(schema, ver, indent=None)[0]) ver = VersionRange(introduced_in="1.2.3") self.assertEqual('{"introduced_in": "1.2.3"}', serialize(schema, ver, indent=None)[0]) ver = VersionRange(fixed_in="1.2.3") self.assertEqual('{"fixed_in": "1.2.3"}', serialize(schema, ver, indent=None)[0]) ver = VersionRange() self.assertEqual( {'_schema': [ "Either introduced_in or fixed_in is required.", ]}, schema.loads(serialize(schema, ver)[0])[1])
def test_list_vulnerabilities_remove_affected_versions_ranges_not_including_target_version( self): vuln = Vulnerability(id="12345", title="Vulnerability", affected_versions=[ VersionRange(introduced_in="3.7", fixed_in="3.7.5"), VersionRange(introduced_in="4.0", fixed_in="4.0.10"), VersionRange(introduced_in="4.5", fixed_in="4.5.2") ]) vuln_list = VulnerabilityList(key="wordpress", producer="producer", vulnerabilities=[vuln]) vuln_software0 = self.vulnerability_lister.list_vulnerabilities( "3.7.3", vuln_list) vuln_software1 = self.vulnerability_lister.list_vulnerabilities( "4.0.9", vuln_list) vuln_software2 = self.vulnerability_lister.list_vulnerabilities( "4.5", vuln_list) self.assertEqual(vuln_software0[0].affected_versions, [VersionRange(introduced_in="3.7", fixed_in="3.7.5")]) self.assertEqual( vuln_software1[0].affected_versions, [VersionRange(introduced_in="4.0", fixed_in="4.0.10")]) self.assertEqual(vuln_software2[0].affected_versions, [VersionRange(introduced_in="4.5", fixed_in="4.5.2")])
def test_list_vulnerabilities_return_empty_list_if_no_vuln_applicable_to_version( self): vuln0 = Vulnerability(id="12345", title="Vulnerability0", affected_versions=[ VersionRange(introduced_in="4.4", fixed_in="4.6") ]) vuln1 = Vulnerability(id="23456", title="Vulnerability1", affected_versions=[VersionRange(fixed_in="3.9")]) vuln_list = VulnerabilityList(key="wordpress", producer="producer", vulnerabilities=[vuln0, vuln1]) applicable_vuln0 = self.vulnerability_lister.list_vulnerabilities( "4.7", vuln_list) applicable_vuln1 = self.vulnerability_lister.list_vulnerabilities( "4.3", vuln_list) self.assertEqual(len(applicable_vuln0), 0) self.assertEqual(len(applicable_vuln1), 0)
def test_list_vulnerabilities_apply_vulnerabilities_with_multiple_affected_versions( self): vuln = Vulnerability(id="12345", title="Vulnerability", affected_versions=[ VersionRange(introduced_in="3.7", fixed_in="3.7.5"), VersionRange(introduced_in="4.0", fixed_in="4.0.10"), VersionRange(introduced_in="4.5", fixed_in="4.5.2") ]) vuln_list = VulnerabilityList(key="wordpress", producer="producer", vulnerabilities=[vuln]) vuln_software0 = self.vulnerability_lister.list_vulnerabilities( "4.1.5", vuln_list) vuln_software1 = self.vulnerability_lister.list_vulnerabilities( "4.0.9", vuln_list) self.assertEqual(vuln_software0, []) self.assertEqual(vuln_software1[0].id, vuln.id)
def test_added_fix_conflicts_with_known_information(self): v = Vulnerability(id="1") v.add_affected_version(VersionRange(fixed_in="1.5")) v.add_affected_version( VersionRange(introduced_in="2.0", fixed_in="2.5")) v.add_affected_version(VersionRange(fixed_in="1.3")) v.add_affected_version(VersionRange(fixed_in="2.3")) v.add_affected_version(VersionRange(introduced_in="2.3")) self.assertEqual(v.affected_versions, [ VersionRange(fixed_in="1.5"), VersionRange(introduced_in="2.0", fixed_in="2.5"), ])
def apply_data(self, vuln, entry, allow_override=False): def apply_value(field, value): if allow_override or getattr(vuln, field) is None: setattr(vuln, field, value) # todo if title is not none check if title from securityfocus is better instead of doing blind override. if vuln.title is None or allow_override: if vuln.title != entry['info_parser'].get_title(): vuln.title = entry['info_parser'].get_title() if entry['info_parser'].get_vuln_class() is not None: if vuln.reported_type is None or vuln.reported_type.lower( ) == "unknown": vuln.reported_type = entry['info_parser'].get_vuln_class() if vuln.cvss is None and len( entry["info_parser"].get_cve_id()) == 0: vuln.cvss = self.cvss_mapper.get_cvss_from_vulnerability_type( entry['info_parser'].get_vuln_class()) if vuln.created_at is not None: if vuln.created_at.replace( tzinfo=None) != entry['info_parser'].get_publication_date( ): apply_value('created_at', entry['info_parser'].get_publication_date()) else: apply_value('created_at', entry['info_parser'].get_publication_date()) fixed_in = self._get_fixed_in(entry) if fixed_in is not None: version_range = VersionRange(fixed_in=fixed_in) if version_range not in vuln.affected_versions: vuln.add_affected_version(version_range) ref_manager = self.reference_manager.for_list(vuln.references) self._add_bugtraqid_reference(ref_manager, entry["id"]) for cve in entry['info_parser'].get_cve_id(): ref_manager.include_normalized( "cve", cve[4:] ) # Remove the "CVE-" at the beginning of the cve id string useful_references = self._remove_useless_references( entry['references_parser'].get_references()) for reference in useful_references: ref_manager.include_url(reference["url"]) if vuln.dirty: apply_value('updated_at', self._get_last_modified(entry))
def test_unaffected_versions(self): v = Vulnerability(id="1") v.unaffected_versions = [ VersionRange(introduced_in="6.0", fixed_in="6.1.2"), VersionRange(introduced_in="7.0", fixed_in="7.0.7"), ] v.add_affected_version(VersionRange(fixed_in="1.5")) v.add_affected_version( VersionRange(introduced_in="6.0", fixed_in="6.1.2")) v.add_affected_version(VersionRange(fixed_in="6.1.1")) self.assertEqual(v.affected_versions, [ VersionRange(fixed_in="1.5"), ])
def test_list_vulnerabilities_return_all_vulnerabilities_with_no_introduced_nor_fixed_in( self): vuln0 = Vulnerability(id="12345", title="Vulnerability0") vuln1 = Vulnerability(id="23456", title="Vulnerability1", affected_versions=[VersionRange()]) vuln_list = VulnerabilityList(key="wordpress", producer="producer", vulnerabilities=[vuln0, vuln1]) applicable_vuln0 = self.vulnerability_lister.list_vulnerabilities( "4.7", vuln_list) applicable_vuln1 = self.vulnerability_lister.list_vulnerabilities( "0.1", vuln_list) applicable_vuln2 = self.vulnerability_lister.list_vulnerabilities( "100.2.3", vuln_list) self.assertIn(vuln0, applicable_vuln0) self.assertIn(vuln1, applicable_vuln0) self.assertIn(vuln0, applicable_vuln1) self.assertIn(vuln1, applicable_vuln1) self.assertIn(vuln0, applicable_vuln2) self.assertIn(vuln1, applicable_vuln2)
def test_vulnerability_fixed_in_only(self): v = Vulnerability(id="1") v.add_affected_version(VersionRange(fixed_in="1.0")) self.assertFalse(v.applies_to("1.1")) self.assertFalse(v.applies_to("1.0")) self.assertTrue(v.applies_to("0.9"))