def execute(self): # Some CVE does not have CVSS, or they just have one version # Check the old values old = {} if self.cve_obj.cvss2: old["v2"] = self.cve_obj.cvss2 if self.cve_obj.cvss3: old["v3"] = self.cve_obj.cvss3 # Check the new values new = {} if "baseMetricV2" in self.cve_json["impact"]: new["v2"] = self.cve_json["impact"]["baseMetricV2"]["cvssV2"][ "baseScore"] if "baseMetricV3" in self.cve_json["impact"]: new["v3"] = self.cve_json["impact"]["baseMetricV3"]["cvssV3"][ "baseScore"] # If at least one version has changed, update the CVE if old != new: self.cve_obj.cvss2 = new.get("v2") self.cve_obj.cvss3 = new.get("v3") db.session.commit() # Create the event with the CVSS changes event = CveUtil.create_event(self.cve_obj, self.cve_json, "cvss", { "old": old, "new": new }) return event return None
def check_for_update(cve_json, task): cve_id = cve_json["cve"]["CVE_data_meta"]["ID"] cve_obj = Cve.query.filter_by(cve_id=cve_id).first() events = [] # A new CVE has been added if not cve_obj: cve_obj = CveUtil.create_cve(cve_json) logger.info("{} created (ID: {})".format(cve_id, cve_obj.id)) events = [CveUtil.create_event(cve_obj, cve_json, "new_cve", {})] # Existing CVE has changed elif CveUtil.cve_has_changed(cve_obj, cve_json): logger.info("{} has changed, parsing it...".format(cve_obj.cve_id)) events = [] checks = BaseCheck.__subclasses__() # Loop on each kind of check for check in checks: c = check(cve_obj, cve_json) event = c.execute() if event: events.append(event) # Change the last updated date cve_obj.updated_at = arrow.get(cve_json["lastModifiedDate"]).datetime cve_obj.json = cve_json db.session.commit() # Create the change if events: CveUtil.create_change(cve_obj, cve_json, task, events)
def test_filter_events_first_time(create_user, create_cve, create_vendor, open_file): cve = create_cve("CVE-2018-18074") event = CveUtil.create_event( cve, open_file(f"modified_cves/CVE-2018-18074_first_time_1.json")[0], "first_time", ["opencveio", "opencveio$PRODUCT$opencveio"], ) # User1 doesn't have the first_time type user1 = create_user("user1") user1.filters_notifications = {"cvss": 0, "event_types": ["summary"]} db.session.commit() assert filter_events(user1, [event]) == [] # User2 hasn't subscribed to opencve vendor user2 = create_user("user2") vendor = create_vendor("not_existing") user2.vendors.append(vendor) db.session.commit() assert filter_events(user2, [event]) == [] # User3 has subscribed to opencve vendor user3 = create_user("user3") vendor = create_vendor("opencveio") user3.vendors.append(vendor) db.session.commit() assert filter_events(user3, [event]) == [event]
def execute(self): old = flatten_vendors(convert_cpes( self.cve_obj.json["configurations"])) new = flatten_vendors(convert_cpes(self.cve_json["configurations"])) payload = list(set(new) - set(old)) if payload: event = CveUtil.create_event(self.cve_obj, self.cve_json, "first_time", payload) return event return None
def test_create_event(app, open_file): cve_json = open_file("cves/CVE-2020-26116.json") cve = CveUtil.create_cve(cve_json) event = CveUtil.create_event(cve, cve_json, "new_cve", {"foo": "bar"}) assert Event.query.first().id == event.id assert event.type == "new_cve" assert event.details == {"foo": "bar"} assert event.review == False assert event.cve_id == cve.id assert event.cve.id == cve.id assert event.change == None assert event.change_id == None assert event.alerts == []
def execute(self): payload = {"changed": [], "added": [], "removed": []} # List the old and new references then make the diff between them old_refs = { ref["url"]: ref for ref in self.cve_obj.json["cve"]["references"]["reference_data"] } new_refs = { ref["url"]: ref for ref in self.cve_json["cve"]["references"]["reference_data"] } diff = DeepDiff(old_refs, new_refs) # New references payload["added"] = [ new_refs[r[6:-2]] for r in diff.get("dictionary_item_added", []) ] # Removed references payload["removed"] = [ old_refs[r[6:-2]] for r in diff.get("dictionary_item_removed", []) ] # Changed references (the following code parses the DeepDiff result # and extracts the urls of modified references) modified_urls = list( set([ r.split("'")[1] for r in list(diff.get("values_changed", {}).keys()) + list(diff.get("iterable_item_added", {}).keys()) ])) payload["changed"] = [{ "old": old_refs[url], "new": new_refs[url] } for url in modified_urls] # Create the event with the references changes if payload["changed"] or payload["added"] or payload["removed"]: event = CveUtil.create_event(self.cve_obj, self.cve_json, "references", payload) return event return None
def execute(self): old = nested_lookup("cpe23Uri", self.cve_obj.json["configurations"]) new = nested_lookup("cpe23Uri", self.cve_json["configurations"]) payload = { "added": list(set(new) - set(old)), "removed": list(set(old) - set(new)), } # The CPEs list has been modified if payload["added"] or payload["removed"]: # Change the CVE's vendors attribute self.cve_obj.vendors = flatten_vendors( convert_cpes(self.cve_json["configurations"]) ) db.session.commit() # Create the vendors and products objects if they don't exist vendors_products = convert_cpes(payload["added"]) for vendor, products in vendors_products.items(): v_obj = Vendor.query.filter_by(name=vendor).first() # Create the vendor and associate it to the CVE if not v_obj: v_obj = Vendor(name=vendor) db.session.add(v_obj) db.session.commit() # Do the same for its products for product in products: p_obj = Product.query.filter_by(name=product, vendor=v_obj).first() if not p_obj: p_obj = Product(name=product, vendor=v_obj) db.session.add(p_obj) db.session.commit() # Create the event event = CveUtil.create_event(self.cve_obj, self.cve_json, "cpes", payload) return event return None
def execute(self): old = self.cve_obj.cwes new = [ c["value"] for c in self.cve_json["cve"]["problemtype"] ["problemtype_data"][0]["description"] ] payload = { "added": list(set(new) - set(old)), "removed": list(set(old) - set(new)), } # It's possible that a CVE links a CWE not yet defined in database. # In this case we'll save it in the `cwes` table and a periodic task # will populate later its name and description using the MITRE file. for cwe_id in payload["added"]: cwe = Cwe.query.filter_by(cwe_id=cwe_id).first() if not cwe: info( f"{cwe_id} detected in {self.cve_obj.cve_id} but not existing in database, adding it..." ) cwe = Cwe(cwe_id=cwe_id) db.session.add(cwe) db.session.commit() # If the list of CWE changed if payload["added"] or payload["removed"]: # Save the new list self.cve_obj.cwes = new db.session.commit() # Create the event event = CveUtil.create_event(self.cve_obj, self.cve_json, "cwes", payload) return event return None
def execute(self): summary = self.cve_json["cve"]["description"]["description_data"][0][ "value"] # Check if the summary has changed if self.cve_obj.summary != summary: # Replace it in the CVE old = self.cve_obj.summary self.cve_obj.summary = summary db.session.commit() # Create a 'summary' event event = CveUtil.create_event( self.cve_obj, self.cve_json, "summary", { "old": old, "new": self.cve_obj.summary }, ) return event return None
def create_events(cve): for t in ["summary", "cpes", "cwes", "cvss", "references"]: CveUtil.create_event( cve, open_file(f"modified_cves/CVE-2018-18074_{t}.json")[0], t, {})