def edit_threat(self, vuln_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse("error: unable to get the organization", safe=False, status=500) threat = get_object_or_404(OrgThreatMetadata, id=self.data['id']) threat.link = self.data['link'] threat.is_in_the_wild = self.data['is_in_the_wild'] threat.is_in_the_news = self.data['is_in_the_news'] threat.trust_level = self.data['trust_level'] threat.tlp_level = self.data['tlp_level'] threat.source = self.data['source'] threat.maturity = self.data['maturity'] threat.notes = self.data['notes'] threat.modified = self.data['modified'] threat.save() # Update vuln score vuln.update_score() vuln.save() return JsonResponse(model_to_dict(threat), safe=False)
def calc_vprating_by_vulnid(self, vuln_id): asset_metadata = {} if self.method == 'POST': asset_metadata.update({ 'exposure': self.data.get('exposure', None), 'criticality': self.data.get('criticality', None), 'distribution': self.data.get('distribution', None) }) vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse("error: unable to get the organization", safe=False, status=500) vpr = _calc_vprating(vuln=vuln, asset_metadata=asset_metadata, org=org) if vpr is not None: return JsonResponse(model_to_dict(vpr)) else: return JsonResponse({'error': 'unable to refresh vprating'})
def add_exploit(self, vuln_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse("Error: unable to get the organization", safe=False, status=500) data = { 'vuln': vuln, 'link': self.data['link'], 'trust_level': self.data['trust_level'], 'tlp_level': self.data['tlp_level'], 'source': self.data['source'], 'availability': self.data['availability'], 'maturity': self.data['maturity'], 'modified': self.data['modified'], 'notes': self.data['notes'], 'organization': org } new_exploit = OrgExploitMetadata(**data) new_exploit.save() # vuln.update_score(org=org) vuln.update_score() vuln.save() return JsonResponse(model_to_dict(new_exploit), safe=False)
def get_alerts_misp_enabled(self, instance): org_id = self.context.get('request').session.get('org_id', None) if org_id is None: return {} org = organization.get_current_organization(user=instance, org_id=org_id) return org.org_settings.alerts_misp_enabled
def add_threat(self, vuln_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse("error: unable to get the organization", safe=False, status=500) data = { 'vuln': vuln, 'link': self.data['link'], 'trust_level': self.data['trust_level'], 'tlp_level': self.data['tlp_level'], 'source': self.data['source'], 'is_in_the_wild': self.data['is_in_the_wild'], 'is_in_the_news': self.data['is_in_the_news'], 'modified': self.data['modified'], 'notes': self.data['notes'], 'organization': org } new_threat = OrgThreatMetadata(**data) new_threat.save() # Update vuln score vuln.update_score() vuln.save() return JsonResponse(model_to_dict(new_threat), safe=False)
def get_exploits(self, vuln_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse( { "status": "error", "reason": "Unable to get the organization" }, safe=False, status=500) res = [] # Get public exploits for exploit in vuln.exploitmetadata_set.all(): e = model_to_dict(exploit) e['scope'] = 'public' e['relevancy_level'] = exploit.get_relevancy_level() res.append(e) # Get org exploits for exploit in vuln.orgexploitmetadata_set.filter(organization=org): e = model_to_dict(exploit) e['scope'] = 'private' e['relevancy_level'] = exploit.get_relevancy_level() res.append(e) return JsonResponse(res, safe=False)
def edit_exploit(self, vuln_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse("error: unable to get the organization", safe=False, status=500) exploit = get_object_or_404(OrgExploitMetadata, id=self.data['id']) exploit.link = self.data['link'] exploit.trust_level = self.data['trust_level'] exploit.tlp_level = self.data['tlp_level'] exploit.source = self.data['source'] exploit.availability = self.data['availability'] exploit.maturity = self.data['maturity'] exploit.notes = self.data['notes'] exploit.modified = self.data['modified'] exploit.save() # Update vuln score vuln.update_score(org=org) vuln.save(org=org) return JsonResponse(model_to_dict(exploit), safe=False)
def get_queryset(self): org_id = self.request.session.get('org_id', None) org = organization.get_current_organization(user=self.request.user, org_id=org_id) monitored_vulns = [] if org is not None: monitored_vulns = list( org.org_monitoring_list.vulns.all().values_list('id', flat=True)) qs = Vuln.objects.all().prefetch_related( 'exploitmetadata_set', 'orgexploitmetadata_set', 'products', 'products__vendor', 'cwe' ).annotate( exploit_count=F( 'id'), # default value: will be adjusted by the VulnSerializer monitored=Case(When(id__in=monitored_vulns, then=True), default=False, output_field=BooleanField()), org=Value( org_id, output_field=CharField())).order_by('-updated_at').distinct() # if self.request.method == 'GET' and 'fields' in self.request.GET: # for f in self.request.GET.get('fields').split(','): # qs = qs.only(f) return qs
def export_vuln_json(self, vuln_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse( { "status": "error", "reason": "Unable to get the organization" }, safe=False, status=500) # Set default values vuln.org = self.session.get('org_id', None) vuln.monitored = False vuln.exploit_count = 1 vuln_json = VulnSerializer(vuln, context={'request': self}).data exploits_json = ExploitMetadataSerializer(vuln.exploitmetadata_set.all(), many=True, context={ 'request': self }).data orgexploits_json = OrgExploitMetadataSerializer( vuln.orgexploitmetadata_set.filter(organization=org), many=True, context={ 'request': self }).data threats_json = ThreatMetadataSerializer(vuln.threatmetadata_set.all(), many=True, context={ 'request': self }).data orgthreats_json = OrgThreatMetadataSerializer( vuln.orgthreatmetadata_set.filter(organization=org), many=True, context={ 'request': self }).data res_json = { "vulnerability": vuln_json, "exploits": exploits_json, "org_exploits": orgexploits_json, "threats": threats_json, "org_threats": orgthreats_json, } response = HttpResponse(json.dumps(res_json, sort_keys=True, indent=4, default=_json_serial), content_type='application/json') response[ 'Content-Disposition'] = 'attachment; filename=hears_vuln_{}.json'.format( vuln.id) return response
def get_enable_email_alert_update_vuln(self, instance): org_id = self.context.get('request').session.get('org_id', None) if org_id is None: return {} org = organization.get_current_organization(user=instance, org_id=org_id) return org.org_settings.enable_email_alert_update_vuln
def get_vuln_history(self, vuln_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse( { "status": "error", "reason": "unable to get the organization" }, safe=False, status=500) res = {} res.update(get_history_diffs(vuln, 'vuln')) for exploit in vuln.exploitmetadata_set.all(): res.update(get_history_diffs(exploit, 'exploit')) for exploit in vuln.orgexploitmetadata_set.filter(organization=org): res.update(get_history_diffs(exploit, 'exploit')) for threat in vuln.threatmetadata_set.all(): res.update(get_history_diffs(threat, 'threat')) for threat in vuln.orgthreatmetadata_set.filter(organization=org): res.update(get_history_diffs(threat, 'threat')) history = [] for h in sorted(res.keys()): history.append(res[h]) return JsonResponse(history, safe=False)
def get_monitored_products_report_by_days(self, days): org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) sendmail = False if self.GET.get('sendmail', False) and self.GET.get('sendmail') == 'yes': sendmail = True body = _get_monitored_products_report(org, days, sendmail) return render(self, 'products_report.html', body)
def get_queryset(self): org_id = self.request.session.get('org_id', None) org = organization.get_current_organization(user=self.request.user, org_id=org_id) if org is None: return None return OrgThreatMetadata.objects.prefetch_related('vuln').annotate( vp=F('vuln__vulnerable_products')).filter( organization=org).order_by('-updated_at')
def get_current_org(self, instance): org_id = self.context.get('request').session.get('org_id', None) if org_id is None: return {} org = organization.get_current_organization(user=instance, org_id=org_id) if org is not None: return {'org_id': org.id, 'org_name': org.name} else: return {'org_id': None, 'org_name': '-'}
def del_exploit(self, vuln_id, exploit_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse("error: unable to get the organization", safe=False, status=500) exploit = org.org_exploits.filter(id=exploit_id) if len(exploit) > 0: exploit.delete() vuln.update_score() vuln.save() return JsonResponse("deleted", safe=False) else: return JsonResponse("unknown", safe=False)
def get_vuln_stats(self): org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) monitored_vendors = Vendor.objects.filter( id__in=org.org_monitoring_list.vendors.all()) monitored_products = Product.objects.filter( id__in=org.org_monitoring_list.products.all()) monitored_vulns = Vuln.objects.filter( id__in=org.org_monitoring_list.vulns.all()) res = { 'vulns': Vuln.objects.count(), 'vulns_exploitable': Vuln.objects.filter(is_exploitable=True).count(), 'exploits': ExploitMetadata.objects.count(), 'threats': ThreatMetadata.objects.count(), 'monitored': monitored_products.count() + monitored_vulns.count(), 'monitored_vendors': monitored_vendors.count(), 'monitored_products': monitored_products.count(), 'monitored_vulns': monitored_vulns.count(), } return JsonResponse(res, safe=False)
def del_threat(self, vuln_id, threat_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse( { "status": "error", "reason": "unable to get the organization" }, safe=False, status=500) threat = org.org_threats.filter(id=threat_id) threat.delete() # Update vuln score vuln.update_score() vuln.save() return JsonResponse("deleted", safe=False)
def get_threats(self, vuln_id): vuln = get_object_or_404(Vuln, id=vuln_id) try: org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) except Exception: return JsonResponse("error: unable to get the organization", safe=False, status=500) res = [] # Get public threat for threat in vuln.threatmetadata_set.all(): t = model_to_dict(threat) t['scope'] = 'public' res.append(t) # Get org threat for threat in vuln.orgthreatmetadata_set.filter(organization=org): t = model_to_dict(threat) t['scope'] = 'private' res.append(t) return JsonResponse(res, safe=False)
def toggle_monitor_vuln(self, vuln_id): if set(['vuln_id', 'monitored', 'organization_id']).issubset( self.data.keys()) is False: return JsonResponse("error.", safe=False, status=500) vuln = get_object_or_404(Vuln, id=self.data['vuln_id']) if vuln is None or vuln_id != str(self.data['vuln_id']): return JsonResponse("error.", safe=False, status=500) else: organization_id = self.data['organization_id'] org = organization.get_current_organization(user=self.user, org_id=organization_id) if self.data[ 'monitored'] is True and vuln not in org.org_monitoring_list.vulns.all( ): org.org_monitoring_list.vulns.add(vuln) if self.data[ 'monitored'] is False and vuln in org.org_monitoring_list.vulns.all( ): org.org_monitoring_list.vulns.remove(vuln) vuln.save() return JsonResponse("toggled.", safe=False)
def add_vuln(self): res = {"status": "success", "reason": "vulnerability successfully created"} # print(self.data) cve_data = { "cve_id": self.data['cve_id'], "summary": self.data.get('summary', 'n/a'), "published": self.data.get('published', datetime.today()), "modified": self.data.get('modified', datetime.today()), "cwe": CWE.objects.filter(cwe_id=self.data.get('cwe', '')).first(), "cvss_time": self.data.get('cvss_time', datetime.today()), "cvss_vector": self.data.get('cvss2_vector', ''), "access": { "authentication": self.data.get('access_authentication', ''), "complexity": self.data.get('access_complexity', ''), "vector": self.data.get('access_vector', ''), }, "impact": { "confidentiality": self.data.get('impact_confidentiality', ''), "integrity": self.data.get('impact_integrity', ''), "availability": self.data.get('impact_availability', ''), }, "references": { "others": [] }, "assigner": self.user.username, "vulnerable_products": [] } if CVE.objects.filter(cve_id=cve_data["cve_id"]).count() > 0: res = {"status": "error", "reason": "CVE already known."} # print(res) return JsonResponse(res, safe=False) # Check CVSS cvss2_data = self.data.get('cvss2', None) cvss2 = 0.0 try: if cvss2_data is not None and cvss2_data != '': cvss2 = float(cvss2_data) except Exception: pass cve_data.update({"cvss": cvss2}) # Sanitize if type(cve_data['published']) != datetime: cve_data['published'] = datetime.today() if 'references' in self.data.keys() and len(self.data['references']) > 0: cve_data["references"]["others"] = [ r.strip() for r in self.data['references'].replace('\n', ',').split(',') ] # Create a CVE cve = CVE(**cve_data) try: cve.full_clean() cve.save() except Exception: res = {"status": "error", "reason": "Unable to create CVE in DB"} return JsonResponse(res, safe=False) # Manage CPEs and related products vulnerable_products = [] # Array products = [] # List of Product productversions = [] # List of ProductVersion # -> Loop over products if 'products' in self.data.keys() and len(self.data['products']) > 0: for pid in self.data['products']: p = Product.objects.filter(id=pid).first() if p is not None and p not in products: products.append(p) # Loop over CPEs if 'cpes' in self.data.keys() and len(self.data['cpes']) > 0: cpes = [ c.strip() for c in self.data['cpes'].replace('\n', ',').split(',') ] my_cpes = list(CPE.objects.values_list('vector', flat=True)) for cpe in cpes: if cpe == '': continue try: c = _CPE(cpe) vendor, is_new_vendor = Vendor.objects.get_or_create( name=c.get_vendor()[0]) product, is_new_product = Product.objects.get_or_create( name=c.get_product()[0], vendor=vendor) productversion, is_new_productversion = ProductVersion.objects.get_or_create( version=c.get_version()[0], product=product, vector=cpe) if cpe not in vulnerable_products: vulnerable_products.append(cpe) if product not in products: products.append(product) if productversion not in productversions: productversions.append(productversion) if cpe not in my_cpes: new_cpe = CPE(vector=cpe, title=cpe, vendor=vendor, product=product, vulnerable_products=[]) new_cpe.save() # Add the current CPE to inner list my_cpes.append(cpe) except Exception: pass cve.vulnerable_products = list(set(vulnerable_products)) # Deduplicate for p in products: cve.products.add(p) for pv in productversions: cve.productversions.add(pv) cve.save() # Create a Vuln vuln_data = dict(cve_data) vuln_data.pop("references") vuln_data["reflinks"] = cve_data["references"]["others"] vuln_data["cve_id"] = cve.id vuln_data["vulnerable_products"] = cve.vulnerable_products vuln_data["cveid"] = cve.cve_id vuln_data["uuid"] = uuid.uuid4() vuln_data["reflinkids"] = dict() vuln_data["is_exploitable"] = str(self.data.get( 'is_exploitable', 'false')).lower() in ['true', 'yes', 'y', 'on', '1'] vuln_data["is_confirmed"] = str(self.data.get( 'is_confirmed', 'false')).lower() in ['true', 'yes', 'y', 'on', '1'] vuln_data["is_in_the_news"] = str(self.data.get( 'is_in_the_news', 'false')).lower() in ['true', 'yes', 'y', 'on', '1'] vuln_data["is_in_the_wild"] = str(self.data.get( 'is_in_the_wild', 'false')).lower() in ['true', 'yes', 'y', 'on', '1'] vuln = Vuln(**vuln_data) try: vuln.full_clean() vuln.save() except Exception: cve.delete() res = { "status": "error", "reason": "Unable to create vulnerability in DB" } return JsonResponse(res, safe=False) # Update products and productversion lists for p in products: vuln.products.add(p) for pv in productversions: vuln.productversions.add(pv) vuln.update_product_versions() vuln.save() # Check if the vulnerability is monitored monitored = False if 'monitored' in self.data.keys() and type( self.data['monitored']) == bool: monitored = self.data['monitored'] org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) if org is not None and monitored is True and vuln not in org.org_monitoring_list.vulns.all( ): org.org_monitoring_list.vulns.add(vuln) res.update({"data": vuln.to_dict()}) return JsonResponse(res, safe=False)
def get_latest_vulns(self): MAX_VULNS = 20 MAX_TIMEDELTA_DAYS = 30 if self.GET.get('timedelta', None) and self.GET.get('timedelta').isnumeric(): MAX_TIMEDELTA_DAYS = int(self.GET.get('timedelta')) + 30 vulns = list( Vuln.objects.all().only('id', 'cveid', 'summary', 'score').values( 'id', 'cveid', 'summary', 'score').order_by('-updated_at').distinct()[:MAX_VULNS]) exploits = [] exploit_list = list(ExploitMetadata.objects.all().only( 'id', 'source', 'link', 'trust_level', 'availability', 'maturity').distinct('link', 'updated_at').order_by('-updated_at', 'link')[:MAX_VULNS]) for exploit in exploit_list: exploits.append({ 'source': exploit.source, 'link': exploit.link, 'trust_level': exploit.trust_level, 'scope': 'public', 'relevancy_level': exploit.get_relevancy_level() }) org_id = self.session.get('org_id', None) org = organization.get_current_organization(user=self.user, org_id=org_id) monitored_products = org.org_monitoring_list.products.all( ).prefetch_related('vendor') monitored_vulns = org.org_monitoring_list.vulns.all().prefetch_related( 'exploitmetadata_set', 'orgexploitmetadata_set', 'orgexploitmetadata_set__organization', 'products', 'products__vendor', 'cwe') mp = monitored_products.annotate( vendorproduct=Concat(Value(':'), F('vendor__name'), Value( ':'), F('name'), Value(':'))).values_list('vendorproduct', flat=True) monitored_vulns_list = list() for mv in monitored_vulns: monitored_vulns_list.append({ 'id': mv.id, 'cveid': mv.cveid, 'summary': mv.summary, 'access': mv.access, 'impact': mv.impact, 'score': mv.score, 'cvss': mv.cvss, 'cvss3': mv.cvss3, 'products': [{ 'id': p.id, 'name': p.name, 'vendor': p.vendor.name } for p in mv.products.all()], 'updated_at': mv.updated_at, 'is_confirmed': mv.is_confirmed, 'exploit_count': mv.exploitmetadata_set.count() + mv.orgexploitmetadata_set.filter(organization=org).count(), }) for lv in Vuln.objects.prefetch_related( 'products', 'products__vendor').exclude( id__in=[o['id'] for o in monitored_vulns_list]).filter( modified__gte=datetime.now() - timedelta(days=MAX_TIMEDELTA_DAYS)).prefetch_related( 'exploitmetadata_set', 'orgexploitmetadata_set').order_by( '-updated_at').distinct()[:1000]: # Check if vulnerable products are monitored if lv.vulnerable_products is not None and len( lv.vulnerable_products) > 0: for lvvp in lv.vulnerable_products: res = [ele for ele in mp if (ele in lvvp)] if bool(res): monitored_vulns_list.append( dict({ 'id': lv.id, 'cveid': lv.cveid, 'summary': lv.summary, 'access': lv.access, 'impact': lv.impact, 'score': lv.score, 'cvss': lv.cvss, 'cvss3': lv.cvss3, 'products': [{ 'id': p.id, 'name': p.name, 'vendor': p.vendor.name } for p in lv.products.all()], 'exploit_count': lv.exploitmetadata_set.count() + lv.orgexploitmetadata_set.filter( organization=org).count(), 'is_confirmed': lv.is_confirmed, 'updated_at': lv.updated_at })) break res = { 'vulns': vulns, 'exploits': exploits, 'monitored_vulns': monitored_vulns_list, } return JsonResponse(res, safe=False)