Пример #1
0
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)
Пример #2
0
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'})
Пример #3
0
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)
Пример #4
0
 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
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
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)
Пример #8
0
    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
Пример #9
0
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
Пример #10
0
 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
Пример #11
0
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)
Пример #12
0
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)
Пример #13
0
    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')
Пример #14
0
 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': '-'}
Пример #15
0
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)
Пример #16
0
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)
Пример #17
0
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)
Пример #18
0
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)
Пример #19
0
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)
Пример #20
0
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)
Пример #21
0
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)