From 157ac8ca99cfe329b6e6722357d7350542ef22f9 Mon Sep 17 00:00:00 2001 From: Christian Studer Date: Mon, 16 Dec 2024 16:42:53 +0100 Subject: [PATCH] add: [vulnerability_lookup] Parsing JVNDB descriptions --- .../modules/expansion/vulnerability_lookup.py | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/misp_modules/modules/expansion/vulnerability_lookup.py b/misp_modules/modules/expansion/vulnerability_lookup.py index e5f40713..c3aee9f5 100644 --- a/misp_modules/modules/expansion/vulnerability_lookup.py +++ b/misp_modules/modules/expansion/vulnerability_lookup.py @@ -46,6 +46,14 @@ class VulnerabilityLookupMapping(VulnerabilityMapping): 'details': 'description', 'modified': 'modified' } + __jvn_mapping = { + 'sec:identifier': 'id', + 'description': 'description', + 'title': 'summary', + 'link': 'references', + 'dcterms:issued': 'published', + 'dcterms:modified': 'modified' + } __nvd_mapping = { 'id': 'id', 'published': 'published', @@ -67,6 +75,7 @@ class VulnerabilityLookupMapping(VulnerabilityMapping): 'cve': '_parse_cve_description', 'ghsa': '_parse_standard_description', 'gsd': '_parse_gsd_description', + 'jvndb': '_parse_jvn_description', 'mal': '_parse_ossf_description', 'pysec': '_parse_standard_description', 'var': '_parse_variot_description' @@ -103,6 +112,10 @@ class VulnerabilityLookupMapping(VulnerabilityMapping): def gsd_mapping(cls) -> dict: return cls.__gsd_mapping + @classmethod + def jvn_mapping(cls) -> dict: + return cls.__jvn_mapping + @classmethod def nvd_mapping(cls) -> dict: return cls.__nvd_mapping @@ -144,7 +157,7 @@ class VulnerabilityLookupParser(VulnerabilityParser): ) getattr(self, feature)(lookup_result) - def _parse_aliases(self, aliases: list) -> Iterator[str]: + def _parse_aliases(self, *aliases: tuple[str]) -> Iterator[str]: for alias in aliases: query = requests.get(f"{api_url}/vulnerability/{alias}") if query.status_code != 200: @@ -266,6 +279,40 @@ class VulnerabilityLookupParser(VulnerabilityParser): return vulnerability_object.uuid + def _parse_jvn_description(self, lookup_result: dict) -> str: + vulnerability = MISPObject('vulnerability') + for field, relation in self.mapping.jvn_mapping().items(): + vulnerability.add_attribute(relation, lookup_result[field]) + for cpe in lookup_result.get('sec:cpe', []): + cpe_value = cpe.get('#text') + if cpe_value is not None: + vulnerability.add_attribute('vulnerable-configuration', cpe_value) + misp_object = self.misp_event.add_object(vulnerability) + for reference in lookup_result.get('sec:references', []): + source = reference.get('@source') + if source is None and reference.get('@id', '').startswith('CWE-'): + title = reference.get('@title') + if title is not None: + weakness = MISPObject('weakness') + weakness.add_attribute('id', reference['@id']) + weakness.add_attribute('description', title) + misp_object.add_reference( + self.misp_event.add_object(weakness).uuid, 'weakened-by' + ) + else: + misp_object.add_reference( + self.misp_event.add_attribute( + type='weakness', value=reference['@id']).uuid, + 'weakened-by' + ) + continue + if source == 'JVN': + misp_object.add_attribute('references', reference['#text']) + elif source == 'CVE': + for referenced_uuid in self._parse_aliases(reference['@id']): + misp_object.add_reference(referenced_uuid, 'related-to') + return misp_object.uuid + def _parse_nvd_related_description(self, nvd_description: dict) -> str: misp_object = MISPObject('vulnerability') for field, relation in self.mapping.nvd_mapping().items(): @@ -306,7 +353,7 @@ class VulnerabilityLookupParser(VulnerabilityParser): ) if lookup_result.get('aliases'): - for vuln_uuid in self._parse_aliases(lookup_result['aliases']): + for vuln_uuid in self._parse_aliases(*lookup_result['aliases']): vulnerability_object.add_reference(vuln_uuid, 'related-to') return vulnerability_object.uuid @@ -328,7 +375,7 @@ class VulnerabilityLookupParser(VulnerabilityParser): vulnerability_object = self.misp_event.add_object(misp_object) if lookup_result.get('aliases'): - for vuln_uuid in self._parse_aliases(lookup_result['aliases']): + for vuln_uuid in self._parse_aliases(*lookup_result['aliases']): vulnerability_object.add_reference(vuln_uuid, 'related-to') return vulnerability_object.uuid