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 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 test_create_change(open_file): task = Task() db.session.add(task) db.session.commit() cve_json = open_file("cves/CVE-2020-26116.json") cve = CveUtil.create_cve(cve_json) change = CveUtil.create_change(cve, cve_json, task, []) assert Change.query.first().id == change.id assert change.json == cve_json assert change.cve_id == cve.id assert change.cve.id == cve.id assert change.task_id == task.id assert change.task.id == task.id assert change.events == []
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_cve(app, open_file): cve = CveUtil.create_cve(open_file("cves/CVE-2020-26116.json")) cves = Cve.query.all() assert len(cves) == 1 # The CVE has been created assert cve.id == cves[0].id assert cve.cve_id == "CVE-2020-26116" assert cve.cwes == ["CWE-116"] assert sorted(cve.vendors) == sorted( [ "fedoraproject", f"fedoraproject{PRODUCT_SEPARATOR}fedora", "python", f"python{PRODUCT_SEPARATOR}python", ] ) assert ( cve.summary == "http.client in Python 3.x before 3.5.10, 3.6.x before 3.6.12, 3.7.x before 3.7.9, and 3.8.x before 3.8.5 allows CRLF injection if the attacker controls the HTTP request method, as demonstrated by inserting CR and LF control characters in the first argument of HTTPConnection.request." ) assert cve.cvss2 == 6.4 assert cve.cvss3 == 7.2 assert cve.events == [] assert cve.changes == [] assert cve.alerts == [] assert round(cve.cvss_weight, 1) == 13.6 # The CWE has been created cwes = Cwe.query.all() assert len(cwes) == 1 cwe = cwes[0] assert cwe.cwe_id == "CWE-116" # The vendors and products has been created vendors = Vendor.query.all() assert len(vendors) == 2 vendor_1 = Vendor.query.filter_by(name="fedoraproject").first() assert len(vendor_1.products) == 1 assert vendor_1.products[0].name == "fedora" vendor_2 = Vendor.query.filter_by(name="python").first() assert len(vendor_2.products) == 1 assert vendor_2.products[0].name == "python"
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_cve(cve_id): CveUtil.create_cve(open_file(f"cves/{cve_id}.json")) return Cve.query.filter_by(cve_id=cve_id).first()
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, {})