예제 #1
0
def new_eng_for_app(request, pid):
    prod = Product.objects.get(id=pid)
    if request.method == 'POST':
        form = EngForm(request.POST)
        if form.is_valid():
            new_eng = form.save(commit=False)
            new_eng.product = prod
            if new_eng.threat_model:
                new_eng.progress = 'threat_model'
            else:
                new_eng.progress = 'other'
            new_eng.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Engagement added successfully.',
                                 extra_tags='alert-success')
            if "_Add Tests" in request.POST:
                return HttpResponseRedirect(reverse('add_tests', args=(new_eng.id,)))
            else:
                return HttpResponseRedirect(reverse('view_engagement', args=(new_eng.id,)))
    else:
        form = EngForm(initial={})

    add_breadcrumb(parent=prod, title="New Engagement", top_level=False, request=request)

    return render(request, 'dojo/new_eng.html',
                  {'form': form, 'pid': pid,
                   })
예제 #2
0
def delete_product(request, pid):
    product = get_object_or_404(Product, pk=pid)
    form = DeleteProductForm(instance=product)

    from django.contrib.admin.util import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([product])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(product.id) == request.POST['id']:
            form = DeleteProductForm(request.POST, instance=product)
            if form.is_valid():
                product.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Product and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('product'))

    add_breadcrumb(parent=product, title="Delete", top_level=False, request=request)

    return render(request, 'dojo/delete_product.html',
                  {'product': product,
                   'form': form,
                   'rels': rels,
                   })
예제 #3
0
def gmap(request, pid):
    prod = get_object_or_404(Product, id=pid)
    if request.user.is_staff or request.user in prod.authorized_users.all():
        pass  # user is authorized for this product
    else:
        raise PermissionDenied

    form = ScanSettingsForm()
    if request.method == 'POST':
        form = ScanSettingsForm(data=request.POST)
        if form.is_valid():
            new_scan = form.save(commit=False)
            new_scan.product = prod
            new_scan.user = request.user
            new_scan.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Scan settings saved.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('view_product', args=(pid,)))
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'Scan settings not saved.',
                                 extra_tags='alert-danger')

    add_breadcrumb(title="Scan", top_level=False, request=request)

    return render(request,
                  'dojo/gmap.html',
                  {'form': form,
                   'pid': pid})
예제 #4
0
def add_stub_finding(request, tid):
    test = get_object_or_404(Test, id=tid)
    form = StubFindingForm()
    if request.method == 'POST':
        form = StubFindingForm(request.POST)
        if form.is_valid():
            stub_finding = form.save(commit=False)
            stub_finding.test = test
            stub_finding.reporter = request.user
            stub_finding.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Stub Finding created successfully.',
                                 extra_tags='alert-success')
            if request.is_ajax():
                data = {'message': 'Stub Finding created successfully.',
                        'id': stub_finding.id,
                        'severity': 'None',
                        'date': formats.date_format(stub_finding.date, "DATE_FORMAT")}
                return HttpResponse(json.dumps(data))
        else:
            if request.is_ajax():
                data = {'message': 'Stub Finding form has error, please revise and try again.',}
                return HttpResponse(json.dumps(data))

            messages.add_message(request,
                                 messages.ERROR,
                                 'Stub Finding form has error, please revise and try again.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Add Stub Finding", top_level=False, request=request)
    return HttpResponseRedirect(reverse('view_test', args=(tid,)))
예제 #5
0
def add_template(request):
    form = FindingTemplateForm()
    if request.method == 'POST':
        form = FindingTemplateForm(request.POST)
        if form.is_valid():
            template = form.save(commit=False)
            template.numerical_severity = Finding.get_numerical_severity(template.severity)
            template.save()
            tags = request.POST.getlist('tags')
            t = ", ".join(tags)
            template.tags = t
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Template created successfully.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('templates'))
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'Template form has error, please revise and try again.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Add Template", top_level=False, request=request)
    return render(request, 'dojo/add_template.html',
                  {'form': form,
                   'name': 'Add Template'
                   })
예제 #6
0
def close_finding(request, fid):
    finding = get_object_or_404(Finding, id=fid)
    # in order to close a finding, we need to capture why it was closed
    # we can do this with a Note
    if request.method == 'POST':
        form = CloseFindingForm(request.POST)

        if form.is_valid():
            now = datetime.now(tz=localtz)
            new_note = form.save(commit=False)
            new_note.author = request.user
            new_note.date = now
            new_note.save()
            finding.notes.add(new_note)
            finding.active = False
            finding.mitigated = now
            finding.mitigated_by = request.user
            finding.last_reviewed = finding.mitigated
            finding.last_reviewed_by = request.user
            finding.endpoints.clear()
            finding.save()

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Finding closed.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('view_test', args=(finding.test.id,)))

    else:
        form = CloseFindingForm()

    add_breadcrumb(parent=finding, title="Close", top_level=False, request=request)
    return render(request, 'dojo/close_finding.html',
                  {'finding': finding,
                   'user': request.user, 'form': form})
예제 #7
0
def accepted_findings(request):
    user = request.user

    fids = [finding.id for ra in
            Risk_Acceptance.objects.all()
            for finding in ra.accepted_findings.all()]
    findings = Finding.objects.filter(id__in=fids)
    findings = AcceptedFingingSuperFilter(request.GET, queryset=findings)
    title_words = [word for ra in
                   Risk_Acceptance.objects.all()
                   for finding in ra.accepted_findings.order_by(
            'title').values('title').distinct()
                   for word in finding['title'].split() if len(word) > 2]

    title_words = sorted(set(title_words))
    paged_findings = get_page_items(request, findings, 25)

    add_breadcrumb(title="Accepted findings", top_level=not len(request.GET), request=request)

    return render(request,
                  'dojo/accepted_findings.html',
                  {"findings": paged_findings,
                   "filtered": findings,
                   "title_words": title_words,
                   })
예제 #8
0
def edit_template(request, tid):
    template = get_object_or_404(Finding_Template, id=tid)
    form = FindingTemplateForm(instance=template)
    if request.method == 'POST':
        form = FindingTemplateForm(request.POST, instance=template)
        if form.is_valid():
            template = form.save(commit=False)
            template.numerical_severity = Finding.get_numerical_severity(template.severity)
            template.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Template updated successfully.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('templates'))
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'Template form has error, please revise and try again.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Edit Template", top_level=False, request=request)
    return render(request, 'dojo/add_template.html',
                  {'form': form,
                   'name': 'Edit Template',
                   'template': template,
                   })
예제 #9
0
def open_findings(request):
    findings = Finding.objects.filter(mitigated__isnull=True,
                                      verified=True,
                                      false_p=False,
                                      duplicate=False,
                                      out_of_scope=False)
    if request.user.is_staff:
        findings = OpenFingingSuperFilter(request.GET, queryset=findings, user=request.user)
    else:
        findings = findings.filter(product__authorized_users__in=[request.user])
        findings = OpenFindingFilter(request.GET, queryset=findings, user=request.user)

    title_words = [word
                   for finding in findings
                   for word in finding.title.split() if len(word) > 2]

    title_words = sorted(set(title_words))
    paged_findings = get_page_items(request, findings, 25)

    product_type = None
    if 'product__prod_type' in request.GET:
        p = request.GET.getlist('product__prod_type', [])
        if len(p) == 1:
            product_type = get_object_or_404(Product_Type, id=p[0])

    add_breadcrumb(title="Open findings", top_level=not len(request.GET), request=request)

    return render(request,
                  'dojo/open_findings.html',
                  {"findings": paged_findings,
                   "filtered": findings,
                   "title_words": title_words,
                   })
def delete_engagement_survey(request, eid, sid):
    engagement = get_object_or_404(Engagement, id=eid)
    survey = get_object_or_404(Answered_Survey, id=sid)

    questions = get_answered_questions(survey=survey, read_only=True)

    form = Delete_Survey_Form(instance=survey)

    if request.method == 'POST':
        form = Delete_Survey_Form(request.POST, instance=survey)
        if form.is_valid():
            answers = Answer.objects.filter(
                question__in=[
                    question.id for question in survey.survey.questions.all()],
                answered_survey=survey)
            for answer in answers:
                answer.delete()
            survey.delete()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Survey deleted successfully.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect('/engagement/%s' % eid)
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'Unable to delete survey.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Delete " + survey.survey.name + " Survey", top_level=False, request=request)
    return render(request, 'defectDojo-engagement-survey/delete_survey.html',
                  {'survey': survey,
                   'form': form,
                   'engagement': engagement,
                   'questions': questions,
                   })
예제 #11
0
def delete_test(request, tid):
    test = get_object_or_404(Test, pk=tid)
    eng = test.engagement
    form = DeleteTestForm(instance=test)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([test])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(test.id) == request.POST['id']:
            form = DeleteTestForm(request.POST, instance=test)
            if form.is_valid():
                del test.tags
                test.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Test and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('view_engagement', args=(eng.id,)))

    add_breadcrumb(parent=test, title="Delete", top_level=False, request=request)
    return render(request, 'dojo/delete_test.html',
                  {'test': test,
                   'form': form,
                   'rels': rels,
                   'deletable_objects': rels,
                   })
예제 #12
0
def edit_object(request, pid, ttid):
    object = Objects.objects.get(pk=ttid)

    if request.method == 'POST':
        tform = ObjectSettingsForm(request.POST, instance=object)
        if tform.is_valid():
            tform.save()

            tags = request.POST.getlist('tags')
            t = ", ".join(tags)
            object.tags = t

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Tool Product Configuration Successfully Updated.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('view_objects', args=(pid,)))
    else:
        tform = ObjectSettingsForm(instance=object,
        initial={'tags': get_tag_list(Tag.objects.get_for_object(object))})

    tform.initial['tags'] = [tag.name for tag in object.tags]
    add_breadcrumb(title="Edit Tracked Files", top_level=False, request=request)
    return render(request,
                  'dojo/edit_object.html',
                  {
                      'tform': tform,
                  })
예제 #13
0
def edit_user(request, uid):
    user = get_object_or_404(Dojo_User, id=uid)
    authed_products = Product.objects.filter(authorized_users__in=[user])
    form = AddDojoUserForm(instance=user, initial={'authorized_products': authed_products})

    if request.method == 'POST':
        form = AddDojoUserForm(request.POST, instance=user, initial={'authorized_products': authed_products})
        if form.is_valid():
            form.save()
            if 'authorized_products' in form.cleaned_data and len(form.cleaned_data['authorized_products']) > 0:
                for p in form.cleaned_data['authorized_products']:
                    p.authorized_users.add(user)
                    p.save()

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'User saved successfully.',
                                 extra_tags='alert-success')
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'User was not saved successfully.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Edit User", top_level=False, request=request)
    return render(request, "dojo/add_user.html", {
        'name': 'Edit User',
        'form': form,
        'to_edit': user})
예제 #14
0
def alerts(request):
    alerts = get_alerts(request.user)
    paged_alerts = get_page_items(request, alerts, 25)
    add_breadcrumb(title="Alerts for " + request.user.get_full_name(), top_level=True, request=request)
    return render(request,
                  'dojo/alerts.html',
                  {'alerts': paged_alerts})
예제 #15
0
def add_user(request):
    form = AddDojoUserForm()
    user = None

    if request.method == 'POST':
        form = AddDojoUserForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            user.set_unusable_password()
            user.is_staff = False
            user.is_superuser = False
            user.active = True
            user.save()
            if 'authorized_products' in form.cleaned_data and len(form.cleaned_data['authorized_products']) > 0:
                for p in form.cleaned_data['authorized_products']:
                    p.authorized_users.add(user)
                    p.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'User added successfully, you may edit if necessary.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('edit_user', args=(user.id,)))
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'User was not added successfully.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Add User", top_level=False, request=request)
    return render(request, "dojo/add_user.html", {
        'name': 'Add User',
        'form': form,
        'to_add': True})
예제 #16
0
def new_object(request, pid):
    prod = get_object_or_404(Product, id=pid)
    if request.method == 'POST':
        tform = ObjectSettingsForm(request.POST)
        if tform.is_valid():
            new_prod = tform.save(commit=False)
            new_prod.product = prod
            new_prod.save()

            tags = request.POST.getlist('tags')
            t = ", ".join(tags)
            new_prod.tags = t

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Added Tracked File to a Product',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('view_objects', args=(pid,)))
    else:
        tform = ObjectSettingsForm()
        add_breadcrumb(title="Add Tracked Files to a Product", top_level=False, request=request)

    return render(request, 'dojo/new_object.html',
                  {'tform': tform,
                  'pid': prod.id})
예제 #17
0
def delete_user(request, uid):
    user = get_object_or_404(Dojo_User, id=uid)
    form = DeleteUserForm(instance=user)

    from django.contrib.admin.utils import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([user])
    rels = collector.nested()

    if user.id == request.user.id:
        messages.add_message(request,
                             messages.ERROR,
                             'You may not delete yourself.',
                             extra_tags='alert-danger')
        return HttpResponseRedirect(reverse('edit_user', args=(user.id,)))

    if request.method == 'POST':
        if 'id' in request.POST and str(user.id) == request.POST['id']:
            form = DeleteUserForm(request.POST, instance=user)
            if form.is_valid():
                user.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'User and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('users'))
    add_breadcrumb(title="Delete User", top_level=False, request=request)
    return render(request, 'dojo/delete_user.html',
                  {'to_delete': user,
                   'form': form,
                   'rels': rels,
                   })
def create_survey(request):
    form = CreateSurveyForm()
    survey = None

    if request.method == 'POST':
        form = CreateSurveyForm(request.POST)
        if form.is_valid():
            survey = form.save()

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Survey successfully created, you may now add questions.',
                                 extra_tags='alert-success')
            if 'add_questions' in request.POST:
                return HttpResponseRedirect(reverse('edit_survey_questions', args=(survey.id,)))
            else:
                return HttpResponseRedirect(reverse('edit_survey', args=(survey.id,)))
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'Please correct any errors displayed below.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Create Survey", top_level=False, request=request)
    return render(request, 'defectDojo-engagement-survey/create_survey.html',
                  {"survey": survey,
                   "form": form,
                   "name": "Create Survey",
                   })
예제 #19
0
def api_key(request):
    api_key = ''
    form = APIKeyForm(instance=request.user)
    if request.method == 'POST':  # new key requested
        form = APIKeyForm(request.POST, instance=request.user)
        if form.is_valid() and form.cleaned_data['id'] == request.user.id:
            try:
                api_key = ApiKey.objects.get(user=request.user)
                api_key.key = None
                api_key.save()
            except ApiKey.DoesNotExist:
                api_key = ApiKey.objects.create(user=request.user)
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'API Key generated successfully.',
                                 extra_tags='alert-success')
        else:
            raise PermissionDenied
    else:
        try:
            api_key = ApiKey.objects.get(user=request.user)
        except ApiKey.DoesNotExist:
            api_key = ApiKey.objects.create(user=request.user)

    add_breadcrumb(title="API Key", top_level=True, request=request)

    return render(request, 'dojo/api_key.html',
                  {'name': 'API Key',
                   'metric': False,
                   'user': request.user,
                   'key': api_key,
                   'form': form,
                   })
예제 #20
0
def report_builder(request):
    add_breadcrumb(title="Report Builder", top_level=True, request=request)
    findings = Finding.objects.all()
    findings = ReportAuthedFindingFilter(request.GET, queryset=findings, user=request.user)
    endpoints = Endpoint.objects.filter(finding__active=True,
                                        finding__verified=True,
                                        finding__false_p=False,
                                        finding__duplicate=False,
                                        finding__out_of_scope=False,
                                        ).distinct()
    ids = get_endpoint_ids(endpoints)

    endpoints = Endpoint.objects.filter(id__in=ids)

    endpoints = EndpointFilter(request.GET, queryset=endpoints)

    in_use_widgets = [ReportOptions(request=request)]
    available_widgets = [CoverPage(request=request),
                         TableOfContents(request=request),
                         WYSIWYGContent(request=request),
                         FindingList(request=request, findings=findings),
                         EndpointList(request=request, endpoints=endpoints),
                         PageBreak()]
    return render(request,
                  'dojo/report_builder.html',
                  {"available_widgets": available_widgets,
                   "in_use_widgets": in_use_widgets})
def delete_survey(request, sid):
    survey = get_object_or_404(Engagement_Survey, id=sid)
    form = Delete_Eng_Survey_Form(instance=survey)

    from django.contrib.admin.util import NestedObjects
    from django.db import DEFAULT_DB_ALIAS

    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([survey])
    rels = collector.nested()

    if request.method == 'POST':
        if 'id' in request.POST and str(survey.id) == request.POST['id']:
            form = Delete_Eng_Survey_Form(request.POST, instance=survey)
            if form.is_valid():
                survey.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Survey and relationships removed.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('survey'))
    add_breadcrumb(title="Delete Survey", top_level=False, request=request)
    return render(request, 'defectDojo-engagement-survey/delete_survey.html',
                  {'survey': survey,
                   'form': form,
                   'rels': rels,
                   })
예제 #22
0
def view_profile(request):
    user = get_object_or_404(Dojo_User, pk=request.user.id)
    try:
        user_contact = UserContactInfo.objects.get(user=user)
    except UserContactInfo.DoesNotExist:
        user_contact = None

    form = DojoUserForm(instance=user)
    if user_contact is None:
        contact_form = UserContactInfoForm()
    else:
        contact_form = UserContactInfoForm(instance=user_contact)
    if request.method == 'POST':
        form = DojoUserForm(request.POST, instance=user)
        contact_form = UserContactInfoForm(request.POST, instance=user_contact)
        if form.is_valid() and contact_form.is_valid():
            form.save()
            contact = contact_form.save(commit=False)
            contact.user = user
            contact.save()

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Profile updated successfully.',
                                 extra_tags='alert-success')
    add_breadcrumb(title="User Profile - " + user.get_full_name(), top_level=True, request=request)
    return render(request, 'dojo/profile.html', {
        'name': 'Engineer Profile',
        'metric': False,
        'user': user,
        'form': form,
        'contact_form': contact_form})
예제 #23
0
def view_engagement(request, eid):
    eng = Engagement.objects.get(id=eid)
    tests = Test.objects.filter(engagement=eng)
    risks_accepted = eng.risk_acceptance.all()

    exclude_findings = [finding.id for ra in eng.risk_acceptance.all()
                        for finding in ra.accepted_findings.all()]
    eng_findings = Finding.objects.filter(test__in=eng.test_set.all()) \
        .exclude(id__in=exclude_findings).order_by('title')

    try:
        check = Check_List.objects.get(engagement=eng)
    except:
        check = None
        pass
    form = DoneForm()
    if request.method == 'POST':
        eng.progress = 'check_list'
        eng.save()

    add_breadcrumb(parent=eng, top_level=False, request=request)

    return render(request, 'dojo/view_eng.html',
                  {'eng': eng, 'tests': tests,
                   'check': check, 'threat': eng.tmodel_path,
                   'risk': eng.risk_path, 'form': form,
                   'risks_accepted': risks_accepted,
                   'can_add_risk': len(eng_findings),
                   })
예제 #24
0
def view_product_details(request, pid):
    prod = get_object_or_404(Product, id=pid)
    scan_sets = ScanSettings.objects.filter(product=prod)
    tools = Tool_Product_Settings.objects.filter(product=prod).order_by('name')
    auth = request.user.is_staff or request.user in prod.authorized_users.all()
    creds = Cred_Mapping.objects.filter(product=prod).select_related('cred_id').order_by('cred_id')
    langSummary = Languages.objects.filter(product=prod).aggregate(Sum('files'), Sum('code'), Count('files'))
    languages = Languages.objects.filter(product=prod).order_by('-code')
    app_analysis = App_Analysis.objects.filter(product=prod).order_by('name')
    benchmark_type = Benchmark_Type.objects.filter(enabled=True).order_by('name')
    benchmarks = Benchmark_Product_Summary.objects.filter(product=prod, publish=True, benchmark_type__enabled=True).order_by('benchmark_type__name')
    system_settings = System_Settings.objects.get()

    if not auth:
        # will render 403
        raise PermissionDenied

    product_metadata = dict(prod.product_meta.values_list('name', 'value'))

    add_breadcrumb(parent=product, title="Details", top_level=False, request=request)
    return render(request,
                  'dojo/view_product_details.html',
                  {'prod': prod,
                   'benchmark_type': benchmark_type,
                   'benchmarks': benchmarks,
                   'product_metadata': product_metadata,
                   'scan_sets': scan_sets,
                   'tools': tools,
                   'creds': creds,
                   'user': request.user,
                   'languages': languages,
                   'langSummary': langSummary,
                   'app_analysis': app_analysis,
                   'system_settings': system_settings,
                   'authorized': auth})
예제 #25
0
def product(request):
    if request.user.is_staff:
        initial_queryset = Product.objects.all()
        name_words = [product.name for product in
                      Product.objects.all()]
    else:
        initial_queryset = Product.objects.filter(
            authorized_users__in=[request.user])
        name_words = [word for product in
                      Product.objects.filter(
                          authorized_users__in=[request.user])
                      for word in product.name.split() if len(word) > 2]

    product_type = None

    if 'prod_type' in request.GET:
        p = request.GET.getlist('prod_type', [])
        if len(p) == 1:
            product_type = get_object_or_404(Product_Type, id=p[0])
    """
    if 'tags' in request.GET:
        tags = request.GET.getlist('tags', [])
        initial_queryset = TaggedItem.objects.get_by_model(initial_queryset, Tag.objects.filter(name__in=tags))
    """
    prods = ProductFilter(request.GET, queryset=initial_queryset, user=request.user)
    prod_list = get_page_items(request, prods.qs, 25)
    add_breadcrumb(title="Product List", top_level=not len(request.GET), request=request)
    return render(request,
                  'dojo/product.html',
                  {'prod_list': prod_list,
                   'prods': prods,
                   'name_words': sorted(set(name_words)),
                   'user': request.user})
def add_survey(request, eid):
    user = request.user
    engagement = get_object_or_404(Engagement, id=eid)
    ids = [survey.survey.id for survey in
           Answered_Survey.objects.filter(engagement=engagement)]
    surveys = Engagement_Survey.objects.exclude(
        id__in=ids)
    form = Add_Survey_Form()
    if request.method == 'POST':
        form = Add_Survey_Form(request.POST)
        if form.is_valid():
            survey = form.save(commit=False)
            survey.engagement = engagement
            survey.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Survey successfully added, answers pending.',
                                 extra_tags='alert-success')
            if 'respond_survey' in request.POST:
                return HttpResponseRedirect(
                    '/engagement/%s/survey/%s/answer' % (eid, survey.id))

            return HttpResponseRedirect('/engagement/%s' % eid)
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'Survey could not be added.',
                                 extra_tags='alert-danger')
    form.fields["survey"].queryset = surveys
    add_breadcrumb(title="Add Survey", top_level=False, request=request)
    return render(request, 'defectDojo-engagement-survey/add_survey.html',
                  {'surveys': surveys,
                   'user': user,
                   'form': form,
                   'engagement': engagement})
예제 #27
0
def edit_tool_config(request, ttid):
    tool_config = Tool_Configuration.objects.get(pk=ttid)
    if request.method == 'POST':
        tform = ToolConfigForm(request.POST, instance=tool_config)
        if tform.is_valid():
            form_copy = tform.save(commit=False)
            form_copy.password = dojo_crypto_encrypt(tform.cleaned_data['password'])
            print "######"
            print tform.cleaned_data['ssh']

            form_copy.ssh = dojo_crypto_encrypt(tform.cleaned_data['ssh'])
            form_copy.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Tool Configuration Successfully Updated.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('tool_config', ))
    else:
        tool_config.password = prepare_for_view(tool_config.password)
        tool_config.ssh = prepare_for_view(tool_config.ssh)
        tform = ToolConfigForm(instance=tool_config)
    add_breadcrumb(title="Edit Tool Configuration", top_level=False, request=request)

    return render(request,
                  'dojo/edit_tool_config.html',
                  {
                      'tform': tform,
                  })
예제 #28
0
def view_tool_product(request, pid, ttid):
    tool = Tool_Product_Settings.objects.get(pk=ttid)
    notes = tool.notes.all()

    if request.method == 'POST':
        form = NoteForm(request.POST)
        if form.is_valid():
            new_note = form.save(commit=False)
            new_note.author = request.user
            new_note.date = timezone.now()
            new_note.save()
            tool.notes.add(new_note)
            form = NoteForm()
            # url = request.build_absolute_uri(reverse("view_test", args=(test.id,)))
            # title="Test: %s on %s" % (test.test_type.name, test.engagement.product.name)
            # process_notifications(request, new_note, url, title)
            messages.add_message(
                request,
                messages.SUCCESS,
                'Note added successfully.',
                extra_tags='alert-success')
    else:
        form = NoteForm()

    add_breadcrumb(
        title="View Product Tool Configuration",
        top_level=False,
        request=request)

    return render(request, 'dojo/view_tool_product.html', {
        'tool': tool,
        'notes': notes,
        'form': form
    })
예제 #29
0
def tool_config(request):
    confs = Tool_Configuration.objects.all().order_by('name')
    add_breadcrumb(title="Tool Configuration List", top_level=not len(request.GET), request=request)
    return render(request,
                  'dojo/tool_config.html',
                  {'confs': confs,
                   })
예제 #30
0
def tool_type(request):
    confs = Tool_Type.objects.all().order_by('name')
    add_breadcrumb(title="Tool Type List", top_level=not len(request.GET), request=request)
    return render(request,
                  'dojo/tool_type.html',
                  {'confs': confs,
                   })
예제 #31
0
def benchmark_view(request, pid, type, cat=None):
    product = get_object_or_404(Product, id=pid)
    benchmark_type = get_object_or_404(Benchmark_Type, id=type)
    benchmark_category = Benchmark_Category.objects.filter(type=type, enabled=True).order_by('name')
    category_name = ""

    # Add requirements to the product
    add_benchmark(Benchmark_Requirement.objects.filter(category__type=type, category__type__enabled=True, enabled=True).all(), product)

    if cat:
        category_name = Benchmark_Category.objects.get(id=cat, enabled=True).name

    # Create the benchmark summary category
    try:
        benchmark_product_summary = Benchmark_Product_Summary.objects.get(product=product, benchmark_type=benchmark_type)
    except:
        pass
        benchmark_product_summary = Benchmark_Product_Summary(product=product, benchmark_type=benchmark_type)
        benchmark_product_summary.save()

    # Insert any new benchmarks since last created
    new_benchmarks = Benchmark_Requirement.objects.filter(category__type=type, category__type__enabled=True, enabled=True).exclude(id__in=Benchmark_Product.objects.filter(product=product).values_list('control_id', flat=True))
    add_benchmark(new_benchmarks, product)

    Benchmark_ProductFormSet = modelformset_factory(Benchmark_Product, exclude=['product, control'], extra=0)

    if request.method == 'POST':
        form = Benchmark_ProductFormSet(request.POST)
        summary_form = Benchmark_Product_SummaryForm(request.POST, instance=benchmark_product_summary)

        if form.is_valid():
            # print summary_form.errors
            summary_form_save = summary_form.save()
            form_save = form.save()
            score_asvs(product, benchmark_type)
            benchmark_product_summary = Benchmark_Product_Summary.objects.get(product=product, benchmark_type=benchmark_type)

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Benchmarks saved.',
                                 extra_tags='alert-success')

    add_breadcrumb(title="Benchmarks", top_level=False, request=request)

    if cat:
        benchmarks = Benchmark_Product.objects.filter(product=product.id, control__category=cat, control__category__enabled=True, control__category__type=type, control__enabled=True).all().order_by('control__objective_number')

        benchmark_formset = Benchmark_ProductFormSet(queryset=Benchmark_Product.objects.filter(product=product.id, control__category=cat, control__category__enabled=True, control__category__type=type, control__enabled=True).all().order_by('control__objective_number'))
    else:
        benchmarks = Benchmark_Product.objects.filter(product=product.id, control__category__enabled=True, control__category__type=type, control__enabled=True).all().order_by('control__category__name', 'control__objective_number')

        benchmark_formset = Benchmark_ProductFormSet(queryset=Benchmark_Product.objects.filter(product=product.id, control__category__enabled=True, control__category__type=type, control__enabled=True).all().order_by('control__category__name', 'control__objective_number'))

    benchmark_summary_form = Benchmark_Product_SummaryForm(instance=benchmark_product_summary)

    product_tab = Product_Tab(pid, title="Benchmarks", tab="benchmarks")

    return render(request, 'dojo/benchmark.html',
                  {'benchmarks': benchmarks,
                   'active_tab': 'benchmarks',
                   'product_tab': product_tab,
                   'benchmark_product_summary': benchmark_product_summary,
                   'benchmark_summary_form': benchmark_summary_form,
                   'benchmark_formset': benchmark_formset,
                   'benchmark_type': benchmark_type,
                   'product': product,
                   'category_name': category_name,
                   'benchmark_category': benchmark_category})
예제 #32
0
def process_endpoints_view(request, host_view=False, vulnerable=False):

    if vulnerable:
        endpoints = Endpoint.objects.filter(finding__active=True,
                                            finding__verified=True,
                                            finding__false_p=False,
                                            finding__duplicate=False,
                                            finding__out_of_scope=False,
                                            mitigated=False)
        endpoints = endpoints.filter(endpoint_status__mitigated=False)
    else:
        endpoints = Endpoint.objects.all()

    endpoints = endpoints.prefetch_related('product', 'product__tags',
                                           'tags').distinct()
    endpoints = get_authorized_endpoints(Permissions.Endpoint_View, endpoints,
                                         request.user)

    if host_view:
        ids = get_endpoint_ids(
            EndpointFilter(request.GET, queryset=endpoints,
                           user=request.user).qs)
        endpoints = EndpointFilter(request.GET,
                                   queryset=endpoints.filter(id__in=ids),
                                   user=request.user)
    else:
        endpoints = EndpointFilter(request.GET,
                                   queryset=endpoints,
                                   user=request.user)

    paged_endpoints = get_page_items(request, endpoints.qs, 25)

    if vulnerable:
        view_name = "Vulnerable"
    else:
        view_name = "All"

    if host_view:
        view_name += " Hosts"
    else:
        view_name += " Endpoints"

    add_breadcrumb(title=view_name,
                   top_level=not len(request.GET),
                   request=request)

    product_tab = None
    if 'product' in request.GET:
        p = request.GET.getlist('product', [])
        if len(p) == 1:
            product = get_object_or_404(Product, id=p[0])
            user_has_permission_or_403(request.user, product,
                                       Permissions.Product_View)
            product_tab = Product_Tab(product.id, view_name, tab="endpoints")

    return render(
        request, 'dojo/endpoints.html', {
            'product_tab': product_tab,
            "endpoints": paged_endpoints,
            "filtered": endpoints,
            "name": view_name,
            "host_view": host_view,
            "product_tab": product_tab
        })
예제 #33
0
def view_engineer(request, eid):
    user = get_object_or_404(Dojo_User, pk=eid)
    if not (request.user.is_superuser
            or request.user.username == 'root'
            or request.user.username == user.username):
        return HttpResponseRedirect(reverse('engineer_metrics'))
    now = localtz.localize(datetime.today())

    findings = Finding.objects.filter(reporter=user, verified=True)
    closed_findings = Finding.objects.filter(mitigated_by=user)
    open_findings = findings.exclude(mitigated__isnull=False)
    open_month = findings.filter(date__year=now.year, date__month=now.month)
    accepted_month = [finding for ra in Risk_Acceptance.objects.filter(
        created__range=[datetime(now.year,
                                 now.month, 1,
                                 tzinfo=localtz),
                        datetime(now.year,
                                 now.month,
                                 monthrange(now.year,
                                            now.month)[1],
                                 tzinfo=localtz)],
        reporter=user)
                      for finding in ra.accepted_findings.all()]
    closed_month = []
    for f in closed_findings:
        if f.mitigated and f.mitigated.year == now.year and f.mitigated.month == now.month:
            closed_month.append(f)

    o_dict, open_count = count_findings(open_month)
    c_dict, closed_count = count_findings(closed_month)
    a_dict, accepted_count = count_findings(accepted_month)
    day_list = [now - relativedelta(weeks=1,
                                    weekday=x,
                                    hour=0,
                                    minute=0,
                                    second=0)
                for x in range(now.weekday())]
    day_list.append(now)

    q_objects = (Q(date=d) for d in day_list)
    closed_week = []
    open_week = findings.filter(reduce(operator.or_, q_objects))

    accepted_week = [finding for ra in Risk_Acceptance.objects.filter(
        reporter=user, created__range=[day_list[0], day_list[-1]])
                     for finding in ra.accepted_findings.all()]

    q_objects = (Q(mitigated=d) for d in day_list)
    # closed_week= findings.filter(reduce(operator.or_, q_objects))
    for f in closed_findings:
        if f.mitigated and f.mitigated >= day_list[0]:
            closed_week.append(f)

    o_week_dict, open_week_count = count_findings(open_week)
    c_week_dict, closed_week_count = count_findings(closed_week)
    a_week_dict, accepted_week_count = count_findings(accepted_week)

    stuff = []
    o_stuff = []
    a_stuff = []
    findings_this_period(findings, 1, stuff, o_stuff, a_stuff)
    # findings_this_period no longer fits the need for accepted findings
    # however will use its week finding output to use here
    for month in a_stuff:
        month_start = localtz.localize(datetime.strptime(
            month[0].strip(), "%b %Y"))
        month_end = datetime(month_start.year,
                             month_start.month,
                             monthrange(
                                 month_start.year,
                                 month_start.month)[1],
                             tzinfo=localtz)
        for finding in [finding for ra in Risk_Acceptance.objects.filter(
                created__range=[month_start, month_end], reporter=user)
                        for finding in ra.accepted_findings.all()]:
            if finding.severity == 'Critical':
                month[1] += 1
            if finding.severity == 'High':
                month[2] += 1
            if finding.severity == 'Medium':
                month[3] += 1
            if finding.severity == 'Low':
                month[4] += 1

        month[5] = sum(month[1:])
    week_stuff = []
    week_o_stuff = []
    week_a_stuff = []
    findings_this_period(findings, 0, week_stuff, week_o_stuff, week_a_stuff)

    # findings_this_period no longer fits the need for accepted findings
    # however will use its week finding output to use here
    for week in week_a_stuff:
        wk_range = week[0].split('-')
        week_start = localtz.localize(datetime.strptime(
            wk_range[0].strip() + " " + str(now.year), "%b %d %Y"))
        week_end = localtz.localize(datetime.strptime(
            wk_range[1].strip() + " " + str(now.year), "%b %d %Y"))

        for finding in [finding for ra in Risk_Acceptance.objects.filter(
                created__range=[week_start, week_end], reporter=user)
                        for finding in ra.accepted_findings.all()]:
            if finding.severity == 'Critical':
                week[1] += 1
            if finding.severity == 'High':
                week[2] += 1
            if finding.severity == 'Medium':
                week[3] += 1
            if finding.severity == 'Low':
                week[4] += 1

        week[5] = sum(week[1:])

    products = Product.objects.all()
    vulns = {}
    for product in products:
        f_count = 0
        engs = Engagement.objects.filter(product=product)
        for eng in engs:
            tests = Test.objects.filter(engagement=eng)
            for test in tests:
                f_count += findings.filter(test=test,
                                           mitigated__isnull=True,
                                           active=True).count()
        vulns[product.id] = f_count
    od = OrderedDict(sorted(vulns.items(), key=itemgetter(1)))
    items = od.items()
    items.reverse()
    top = items[: 10]
    update = []
    for t in top:
        product = t[0]
        z_count = 0
        o_count = 0
        t_count = 0
        h_count = 0
        engs = Engagement.objects.filter(
            product=Product.objects.get(id=product))
        for eng in engs:
            tests = Test.objects.filter(engagement=eng)
            for test in tests:
                z_count += findings.filter(
                    test=test,
                    mitigated__isnull=True,
                    severity='Critical'
                ).count()
                o_count += findings.filter(
                    test=test,
                    mitigated__isnull=True,
                    severity='High'
                ).count()
                t_count += findings.filter(
                    test=test,
                    mitigated__isnull=True,
                    severity='Medium'
                ).count()
                h_count += findings.filter(
                    test=test,
                    mitigated__isnull=True,
                    severity='Low'
                ).count()
        prod = Product.objects.get(id=product)
        all_findings_link = "<a href='%s'>%s</a>" % (
            reverse('view_product_findings', args=(prod.id,)), escape(prod.name))
        update.append([all_findings_link, z_count, o_count, t_count, h_count,
                       z_count + o_count + t_count + h_count])
    total_update = []
    for i in items:
        product = i[0]
        z_count = 0
        o_count = 0
        t_count = 0
        h_count = 0
        engs = Engagement.objects.filter(
            product=Product.objects.get(id=product))
        for eng in engs:
            tests = Test.objects.filter(engagement=eng)
            for test in tests:
                z_count += findings.filter(
                    test=test,
                    mitigated__isnull=True,
                    severity='Critical').count()
                o_count += findings.filter(
                    test=test,
                    mitigated__isnull=True,
                    severity='High').count()
                t_count += findings.filter(
                    test=test,
                    mitigated__isnull=True,
                    severity='Medium').count()
                h_count += findings.filter(
                    test=test,
                    mitigated__isnull=True,
                    severity='Low').count()
        prod = Product.objects.get(id=product)
        all_findings_link = "<a href='%s'>%s</a>" % (
            reverse('view_product_findings', args=(prod.id,)), escape(prod.name))
        total_update.append([all_findings_link, z_count, o_count, t_count,
                             h_count, z_count + o_count + t_count + h_count])

    neg_length = len(stuff)
    findz = findings.filter(mitigated__isnull=True, active=True,
                            test__engagement__risk_acceptance=None)
    findz = findz.filter(Q(severity="Critical") | Q(severity="High"))
    less_thirty = 0
    less_sixty = 0
    less_nine = 0
    more_nine = 0
    for finding in findz:
        elapsed = date.today() - finding.date
        if elapsed <= timedelta(days=30):
            less_thirty += 1
        elif elapsed <= timedelta(days=60):
            less_sixty += 1
        elif elapsed <= timedelta(days=90):
            less_nine += 1
        else:
            more_nine += 1

    # Data for the monthly charts
    chart_data = [['Date', 'S0', 'S1', 'S2', 'S3', 'Total']]
    for thing in o_stuff:
        chart_data.insert(1, thing)

    a_chart_data = [['Date', 'S0', 'S1', 'S2', 'S3', 'Total']]
    for thing in a_stuff:
        a_chart_data.insert(1, thing)

    # Data for the weekly charts
    week_chart_data = [['Date', 'S0', 'S1', 'S2', 'S3', 'Total']]
    for thing in week_o_stuff:
        week_chart_data.insert(1, thing)

    week_a_chart_data = [['Date', 'S0', 'S1', 'S2', 'S3', 'Total']]
    for thing in week_a_stuff:
        week_a_chart_data.insert(1, thing)

    details = []
    for find in open_findings:
        team = find.test.engagement.product.prod_type.name
        name = find.test.engagement.product.name
        severity = find.severity
        description = find.title
        life = date.today() - find.date
        life = life.days
        status = 'Active'
        if len(find.risk_acceptance_set.all()) > 0:
            status = 'Accepted'
        detail = [team, name, severity, description, life, status, find.reporter]
        details.append(detail)

    details = sorted(details, key=lambda x: x[2])

    add_breadcrumb(title="%s Metrics" % user.get_full_name(), top_level=False, request=request)

    return render(request, 'dojo/view_engineer.html', {
        'open_month': open_month,
        'a_month': accepted_month,
        'low_a_month': accepted_count["low"],
        'medium_a_month': accepted_count["med"],
        'high_a_month': accepted_count["high"],
        'critical_a_month': accepted_count["crit"],
        'closed_month': closed_month,
        'low_open_month': open_count["low"],
        'medium_open_month': open_count["med"],
        'high_open_month': open_count["high"],
        'critical_open_month': open_count["crit"],
        'low_c_month': closed_count["low"],
        'medium_c_month': closed_count["med"],
        'high_c_month': closed_count["high"],
        'critical_c_month': closed_count["crit"],
        'week_stuff': week_stuff,
        'week_a_stuff': week_a_stuff,
        'a_total': a_stuff,
        'total': stuff,
        'sub': neg_length,
        'update': update,
        'lt': less_thirty,
        'ls': less_sixty,
        'ln': less_nine,
        'mn': more_nine,
        'chart_data': chart_data,
        'a_chart_data': a_chart_data,
        'week_chart_data': week_chart_data,
        'week_a_chart_data': week_a_chart_data,
        'name': '%s Metrics' % user.get_full_name(),
        'metric': True,
        'total_update': total_update,
        'details': details,
        'open_week': open_week,
        'closed_week': closed_week,
        'accepted_week': accepted_week,
        'a_dict': a_dict,
        'o_dict': o_dict,
        'c_dict': c_dict,
        'o_week_dict': o_week_dict,
        'a_week_dict': a_week_dict,
        'c_week_dict': c_week_dict,
        'open_week_count': open_week_count,
        'accepted_week_count': accepted_week_count,
        'closed_week_count': closed_week_count,
        'user': request.user,
    })
예제 #34
0
def metrics(request, mtype):
    template = 'dojo/metrics.html'
    page_name = 'Product Type Metrics'
    show_pt_filter = True
    findings = Finding.objects.filter(verified=True,
                                      severity__in=('Critical', 'High', 'Medium', 'Low', 'Info')).prefetch_related(
        'test__engagement__product',
        'test__engagement__product__prod_type',
        'test__engagement__risk_acceptance',
        'risk_acceptance_set',
        'reporter').extra(
        select={
            'ra_count': 'SELECT COUNT(*) FROM dojo_risk_acceptance INNER JOIN '
                        'dojo_risk_acceptance_accepted_findings ON '
                        '( dojo_risk_acceptance.id = dojo_risk_acceptance_accepted_findings.risk_acceptance_id ) '
                        'WHERE dojo_risk_acceptance_accepted_findings.finding_id = dojo_finding.id',
            "sql_age": 'SELECT IF(dojo_finding.mitigated IS NULL, DATEDIFF(CURDATE(), dojo_finding.date), '
                       'DATEDIFF(dojo_finding.mitigated, dojo_finding.date))'
        },
    )
    active_findings = Finding.objects.filter(verified=True, active=True,
                                      severity__in=('Critical', 'High', 'Medium', 'Low', 'Info')).prefetch_related(
        'test__engagement__product',
        'test__engagement__product__prod_type',
        'test__engagement__risk_acceptance',
        'risk_acceptance_set',
        'reporter').extra(
        select={
            'ra_count': 'SELECT COUNT(*) FROM dojo_risk_acceptance INNER JOIN '
                        'dojo_risk_acceptance_accepted_findings ON '
                        '( dojo_risk_acceptance.id = dojo_risk_acceptance_accepted_findings.risk_acceptance_id ) '
                        'WHERE dojo_risk_acceptance_accepted_findings.finding_id = dojo_finding.id',
            "sql_age": 'SELECT IF(dojo_finding.mitigated IS NULL, DATEDIFF(CURDATE(), dojo_finding.date), '
                       'DATEDIFF(dojo_finding.mitigated, dojo_finding.date))'
        },
    )

    if mtype != 'All':
        pt = Product_Type.objects.filter(id=mtype)
        request.GET._mutable = True
        request.GET.appendlist('test__engagement__product__prod_type', mtype)
        request.GET._mutable = False
        mtype = pt[0].name
        show_pt_filter = False
        page_name = '%s Metrics' % mtype
        prod_type = pt
    elif 'test__engagement__product__prod_type' in request.GET:
        prod_type = Product_Type.objects.filter(id__in=request.GET.getlist('test__engagement__product__prod_type', []))
    else:
        prod_type = Product_Type.objects.all()
    findings = MetricsFindingFilter(request.GET, queryset=findings)
    active_findings = MetricsFindingFilter(request.GET, queryset=active_findings)

    findings.qs  # this is needed to load details from filter since it is lazy
    active_findings.qs  # this is needed to load details from filter since it is lazy

    start_date = findings.filters['date'].start_date
    start_date = datetime(start_date.year,
                          start_date.month, start_date.day,
                          tzinfo=localtz)
    end_date = findings.filters['date'].end_date
    end_date = datetime(end_date.year,
                        end_date.month, end_date.day,
                        tzinfo=localtz)

    if len(prod_type) > 0:
        findings_closed = Finding.objects.filter(mitigated__range=[start_date, end_date],
                                                 test__engagement__product__prod_type__in=prod_type).prefetch_related(
            'test__engagement__product')
        # capture the accepted findings in period
        accepted_findings = Finding.objects.filter(risk_acceptance__created__range=[start_date, end_date],
                                                   test__engagement__product__prod_type__in=prod_type). \
            prefetch_related('test__engagement__product')
        accepted_findings_counts = Finding.objects.filter(risk_acceptance__created__range=[start_date, end_date],
                                                          test__engagement__product__prod_type__in=prod_type). \
            prefetch_related('test__engagement__product').aggregate(
            total=Sum(
                Case(When(severity__in=('Critical', 'High', 'Medium', 'Low'),
                          then=Value(1)),
                     output_field=IntegerField())),
            critical=Sum(
                Case(When(severity='Critical',
                          then=Value(1)),
                     output_field=IntegerField())),
            high=Sum(
                Case(When(severity='High',
                          then=Value(1)),
                     output_field=IntegerField())),
            medium=Sum(
                Case(When(severity='Medium',
                          then=Value(1)),
                     output_field=IntegerField())),
            low=Sum(
                Case(When(severity='Low',
                          then=Value(1)),
                     output_field=IntegerField())),
            info=Sum(
                Case(When(severity='Info',
                          then=Value(1)),
                     output_field=IntegerField())),
        )
    else:
        findings_closed = Finding.objects.filter(mitigated__range=[start_date, end_date]).prefetch_related(
            'test__engagement__product')
        accepted_findings = Finding.objects.filter(risk_acceptance__created__range=[start_date, end_date]). \
            prefetch_related('test__engagement__product')
        accepted_findings_counts = Finding.objects.filter(risk_acceptance__created__range=[start_date, end_date]). \
            prefetch_related('test__engagement__product').aggregate(
            total=Sum(
                Case(When(severity__in=('Critical', 'High', 'Medium', 'Low'),
                          then=Value(1)),
                     output_field=IntegerField())),
            critical=Sum(
                Case(When(severity='Critical',
                          then=Value(1)),
                     output_field=IntegerField())),
            high=Sum(
                Case(When(severity='High',
                          then=Value(1)),
                     output_field=IntegerField())),
            medium=Sum(
                Case(When(severity='Medium',
                          then=Value(1)),
                     output_field=IntegerField())),
            low=Sum(
                Case(When(severity='Low',
                          then=Value(1)),
                     output_field=IntegerField())),
            info=Sum(
                Case(When(severity='Info',
                          then=Value(1)),
                     output_field=IntegerField())),
        )

    r = relativedelta(end_date, start_date)
    months_between = (r.years * 12) + r.months
    # include current month
    months_between += 1

    weeks_between = int(ceil((((r.years * 12) + r.months) * 4.33) + (r.days / 7)))
    if weeks_between <= 0:
        weeks_between += 2

    monthly_counts = get_period_counts(active_findings.qs, findings.qs, findings_closed, accepted_findings, months_between, start_date,
                                       relative_delta='months')
    weekly_counts = get_period_counts(active_findings.qs, findings.qs, findings_closed, accepted_findings, weeks_between, start_date,
                                      relative_delta='weeks')

    top_ten = Product.objects.filter(engagement__test__finding__verified=True,
                                     engagement__test__finding__false_p=False,
                                     engagement__test__finding__duplicate=False,
                                     engagement__test__finding__out_of_scope=False,
                                     engagement__test__finding__mitigated__isnull=True,
                                     engagement__test__finding__severity__in=(
                                         'Critical', 'High', 'Medium', 'Low'),
                                     prod_type__in=prod_type).annotate(
        critical=Sum(
            Case(When(engagement__test__finding__severity='Critical', then=Value(1)),
                 output_field=IntegerField())
        ),
        high=Sum(
            Case(When(engagement__test__finding__severity='High', then=Value(1)),
                 output_field=IntegerField())
        ),
        medium=Sum(
            Case(When(engagement__test__finding__severity='Medium', then=Value(1)),
                 output_field=IntegerField())
        ),
        low=Sum(
            Case(When(engagement__test__finding__severity='Low', then=Value(1)),
                 output_field=IntegerField())
        ),
        total=Sum(
            Case(When(engagement__test__finding__severity__in=(
                'Critical', 'High', 'Medium', 'Low'), then=Value(1)),
                output_field=IntegerField()))
    ).order_by('-critical', '-high', '-medium', '-low')[:10]

    age_detail = [0, 0, 0, 0]

    in_period_counts = {"Critical": 0, "High": 0, "Medium": 0,
                        "Low": 0, "Info": 0, "Total": 0}
    in_period_details = {}

    closed_in_period_counts = {"Critical": 0, "High": 0, "Medium": 0,
                               "Low": 0, "Info": 0, "Total": 0}
    closed_in_period_details = {}

    accepted_in_period_details = {}

    for finding in findings.qs:
        if 0 <= finding.sql_age <= 30:
            age_detail[0] += 1
        elif 30 < finding.sql_age <= 60:
            age_detail[1] += 1
        elif 60 < finding.sql_age <= 90:
            age_detail[2] += 1
        elif finding.sql_age > 90:
            age_detail[3] += 1

        in_period_counts[finding.severity] += 1
        in_period_counts['Total'] += 1

        if finding.test.engagement.product.name not in in_period_details:
            in_period_details[finding.test.engagement.product.name] = {
                'path': reverse('view_product_findings', args=(finding.test.engagement.product.id,)),
                'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0}
        in_period_details[
            finding.test.engagement.product.name
        ][finding.severity] += 1
        in_period_details[finding.test.engagement.product.name]['Total'] += 1

    for finding in accepted_findings:
        if finding.test.engagement.product.name not in accepted_in_period_details:
            accepted_in_period_details[finding.test.engagement.product.name] = {
                'path': reverse('accepted_findings') + '?test__engagement__product=' + str(
                    finding.test.engagement.product.id),
                'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0}
        accepted_in_period_details[
            finding.test.engagement.product.name
        ][finding.severity] += 1
        accepted_in_period_details[finding.test.engagement.product.name]['Total'] += 1

    for f in findings_closed:
        closed_in_period_counts[f.severity] += 1
        closed_in_period_counts['Total'] += 1

        if f.test.engagement.product.name not in closed_in_period_details:
            closed_in_period_details[f.test.engagement.product.name] = {
                'path': reverse('closed_findings') + '?test__engagement__product=' + str(
                    f.test.engagement.product.id),
                'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0}
        closed_in_period_details[
            f.test.engagement.product.name
        ][f.severity] += 1
        closed_in_period_details[f.test.engagement.product.name]['Total'] += 1

    punchcard = list()
    ticks = list()
    highest_count = 0

    if 'view' in request.GET and 'dashboard' == request.GET['view']:
        punchcard, ticks, highest_count = get_punchcard_data(findings.qs, weeks_between, start_date)
        page_name = (get_system_setting('team_name')) + " Metrics"
        template = 'dojo/dashboard-metrics.html'

    add_breadcrumb(title=page_name, top_level=not len(request.GET), request=request)

    return render(request, template, {
        'name': page_name,
        'start_date': start_date,
        'end_date': end_date,
        'findings': findings,
        'opened_per_month': monthly_counts['opened_per_period'],
        'active_per_month': monthly_counts['active_per_period'],
        'opened_per_week': weekly_counts['opened_per_period'],
        'accepted_per_month': monthly_counts['accepted_per_period'],
        'accepted_per_week': weekly_counts['accepted_per_period'],
        'top_ten_products': top_ten,
        'age_detail': age_detail,
        'in_period_counts': in_period_counts,
        'in_period_details': in_period_details,
        'accepted_in_period_counts': accepted_findings_counts,
        'accepted_in_period_details': accepted_in_period_details,
        'closed_in_period_counts': closed_in_period_counts,
        'closed_in_period_details': closed_in_period_details,
        'punchcard': punchcard,
        'ticks': ticks,
        'highest_count': highest_count,
        'show_pt_filter': show_pt_filter,
    })
예제 #35
0
def product_type_counts(request):
    form = ProductTypeCountsForm()
    opened_in_period_list = []
    oip = None
    cip = None
    aip = None
    all_current_in_pt = None
    top_ten = None
    pt = None
    today = datetime.now(tz=localtz)
    first_of_month = today.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    mid_month = first_of_month.replace(day=15, hour=23, minute=59, second=59, microsecond=999999)
    end_of_month = mid_month.replace(day=monthrange(today.year, today.month)[1], hour=23, minute=59, second=59,
                                     microsecond=999999)
    start_date = first_of_month
    end_date = end_of_month

    if request.method == 'GET' and 'month' in request.GET and 'year' in request.GET and 'product_type' in request.GET:
        form = ProductTypeCountsForm(request.GET)
        if form.is_valid():
            pt = form.cleaned_data['product_type']
            month = int(form.cleaned_data['month'])
            year = int(form.cleaned_data['year'])
            first_of_month = first_of_month.replace(month=month, year=year)

            month_requested = datetime(year, month, 1)

            end_of_month = month_requested.replace(day=monthrange(month_requested.year, month_requested.month)[1],
                                                   hour=23, minute=59, second=59, microsecond=999999)
            start_date = first_of_month
            start_date = datetime(start_date.year,
                                  start_date.month, start_date.day,
                                  tzinfo=localtz)
            end_date = end_of_month
            end_date = datetime(end_date.year,
                                end_date.month, end_date.day,
                                tzinfo=localtz)

            oip = opened_in_period(start_date, end_date, pt)


            # trending data - 12 months
            for x in range(12, 0, -1):
                opened_in_period_list.append(
                    opened_in_period(start_date + relativedelta(months=-x), end_of_month + relativedelta(months=-x),
                                     pt))

            opened_in_period_list.append(oip)

            closed_in_period = Finding.objects.filter(mitigated__range=[start_date, end_date],
                                                      test__engagement__product__prod_type=pt,
                                                      severity__in=('Critical', 'High', 'Medium', 'Low')).values(
                'numerical_severity').annotate(Count('numerical_severity')).order_by('numerical_severity')

            total_closed_in_period = Finding.objects.filter(mitigated__range=[start_date, end_date],
                                                            test__engagement__product__prod_type=pt,
                                                            severity__in=(
                                                                'Critical', 'High', 'Medium', 'Low')).aggregate(
                total=Sum(
                    Case(When(severity__in=('Critical', 'High', 'Medium', 'Low'),
                              then=Value(1)),
                         output_field=IntegerField())))['total']

            overall_in_pt = Finding.objects.filter(date__lt=end_date,
                                                   verified=True,
                                                   false_p=False,
                                                   duplicate=False,
                                                   out_of_scope=False,
                                                   mitigated__isnull=True,
                                                   test__engagement__product__prod_type=pt,
                                                   severity__in=('Critical', 'High', 'Medium', 'Low')).values(
                'numerical_severity').annotate(Count('numerical_severity')).order_by('numerical_severity')

            total_overall_in_pt = Finding.objects.filter(date__lte=end_date,
                                                         verified=True,
                                                         false_p=False,
                                                         duplicate=False,
                                                         out_of_scope=False,
                                                         mitigated__isnull=True,
                                                         test__engagement__product__prod_type=pt,
                                                         severity__in=('Critical', 'High', 'Medium', 'Low')).aggregate(
                total=Sum(
                    Case(When(severity__in=('Critical', 'High', 'Medium', 'Low'),
                              then=Value(1)),
                         output_field=IntegerField())))['total']

            all_current_in_pt = Finding.objects.filter(date__lte=end_date,
                                                       verified=True,
                                                       false_p=False,
                                                       duplicate=False,
                                                       out_of_scope=False,
                                                       mitigated__isnull=True,
                                                       test__engagement__product__prod_type=pt,
                                                       severity__in=(
                                                           'Critical', 'High', 'Medium', 'Low')).prefetch_related(
                'test__engagement__product',
                'test__engagement__product__prod_type',
                'test__engagement__risk_acceptance',
                'reporter').order_by(
                'numerical_severity')

            top_ten = Product.objects.filter(engagement__test__finding__date__lte=end_date,
                                             engagement__test__finding__verified=True,
                                             engagement__test__finding__false_p=False,
                                             engagement__test__finding__duplicate=False,
                                             engagement__test__finding__out_of_scope=False,
                                             engagement__test__finding__mitigated__isnull=True,
                                             engagement__test__finding__severity__in=(
                                                 'Critical', 'High', 'Medium', 'Low'),
                                             prod_type=pt).annotate(
                critical=Sum(
                    Case(When(engagement__test__finding__severity='Critical', then=Value(1)),
                         output_field=IntegerField())
                ),
                high=Sum(
                    Case(When(engagement__test__finding__severity='High', then=Value(1)),
                         output_field=IntegerField())
                ),
                medium=Sum(
                    Case(When(engagement__test__finding__severity='Medium', then=Value(1)),
                         output_field=IntegerField())
                ),
                low=Sum(
                    Case(When(engagement__test__finding__severity='Low', then=Value(1)),
                         output_field=IntegerField())
                ),
                total=Sum(
                    Case(When(engagement__test__finding__severity__in=(
                        'Critical', 'High', 'Medium', 'Low'), then=Value(1)),
                        output_field=IntegerField()))
            ).order_by('-critical', '-high', '-medium', '-low')[:10]

            cip = {'S0': 0,
                   'S1': 0,
                   'S2': 0,
                   'S3': 0,
                   'Total': total_closed_in_period}

            aip = {'S0': 0,
                   'S1': 0,
                   'S2': 0,
                   'S3': 0,
                   'Total': total_overall_in_pt}

            for o in closed_in_period:
                cip[o['numerical_severity']] = o['numerical_severity__count']

            for o in overall_in_pt:
                aip[o['numerical_severity']] = o['numerical_severity__count']
        else:
            messages.add_message(request, messages.ERROR, "Please choose month and year and the Product Type.",
                                 extra_tags='alert-danger')

    add_breadcrumb(title="Bi-Weekly Metrics", top_level=True, request=request)

    return render(request,
                  'dojo/pt_counts.html',
                  {'form': form,
                   'start_date': start_date,
                   'end_date': end_date,
                   'opened_in_period': oip,
                   'trending_opened': opened_in_period_list,
                   'closed_in_period': cip,
                   'overall_in_pt': aip,
                   'all_current_in_pt': all_current_in_pt,
                   'top_ten': top_ten,
                   'pt': pt}
                  )
예제 #36
0
def simple_metrics(request):
    now = localtz.localize(datetime.today())

    if request.method == 'POST':
        form = SimpleMetricsForm(request.POST)
        if form.is_valid():
            now = form.cleaned_data['date']
            form = SimpleMetricsForm({'date': now})
    else:
        form = SimpleMetricsForm({'date': now})

    findings_by_product_type = collections.OrderedDict()

    # for each product type find each product with open findings and
    # count the S0, S1, S2 and S3
    for pt in Product_Type.objects.order_by('name'):
        total_critical = []
        total_high = []
        total_medium = []
        total_low = []
        total_info = []
        total_closed = []
        total_opened = []
        findings_broken_out = {}

        total = Finding.objects.filter(test__engagement__product__prod_type=pt,
                                       verified=True,
                                       false_p=False,
                                       duplicate=False,
                                       out_of_scope=False,
                                       date=now,
                                       ).distinct()

        for f in total.all():
            if f.severity == "Critical":
                total_critical.append(f)
            elif f.severity == 'High':
                total_high.append(f)
            elif f.severity == 'Medium':
                total_medium.append(f)
            elif f.severity == 'Low':
                total_low.append(f)
            else:
                total_info.append(f)

            if f.mitigated and f.mitigated.year == now.year and f.mitigated.month == now.month:
                total_closed.append(f)

            if f.date.year == now.year and f.date.month == now.month:
                total_opened.append(f)

        findings_broken_out['Total'] = total.count()
        findings_broken_out['S0'] = len(total_critical)
        findings_broken_out['S1'] = len(total_high)
        findings_broken_out['S2'] = len(total_medium)
        findings_broken_out['S3'] = len(total_low)
        findings_broken_out['S4'] = len(total_info)

        findings_broken_out['Opened'] = len(total_opened)
        findings_broken_out['Closed'] = len(total_closed)

        findings_by_product_type[pt] = findings_broken_out

    add_breadcrumb(title="Simple Metrics", top_level=True, request=request)

    return render(request, 'dojo/simple_metrics.html', {
        'findings': findings_by_product_type,
        'name': 'Simple Metrics',
        'metric': True,
        'user': request.user,
        'form': form,
    })
예제 #37
0
def import_scan_results(request, eid):
    engagement = get_object_or_404(Engagement, id=eid)
    finding_count = 0
    form = ImportScanForm()
    cred_form = CredMappingForm()
    cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(engagement=engagement).order_by('cred_id')

    if request.method == "POST":
        form = ImportScanForm(request.POST, request.FILES)
        cred_form = CredMappingForm(request.POST)
        cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(engagement=engagement).order_by('cred_id')
        if form.is_valid():
            file = request.FILES['file']
            scan_date = form.cleaned_data['scan_date']
            min_sev = form.cleaned_data['minimum_severity']
            active = form.cleaned_data['active']
            verified = form.cleaned_data['verified']

            scan_type = request.POST['scan_type']
            if not any(scan_type in code for code in ImportScanForm.SCAN_TYPE_CHOICES):
                raise Http404()

            tt, t_created = Test_Type.objects.get_or_create(name=scan_type)
            # will save in development environment
            environment, env_created = Development_Environment.objects.get_or_create(name="Development")
            t = Test(engagement=engagement, test_type=tt, target_start=scan_date,
                     target_end=scan_date, environment=environment, percent_complete=100)
            t.lead = request.user
            t.full_clean()
            t.save()
            tags = request.POST.getlist('tags')
            ts = ", ".join(tags)
            t.tags = ts

            #Save the credential to the test
            if cred_form.is_valid():
                if cred_form.cleaned_data['cred_user']:
                    #Select the credential mapping object from the selected list and only allow if the credential is associated with the product
                    cred_user = Cred_Mapping.objects.filter(pk=cred_form.cleaned_data['cred_user'].id, engagement=eid).first()

                    new_f = cred_form.save(commit=False)
                    new_f.test = t
                    new_f.cred_id = cred_user.cred_id
                    new_f.save()

            try:
                parser = import_parser_factory(file, t)
            except ValueError:
                raise Http404()

            try:
                for item in parser.items:
                    sev = item.severity
                    if sev == 'Information' or sev == 'Informational':
                        sev = 'Info'

                    item.severity = sev

                    if Finding.SEVERITIES[sev] > Finding.SEVERITIES[min_sev]:
                        continue

                    item.test = t
                    item.date = t.target_start
                    item.reporter = request.user
                    item.last_reviewed = datetime.now(tz=localtz)
                    item.last_reviewed_by = request.user
                    item.active = active
                    item.verified = verified
                    item.save()

                    if hasattr(item, 'unsaved_req_resp') and len(item.unsaved_req_resp) > 0:
                        for req_resp in item.unsaved_req_resp:
                            burp_rr = BurpRawRequestResponse(finding=item,
                                                             burpRequestBase64=req_resp["req"],
                                                             burpResponseBase64=req_resp["resp"],
                                                             )
                            burp_rr.clean()
                            burp_rr.save()

                    if item.unsaved_request is not None and item.unsaved_response is not None:
                        burp_rr = BurpRawRequestResponse(finding=item,
                                                         burpRequestBase64=item.unsaved_request,
                                                         burpResponseBase64=item.unsaved_response,
                                                         )
                        burp_rr.clean()
                        burp_rr.save()

                    for endpoint in item.unsaved_endpoints:
                        ep, created = Endpoint.objects.get_or_create(protocol=endpoint.protocol,
                                                                     host=endpoint.host,
                                                                     path=endpoint.path,
                                                                     query=endpoint.query,
                                                                     fragment=endpoint.fragment,
                                                                     product=t.engagement.product)

                        item.endpoints.add(ep)

                    if item.unsaved_tags is not None:
                        item.tags = item.unsaved_tags

                    finding_count += 1

                messages.add_message(request,
                                     messages.SUCCESS,
                                     scan_type + ' processed, a total of ' + message(finding_count, 'finding',
                                                                                     'processed'),
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('view_test', args=(t.id,)))
            except SyntaxError:
                messages.add_message(request,
                                     messages.ERROR,
                                     'There appears to be an error in the XML report, please check and try again.',
                                     extra_tags='alert-danger')

    add_breadcrumb(parent=engagement, title="Import Scan Results", top_level=False, request=request)
    return render(request,
                  'dojo/import_scan_results.html',
                  {'form': form,
                   'eid': engagement.id,
                   'cred_form': cred_form,
                   })
예제 #38
0
def add_tests(request, eid):
    eng = Engagement.objects.get(id=eid)
    cred_form = CredMappingForm()
    cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(
        engagement=eng).order_by('cred_id')

    if request.method == 'POST':
        form = TestForm(request.POST, engagement=eng)
        cred_form = CredMappingForm(request.POST)
        cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(
            engagement=eng).order_by('cred_id')
        if form.is_valid():
            new_test = form.save(commit=False)
            new_test.engagement = eng
            try:
                new_test.lead = User.objects.get(id=form['lead'].value())
            except:
                new_test.lead = None
                pass

            # Set status to in progress if a test is added
            if eng.status != "In Progress" and eng.active is True:
                eng.status = "In Progress"
                eng.save()

            new_test.save()

            # Save the credential to the test
            if cred_form.is_valid():
                if cred_form.cleaned_data['cred_user']:
                    # Select the credential mapping object from the selected list and only allow if the credential is associated with the product
                    cred_user = Cred_Mapping.objects.filter(
                        pk=cred_form.cleaned_data['cred_user'].id,
                        engagement=eid).first()

                    new_f = cred_form.save(commit=False)
                    new_f.test = new_test
                    new_f.cred_id = cred_user.cred_id
                    new_f.save()

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Test added successfully.',
                                 extra_tags='alert-success')

            create_notification(
                event='test_added',
                title=new_test.test_type.name + " for " + eng.product.name,
                test=new_test,
                engagement=eng,
                url=reverse('view_engagement', args=(eng.id, )))

            if '_Add Another Test' in request.POST:
                return HttpResponseRedirect(
                    reverse('add_tests', args=(eng.id, )))
            elif '_Add Findings' in request.POST:
                return HttpResponseRedirect(
                    reverse('add_findings', args=(new_test.id, )))
            elif '_Finished' in request.POST:
                return HttpResponseRedirect(
                    reverse('view_engagement', args=(eng.id, )))
    else:
        form = TestForm(engagement=eng)
        form.initial['target_start'] = eng.target_start
        form.initial['target_end'] = eng.target_end
        form.initial['lead'] = request.user
    add_breadcrumb(parent=eng,
                   title="Add Tests",
                   top_level=False,
                   request=request)
    product_tab = Product_Tab(eng.product.id,
                              title="Add Tests",
                              tab="engagements")
    product_tab.setEngagement(eng)
    return render(
        request, 'dojo/add_tests.html', {
            'product_tab': product_tab,
            'form': form,
            'cred_form': cred_form,
            'eid': eid,
            'eng': eng
        })
예제 #39
0
def view_engagement(request, eid):
    eng = get_object_or_404(Engagement, id=eid)
    tests = (Test.objects.filter(engagement=eng).prefetch_related(
        'tags', 'test_type').annotate(
            count_findings_test_all=Count('finding__id')).annotate(
                count_findings_test_active_verified=Count(
                    'finding__id', filter=Q(finding__active=True))
            ).annotate(count_findings_test_mitigated=Count(
                'finding__id', filter=Q(finding__is_Mitigated=True))).annotate(
                    count_findings_test_dups=Count(
                        'finding__id', filter=Q(
                            finding__duplicate=True))).order_by(
                                'test_type__name', '-updated'))

    prod = eng.product
    risks_accepted = eng.risk_acceptance.all().select_related('owner')
    preset_test_type = None
    network = None
    if eng.preset:
        preset_test_type = eng.preset.test_type.all()
        network = eng.preset.network_locations.all()
    system_settings = System_Settings.objects.get()

    jissue = jira_helper.get_jira_issue(eng)
    jira_project = jira_helper.get_jira_project(eng)

    exclude_findings = [
        finding.id for ra in eng.risk_acceptance.all()
        for finding in ra.accepted_findings.all()
    ]

    eng_findings = Finding.objects.filter(test__in=eng.test_set.all()) \
        .exclude(id__in=exclude_findings).order_by('title')

    try:
        check = Check_List.objects.get(engagement=eng)
    except:
        check = None
        pass
    notes = eng.notes.all()
    note_type_activation = Note_Type.objects.filter(is_active=True).count()
    if note_type_activation:
        available_note_types = find_available_notetypes(notes)
    if request.method == 'POST' and request.user.is_staff:
        eng.progress = 'check_list'
        eng.save()

        if note_type_activation:
            form = TypedNoteForm(request.POST,
                                 available_note_types=available_note_types)
        else:
            form = NoteForm(request.POST)
        if form.is_valid():
            new_note = form.save(commit=False)
            new_note.author = request.user
            new_note.date = timezone.now()
            new_note.save()
            eng.notes.add(new_note)
            if note_type_activation:
                form = TypedNoteForm(available_note_types=available_note_types)
            else:
                form = NoteForm()
            url = request.build_absolute_uri(
                reverse("view_engagement", args=(eng.id, )))
            title = "Engagement: %s on %s" % (eng.name, eng.product.name)
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Note added successfully.',
                                 extra_tags='alert-success')
    else:
        if note_type_activation:
            form = TypedNoteForm(available_note_types=available_note_types)
        else:
            form = NoteForm()

    creds = Cred_Mapping.objects.filter(
        product=eng.product).select_related('cred_id').order_by('cred_id')
    cred_eng = Cred_Mapping.objects.filter(
        engagement=eng.id).select_related('cred_id').order_by('cred_id')

    add_breadcrumb(parent=eng, top_level=False, request=request)
    if hasattr(settings, 'ENABLE_DEDUPLICATION'):
        if settings.ENABLE_DEDUPLICATION:
            enabled = True
            findings = Finding.objects.filter(test__engagement=eng,
                                              duplicate=False)
        else:
            enabled = False
            findings = None
    else:
        enabled = False
        findings = None

    if findings is not None:
        fpage = get_page_items(request, findings, 15)
    else:
        fpage = None

    # ----------

    try:
        start_date = Finding.objects.filter(
            test__engagement__product=eng.product).order_by('date')[:1][0].date
    except:
        start_date = timezone.now()

    end_date = timezone.now()

    risk_acceptances = Risk_Acceptance.objects.filter(
        engagement__in=Engagement.objects.filter(product=eng.product))

    accepted_findings = [
        finding for ra in risk_acceptances
        for finding in ra.accepted_findings.all()
    ]

    title = ""
    if eng.engagement_type == "CI/CD":
        title = " CI/CD"
    product_tab = Product_Tab(prod.id,
                              title="View" + title + " Engagement",
                              tab="engagements")
    product_tab.setEngagement(eng)
    return render(
        request, 'dojo/view_eng.html', {
            'eng': eng,
            'product_tab': product_tab,
            'system_settings': system_settings,
            'tests': tests,
            'findings': fpage,
            'enabled': enabled,
            'check': check,
            'threat': eng.tmodel_path,
            'risk': eng.risk_path,
            'form': form,
            'notes': notes,
            'risks_accepted': risks_accepted,
            'can_add_risk': eng_findings.count(),
            'jissue': jissue,
            'jira_project': jira_project,
            'accepted_findings': accepted_findings,
            'start_date': start_date,
            'creds': creds,
            'cred_eng': cred_eng,
            'network': network,
            'preset_test_type': preset_test_type
        })
예제 #40
0
def simple_search(request):
    ip_addresses = []
    dashes = []
    query = []
    tests = None
    findings = None
    finding_templates = None
    products = None
    tagged_tests = None
    tagged_findings = None
    tagged_products = None
    tagged_endpoints = None
    tagged_engagements = None
    tagged_finding_templates = None
    engagements = None
    endpoints = None
    languages = None
    app_analysis = None
    clean_query = ''
    cookie = False
    terms = ''
    form = SimpleSearchForm()

    original_clean_query = ""
    findings_filter = None
    title_words = None
    component_words = None
    paged_generic = None

    max_results = settings.SEARCH_MAX_RESULTS

    # if request.method == 'GET' and "query" in request.GET:
    if request.method == 'GET':
        form = SimpleSearchForm(request.GET)
        if form.is_valid():
            # logger.debug('form vars: %s', vars(form))
            cookie = True
            clean_query = form.cleaned_data['query'] or ''
            search_operator, operator = "", ""
            # Check for search operator like finding:, endpoint:, test: product:
            original_clean_query = clean_query
            # print('clean_query: ', clean_query)
            if ":" in clean_query:
                operator = clean_query.split(":")
                search_operator = operator[0]
                clean_query = operator[1].lstrip()

            logger.debug('operator: %s', operator)
            logger.debug('search_operator: %s', search_operator)
            logger.debug('clean_query: %s', clean_query)

            # if the query contains hyphens, django-watson will escape these leading to problems.
            # for cve we make this workaround because we really want to be able to search for CVEs
            # problem still remains for other case, i.e. searching for "valentijn-scholten" will return no results because of the hyphen.
            # see:
            # - https://github.com/etianen/django-watson/issues/223
            # - https://github.com/DefectDojo/django-DefectDojo/issues/1092
            # - https://github.com/DefectDojo/django-DefectDojo/issues/2081

            # it's not google grade parsing, but let's do some basic stuff right
            query_parts = clean_query.split(" ")
            new_parts = ""
            for part in query_parts:
                if bool(cve_pattern.match(part)):
                    part = '\'' + part + '\''
                    clean_query = '\'' + clean_query + '\''
                    print('new part: ', part)
                else:
                    print('old part: ', part)

                new_parts += (part + " ")

            clean_query = new_parts.strip()

            # clean_query = '\'' + clean_query + '\''

            logger.debug('cve clean_query: [%s]', clean_query)

            search_tags = "tag" in search_operator or search_operator == ""
            search_findings = "finding" in search_operator or "cve" in search_operator or "id" in search_operator or search_operator == ""
            search_finding_templates = "template" in search_operator or search_operator == ""
            search_tests = "test" in search_operator or search_operator == ""
            search_engagements = "engagement" in search_operator or search_operator == ""
            search_products = "product" in search_operator or search_operator == ""
            search_endpoints = "endpoint" in search_operator or search_operator == ""
            search_languages = "language" in search_operator or search_operator == ""
            search_technologies = "technology" in search_operator or search_operator == ""

            findings = Finding.objects.all()
            tests = Test.objects.all()
            engagements = Engagement.objects.all()
            products = Product.objects.all()
            endpoints = Endpoint.objects.all()
            finding_templates = Finding_Template.objects.all()

            if not request.user.is_staff:
                findings = findings.filter(
                    Q(test__engagement__product__authorized_users__in=[
                        request.user
                    ]) |
                    Q(test__engagement__product__prod_type__authorized_users__in
                      =[request.user]))
                tests = tests.filter(
                    Q(engagement__product__authorized_users__in=[request.user])
                    | Q(engagement__product__prod_type__authorized_users__in=[
                        request.user
                    ]))
                engagements = engagements.filter(
                    Q(product__authorized_users__in=[request.user]) |
                    Q(product__prod_type__authorized_users__in=[request.user]))
                products = products.filter(
                    Q(authorized_users__in=[request.user])
                    | Q(prod_type__authorized_users__in=[request.user]))
                endpoints = endpoints.filter(
                    Q(product__authorized_users__in=[request.user]) |
                    Q(product__prod_type__authorized_users__in=[request.user]))

            # TODO better get findings in their own query and match on id. that would allow filtering on additional fields such cve, prod_id, etc.

            findings_filter = None
            title_words = None
            component_words = None

            tags = clean_query
            # search tags first to avoid errors due to slicing too early
            if search_tags:
                tagged_findings = TaggedItem.objects.get_by_model(
                    findings, tags)[:max_results]
                tagged_finding_templates = TaggedItem.objects.get_by_model(
                    Finding_Template, tags)[:max_results]
                tagged_tests = TaggedItem.objects.get_by_model(
                    tests, tags)[:max_results]
                tagged_engagements = TaggedItem.objects.get_by_model(
                    engagements, tags)[:max_results]
                tagged_products = TaggedItem.objects.get_union_by_model(
                    products, tags)[:max_results]
                tagged_endpoints = TaggedItem.objects.get_by_model(
                    endpoints, tags)[:max_results]
            else:
                tagged_findings = None
                tagged_finding_templates = None
                tagged_tests = None
                tagged_engagements = None
                tagged_products = None
                tagged_endpoints = None

            if search_findings:
                findings_filter = OpenFindingFilter(request.GET,
                                                    queryset=findings,
                                                    user=request.user,
                                                    pid=None,
                                                    prefix='finding')
                title_words = get_words_for_field(findings_filter.qs, 'title')
                component_words = get_words_for_field(findings_filter.qs,
                                                      'component_name')
                findings = findings_filter.qs

                if clean_query:
                    logger.debug('going watson with: %s', clean_query)
                    watson_results = watson.filter(findings_filter.qs,
                                                   clean_query)[:max_results]
                    findings = findings.filter(
                        id__in=[watson.id for watson in watson_results])

                # prefetch after watson to avoid inavlid query errors due to watson not understanding prefetching
                findings = prefetch_for_findings(findings)
                # some over the top tag displaying happening...
                findings = findings.prefetch_related(
                    'test__engagement__product__tagged_items__tag')

                findings = findings[:max_results]
            else:
                findings = None
                findings_filter = None
                component_words = None

                # logger.debug('%s', findings.query)
                # paged_findings = get_page_items(request, findings, 25)

                # findings = prefetch_for_findings(findings)
                # some over the top tag displaying happening...
                # findings = findings.prefetch_related('test__engagement__product__tagged_items__tag')

                # paged_findings.object_list = findings

            # for result in findings:
            #     if False:
            #         logger.debug('findings result: %s', vars(result))

            if search_finding_templates:
                watson_results = watson.filter(finding_templates, clean_query)
                finding_templates = finding_templates.filter(
                    id__in=[watson.id for watson in watson_results])
                finding_templates = finding_templates[:max_results]
            else:
                finding_templates = None

            if search_tests:
                watson_results = watson.filter(tests, clean_query)
                tests = tests.filter(
                    id__in=[watson.id for watson in watson_results])
                tests = tests.prefetch_related(
                    'engagement', 'engagement__product', 'test_type',
                    'tagged_items__tag', 'engagement__tagged_items__tag',
                    'engagement__product__tagged_items__tag')
                tests = tests[:max_results]
            else:
                tests = None

            if search_engagements:
                watson_results = watson.filter(engagements, clean_query)
                engagements = engagements.filter(
                    id__in=[watson.id for watson in watson_results])
                engagements = engagements.prefetch_related(
                    'product', 'product__tagged_items__tag',
                    'tagged_items__tag')
                engagements = engagements[:max_results]
            else:
                engagements = None

            if search_products:
                watson_results = watson.filter(products, clean_query)
                products = products.filter(
                    id__in=[watson.id for watson in watson_results])
                products = products.prefetch_related('tagged_items__tag')
                products = products[:max_results]
            else:
                products = None

            if search_endpoints:
                endpoints = endpoints.filter(
                    Q(host__icontains=clean_query)
                    | Q(path__icontains=clean_query)
                    | Q(fqdn__icontains=clean_query)
                    | Q(protocol__icontains=clean_query))
                endpoints = endpoints.prefetch_related(
                    'product', 'tagged_items__tag',
                    'product__tagged_items__tag')
                endpoints = endpoints[:max_results]
            else:
                endpoints = None

            if search_languages:
                languages = Languages.objects.filter(
                    language__language__icontains=clean_query)
                languages = languages.prefetch_related(
                    'product', 'product__tagged_items__tag')
                languages = languages[:max_results]
            else:
                languages = None

            if search_technologies:
                app_analysis = App_Analysis.objects.filter(
                    name__icontains=clean_query)
                app_analysis = app_analysis[:max_results]
            else:
                app_analysis = None

            # generic = watson.search(clean_query, models=(Finding,)).prefetch_related('object')
            generic = watson.search(clean_query).prefetch_related(
                'object')[:max_results]

            # paging doesn't work well with django_watson
            # paged_generic = get_page_items(request, generic, 25)

            # generic = get_page_items(request, generic, 25)
            # generic = watson.search(original_clean_query)[:50].prefetch_related('object')
            # generic = watson.search("qander document 'CVE-2019-8331'")[:10].prefetch_related('object')
            # generic = watson.search("'CVE-2020-6754'")[:10].prefetch_related('object')
            # generic = watson.search(" 'ISEC-433'")[:10].prefetch_related('object')

            # for result in generic:
            #     if False:
            #         logger.debug('generic result: %s', vars(result))

        else:
            logger.debug('search form invalid')
            logger.debug(form.errors)
            form = SimpleSearchForm()

        add_breadcrumb(title="Simple Search", top_level=True, request=request)

        activetab = 'findings' if findings \
            else 'products' if products \
                else 'engagements' if engagements else \
                    'tests' if tests else \
                         'endpoint' if endpoints else \
                            'generic' if generic else \
                                'tagged'

    response = render(
        request, 'dojo/simple_search.html', {
            'clean_query': original_clean_query,
            'languages': languages,
            'app_analysis': app_analysis,
            'tests': tests,
            'findings': findings,
            'finding_templates': finding_templates,
            'filtered': findings_filter,
            'title_words': title_words,
            'component_words': component_words,
            'products': products,
            'tagged_tests': tagged_tests,
            'tagged_findings': tagged_findings,
            'tagged_finding_templates': tagged_finding_templates,
            'tagged_products': tagged_products,
            'tagged_endpoints': tagged_endpoints,
            'tagged_engagements': tagged_engagements,
            'engagements': engagements,
            'endpoints': endpoints,
            'name': 'Simple Search',
            'metric': False,
            'user': request.user,
            'form': form,
            'activetab': activetab,
            'show_product_column': True,
            'generic': generic
        })

    if cookie:
        response.set_cookie("highlight",
                            value=clean_query,
                            max_age=None,
                            expires=None,
                            path='/',
                            secure=True,
                            httponly=False)
    else:
        response.delete_cookie("highlight", path='/')
    return response
예제 #41
0
def view_engagement(request, eid):
    eng = Engagement.objects.get(id=eid)
    tests = Test.objects.filter(engagement=eng)
    risks_accepted = eng.risk_acceptance.all()
    try:
        jissue = JIRA_Issue.objects.get(engagement=eng)
    except:
        jissue = None
        pass
    try:
        jconf = JIRA_PKey.objects.get(product=eng.product).conf
    except:
        jconf = None
        pass
    exclude_findings = [finding.id for ra in eng.risk_acceptance.all()
                        for finding in ra.accepted_findings.all()]
    eng_findings = Finding.objects.filter(test__in=eng.test_set.all()) \
        .exclude(id__in=exclude_findings).order_by('title')

    try:
        check = Check_List.objects.get(engagement=eng)
    except:
        check = None
        pass
    form = DoneForm()
    if request.method == 'POST':
        eng.progress = 'check_list'
        eng.save()

    creds = Cred_Mapping.objects.filter(product=eng.product).select_related('cred_id').order_by('cred_id')
    cred_eng = Cred_Mapping.objects.filter(engagement=eng.id).select_related('cred_id').order_by('cred_id')

    add_breadcrumb(parent=eng, top_level=False, request=request)
    if hasattr(settings, 'ENABLE_DEDUPLICATION'):
        if settings.ENABLE_DEDUPLICATION:
            enabled = True
            findings = Finding.objects.filter(test__engagement=eng, duplicate=False)
        else:
            enabled = False
            findings = None
    else:
        enabled = False
        findings = None

    if findings is not None:
        fpage = get_page_items(request, findings, 15)
    else:
        fpage = None

    # ----------

    try:
        start_date = Finding.objects.filter(test__engagement__product=eng.product).order_by('date')[:1][0].date
    except:
        start_date = localtz.localize(datetime.today())

    end_date = localtz.localize(datetime.today())

    risk_acceptances = Risk_Acceptance.objects.filter(engagement__in=Engagement.objects.filter(product=eng.product))

    accepted_findings = [finding for ra in risk_acceptances
                         for finding in ra.accepted_findings.all()]

    week_date = end_date - timedelta(days=7)  # seven days and /newer are considered "new"

    new_verified_findings = Finding.objects.filter(test__engagement__product=eng.product,
                                                   date__range=[week_date, end_date],
                                                   false_p=False,
                                                   verified=True,
                                                   duplicate=False,
                                                   out_of_scope=False).order_by("date")

    open_findings = Finding.objects.filter(test__engagement__product=eng.product,
                                           date__range=[start_date, end_date],
                                           false_p=False,
                                           verified=True,
                                           duplicate=False,
                                           out_of_scope=False,
                                           active=True,
                                           mitigated__isnull=True)

    closed_findings = Finding.objects.filter(test__engagement__product=eng.product,
                                             date__range=[start_date, end_date],
                                             false_p=False,
                                             verified=True,
                                             duplicate=False,
                                             out_of_scope=False,
                                             mitigated__isnull=False)

    return render(request, 'dojo/view_eng.html',
                  {'eng': eng, 'tests': tests,
                   'findings': fpage, 'enabled': enabled,
                   'check': check, 'threat': eng.tmodel_path,
                   'risk': eng.risk_path, 'form': form,
                   'risks_accepted': risks_accepted,
                   'can_add_risk': len(eng_findings),
                   'jissue': jissue, 'jconf': jconf,
                   'open_findings': open_findings,
                   'closed_findings': closed_findings,
                   'accepted_findings': accepted_findings,
                   'new_findings': new_verified_findings,
                   'start_date': start_date,
                   'creds': creds,
                   'cred_eng': cred_eng
                   })
예제 #42
0
def view_risk(request, eid, raid):
    risk_approval = get_object_or_404(Risk_Acceptance, pk=raid)
    eng = get_object_or_404(Engagement, pk=eid)
    if (request.user.is_staff or
                request.user in eng.product.authorized_users.all()):
        pass
    else:
        raise PermissionDenied

    a_file = risk_approval.path

    if request.method == 'POST':
        note_form = NoteForm(request.POST)
        if note_form.is_valid():
            new_note = note_form.save(commit=False)
            new_note.author = request.user
            new_note.date = datetime.now(tz=localtz)
            new_note.save()
            risk_approval.notes.add(new_note)
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Note added successfully.',
                                 extra_tags='alert-success')

        if 'delete_note' in request.POST:
            note = get_object_or_404(Notes, pk=request.POST['delete_note_id'])
            if note.author.username == request.user.username:
                risk_approval.notes.remove(note)
                note.delete()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Note deleted successfully.',
                                     extra_tags='alert-success')
            else:
                messages.add_message(
                    request,
                    messages.ERROR,
                    "Since you are not the note's author, it was not deleted.",
                    extra_tags='alert-danger')

        if 'remove_finding' in request.POST:
            finding = get_object_or_404(Finding,
                                        pk=request.POST['remove_finding_id'])
            risk_approval.accepted_findings.remove(finding)
            finding.active = True
            finding.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Finding removed successfully.',
                                 extra_tags='alert-success')
        if 'replace_file' in request.POST:
            replace_form = ReplaceRiskAcceptanceForm(
                request.POST,
                request.FILES,
                instance=risk_approval)
            if replace_form.is_valid():
                risk_approval.path.delete(save=False)
                risk_approval.path = replace_form.cleaned_data['path']
                risk_approval.save()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'File replaced successfully.',
                                     extra_tags='alert-success')
        if 'add_findings' in request.POST:
            add_findings_form = AddFindingsRiskAcceptanceForm(
                request.POST,
                request.FILES,
                instance=risk_approval)
            if add_findings_form.is_valid():
                findings = add_findings_form.cleaned_data[
                    'accepted_findings']
                for finding in findings:
                    finding.active = False
                    finding.save()
                    risk_approval.accepted_findings.add(finding)
                risk_approval.save()
                messages.add_message(
                    request,
                    messages.SUCCESS,
                    'Finding%s added successfully.' % ('s'
                                                       if len(findings) > 1 else ''),
                    extra_tags='alert-success')

    note_form = NoteForm()
    replace_form = ReplaceRiskAcceptanceForm()
    add_findings_form = AddFindingsRiskAcceptanceForm()
    exclude_findings = [finding.id for ra in eng.risk_acceptance.all()
                        for finding in ra.accepted_findings.all()]
    findings = Finding.objects.filter(test__in=eng.test_set.all()) \
        .exclude(id__in=exclude_findings).order_by("title")

    add_fpage = get_page_items(request, findings, 10, 'apage')
    add_findings_form.fields[
        "accepted_findings"].queryset = add_fpage.object_list

    fpage = get_page_items(request, risk_approval.accepted_findings.order_by(
        'numerical_severity'), 15)

    authorized = (request.user == risk_approval.reporter.username
                  or request.user.is_staff)

    add_breadcrumb(parent=risk_approval, top_level=False, request=request)

    return render(request, 'dojo/view_risk.html',
                  {'risk_approval': risk_approval,
                   'accepted_findings': fpage,
                   'notes': risk_approval.notes.all(),
                   'a_file': a_file,
                   'eng': eng,
                   'note_form': note_form,
                   'replace_form': replace_form,
                   'add_findings_form': add_findings_form,
                   'show_add_findings_form': len(findings),
                   'request': request,
                   'add_findings': add_fpage,
                   'authorized': authorized,
                   })
예제 #43
0
def edit_finding(request, fid):
    finding = get_object_or_404(Finding, id=fid)
    old_status = finding.status()
    form = FindingForm(instance=finding)
    form.initial['tags'] = [tag.name for tag in finding.tags]
    form_error = False
    jform = None
    try:
        jissue = JIRA_Issue.objects.get(finding=finding)
        enabled = True
    except:
        enabled = False
    pass
    if hasattr(settings, 'ENABLE_JIRA'):
        if settings.ENABLE_JIRA:
            if JIRA_PKey.objects.filter(
                    product=finding.test.engagement.product) != 0:
                jform = JIRAFindingForm(enabled=enabled, prefix='jiraform')
    if request.method == 'POST':
        form = FindingForm(request.POST, instance=finding)
        if form.is_valid():
            new_finding = form.save(commit=False)
            new_finding.test = finding.test
            new_finding.numerical_severity = Finding.get_numerical_severity(
                new_finding.severity)
            if new_finding.false_p or new_finding.active is False:
                new_finding.mitigated = datetime.now(tz=localtz)
                new_finding.mitigated_by = request.user
            if new_finding.active is True:
                new_finding.false_p = False
                new_finding.mitigated = None
                new_finding.mitigated_by = None

            create_template = new_finding.is_template
            # always false now since this will be deprecated soon in favor of new Finding_Template model
            new_finding.is_template = False
            new_finding.endpoints = form.cleaned_data['endpoints']
            new_finding.last_reviewed = datetime.now(tz=localtz)
            new_finding.last_reviewed_by = request.user
            tags = request.POST.getlist('tags')
            t = ", ".join(tags)
            new_finding.tags = t
            new_finding.save()
            if 'jiraform-push_to_jira' in request.POST:
                jform = JIRAFindingForm(request.POST,
                                        prefix='jiraform',
                                        enabled=enabled)
                if jform.is_valid():
                    try:
                        jissue = JIRA_Issue.objects.get(finding=new_finding)
                        update_issue_task.delay(
                            new_finding, old_status,
                            jform.cleaned_data.get('push_to_jira'))
                    except:
                        add_issue_task.delay(
                            new_finding,
                            jform.cleaned_data.get('push_to_jira'))
                        pass
            tags = request.POST.getlist('tags')
            t = ", ".join(tags)
            new_finding.tags = t

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Finding saved successfully.',
                                 extra_tags='alert-success')
            if create_template:
                templates = Finding_Template.objects.filter(
                    title=new_finding.title)
                if len(templates) > 0:
                    messages.add_message(
                        request,
                        messages.ERROR,
                        'A finding template was not created.  A template with this title already '
                        'exists.',
                        extra_tags='alert-danger')
                else:
                    template = Finding_Template(
                        title=new_finding.title,
                        cwe=new_finding.cwe,
                        severity=new_finding.severity,
                        description=new_finding.description,
                        mitigation=new_finding.mitigation,
                        impact=new_finding.impact,
                        references=new_finding.references,
                        numerical_severity=new_finding.numerical_severity)
                    template.save()
                    messages.add_message(
                        request,
                        messages.SUCCESS,
                        'A finding template was also created.',
                        extra_tags='alert-success')
            return HttpResponseRedirect(
                reverse('view_finding', args=(new_finding.id, )))
        else:
            messages.add_message(
                request,
                messages.ERROR,
                'There appears to be errors on the form, please correct below.',
                extra_tags='alert-danger')
            form_error = True

    if form_error and 'endpoints' in form.cleaned_data:
        form.fields['endpoints'].queryset = form.cleaned_data['endpoints']
    else:
        form.fields['endpoints'].queryset = finding.endpoints.all()
    form.initial['tags'] = [tag.name for tag in finding.tags]
    add_breadcrumb(parent=finding,
                   title="Edit",
                   top_level=False,
                   request=request)
    return render(request, 'dojo/edit_findings.html', {
        'form': form,
        'finding': finding,
        'jform': jform
    })
예제 #44
0
def edit_user(request, uid):
    user = get_object_or_404(Dojo_User, id=uid)
    authed_products = Product.objects.filter(authorized_users__in=[user])
    authed_product_types = Product_Type.objects.filter(authorized_users__in=[user])
    form = AddDojoUserForm(instance=user, initial={
        'authorized_products': authed_products,
        'authorized_product_types': authed_product_types
    })
    if not request.user.is_superuser:
        form.fields['is_staff'].widget.attrs['disabled'] = True
        form.fields['is_superuser'].widget.attrs['disabled'] = True
        form.fields['is_active'].widget.attrs['disabled'] = True

    user_contact = user.usercontactinfo if hasattr(user, 'usercontactinfo') else None

    if user_contact is None:
        contact_form = UserContactInfoForm()
    else:
        contact_form = UserContactInfoForm(instance=user_contact)

    if request.method == 'POST':
        form = AddDojoUserForm(request.POST, instance=user)
        if user_contact is None:
            contact_form = UserContactInfoForm(request.POST)
        else:
            contact_form = UserContactInfoForm(request.POST, instance=user_contact)

        if form.is_valid() and contact_form.is_valid():
            form.save()
            for init_auth_prods in authed_products:
                init_auth_prods.authorized_users.remove(user)
                init_auth_prods.save()
            for init_auth_prod_types in authed_product_types:
                init_auth_prod_types.authorized_users.remove(user)
                init_auth_prod_types.save()
            if 'authorized_products' in form.cleaned_data and len(form.cleaned_data['authorized_products']) > 0:
                for p in form.cleaned_data['authorized_products']:
                    p.authorized_users.add(user)
                    p.save()
            if 'authorized_product_types' in form.cleaned_data and len(form.cleaned_data['authorized_product_types']) > 0:
                for pt in form.cleaned_data['authorized_product_types']:
                    pt.authorized_users.add(user)
                    pt.save()
            contact = contact_form.save(commit=False)
            contact.user = user
            contact.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'User saved successfully.',
                                 extra_tags='alert-success')
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'User was not saved successfully.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Edit User", top_level=False, request=request)
    return render(request, "dojo/add_user.html", {
        'name': 'Edit User',
        'form': form,
        'contact_form': contact_form,
        'to_edit': user})
예제 #45
0
def view_finding(request, fid):
    finding = get_object_or_404(Finding, id=fid)

    user = request.user
    try:
        jissue = JIRA_Issue.objects.get(finding=finding)
    except:
        jissue = None
        pass
    try:
        jpkey = JIRA_PKey.objects.get(product=finding.test.engagement.product)
        jconf = jpkey.conf
    except:
        jconf = None
        pass
    dojo_user = get_object_or_404(Dojo_User, id=user.id)
    if user.is_staff or user in finding.test.engagement.product.authorized_users.all(
    ):
        pass  # user is authorized for this product
    else:
        raise PermissionDenied

    notes = finding.notes.all()

    if request.method == 'POST':
        form = NoteForm(request.POST)
        if form.is_valid():
            new_note = form.save(commit=False)
            new_note.author = request.user
            new_note.date = datetime.now(tz=localtz)
            new_note.save()
            finding.notes.add(new_note)
            finding.last_reviewed = new_note.date
            finding.last_reviewed_by = user
            finding.save()
            if jissue is not None:
                add_comment_task(finding, new_note)
            form = NoteForm()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Note saved.',
                                 extra_tags='alert-success')
    else:
        form = NoteForm()

    try:
        reqres = BurpRawRequestResponse.objects.get(finding=finding)
        burp_request = base64.b64decode(reqres.burpRequestBase64)
        burp_response = base64.b64decode(reqres.burpResponseBase64)
    except:
        reqres = None
        burp_request = None
        burp_response = None

    add_breadcrumb(parent=finding, top_level=False, request=request)
    return render(
        request, 'dojo/view_finding.html', {
            'finding': finding,
            'burp_request': burp_request,
            'jissue': jissue,
            'jconf': jconf,
            'burp_response': burp_response,
            'dojo_user': dojo_user,
            'user': user,
            'notes': notes,
            'form': form
        })
예제 #46
0
def promote_to_finding(request, fid):
    finding = get_object_or_404(Stub_Finding, id=fid)
    test = finding.test
    form_error = False
    jira_available = False
    if hasattr(settings, 'ENABLE_JIRA'):
        if settings.ENABLE_JIRA:
            if JIRA_PKey.objects.filter(product=test.engagement.product) != 0:
                jform = JIRAFindingForm(
                    request.POST,
                    prefix='jiraform',
                    enabled=JIRA_PKey.objects.get(
                        product=test.engagement.product).push_all_issues)
                jira_available = True
    else:
        jform = None
    form = PromoteFindingForm(
        initial={
            'title': finding.title,
            'date': finding.date,
            'severity': finding.severity,
            'description': finding.description,
            'test': finding.test,
            'reporter': finding.reporter
        })
    if request.method == 'POST':
        form = PromoteFindingForm(request.POST)
        if form.is_valid():
            new_finding = form.save(commit=False)
            new_finding.test = test
            new_finding.reporter = request.user
            new_finding.numerical_severity = Finding.get_numerical_severity(
                new_finding.severity)

            new_finding.active = True
            new_finding.false_p = False
            new_finding.duplicate = False
            new_finding.mitigated = None
            new_finding.verified = True
            new_finding.out_of_scope = False

            new_finding.save()
            new_finding.endpoints = form.cleaned_data['endpoints']
            new_finding.save()

            finding.delete()
            if 'jiraform' in request.POST:
                jform = JIRAFindingForm(
                    request.POST,
                    prefix='jiraform',
                    enabled=JIRA_PKey.objects.get(
                        product=test.engagement.product).push_all_issues)
                if jform.is_valid():
                    add_issue_task.delay(
                        new_finding, jform.cleaned_data.get('push_to_jira'))

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Finding promoted successfully.',
                                 extra_tags='alert-success')

            return HttpResponseRedirect(reverse('view_test', args=(test.id, )))
        else:
            if 'endpoints' in form.cleaned_data:
                form.fields['endpoints'].queryset = form.cleaned_data[
                    'endpoints']
            else:
                form.fields['endpoints'].queryset = Endpoint.objects.none()
            form_error = True
            messages.add_message(
                request,
                messages.ERROR,
                'The form has errors, please correct them below.',
                extra_tags='alert-danger')
    add_breadcrumb(parent=test,
                   title="Promote Finding",
                   top_level=False,
                   request=request)
    return render(
        request, 'dojo/promote_to_finding.html', {
            'form': form,
            'test': test,
            'stub_finding': finding,
            'form_error': form_error,
        })
예제 #47
0
def system_settings(request):
    system_settings_obj = System_Settings.objects.get(no_cache=True)
    """
    **** To be Finished JIRA Status info ****
    jira_bool = True
    jira_msg = 'None'
    if not celery_bool:
        jira_bool = False
        jira_msg = 'Celery is not working properly'
    else:

        try:
            jira_server = jform.cleaned_data.get('url').rstrip('/')
            jira = JIRA(server=jform.cleaned_data.get('url').rstrip('/'),
                        basic_auth=(jform.cleaned_data.get('username'), jform.cleaned_data.get('password')))
            new_j = jform.save(commit=False)
            new_j.url = jira_server
            new_j.save()
            messages.add_message(request,
                                 messages.SUCCESS,

                                 'JIRA Configuration Successfully Created.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('jira', ))
        except:
            messages.add_message(request,
                                 messages.ERROR,
                                 'Unable to authenticate. Please check the URL, username, and password.',
                                 extra_tags='alert-danger')

    """
    form = SystemSettingsForm(instance=system_settings_obj)
    if request.method == 'POST':
        form = SystemSettingsForm(request.POST, instance=system_settings_obj)
        if form.is_valid():
            new_settings = form.save()
            enable_disable_auditlog(enable=new_settings.enable_auditlog)
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Settings saved.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('system_settings', ))
    else:
        # Celery needs to be set with the setting: CELERY_RESULT_BACKEND = 'db+sqlite:///dojo.celeryresults.sqlite'
        if hasattr(settings, 'CELERY_RESULT_BACKEND'):
            # Check the status of Celery by sending calling a celery task
            celery_bool = get_celery_worker_status()

            if celery_bool:
                celery_msg = "Celery is processing tasks."
                celery_status = "Running"
            else:
                celery_msg = "Celery does not appear to be up and running. Please ensure celery is running."
                celery_status = "Not Running"
        else:
            celery_bool = False
            celery_msg = "Celery needs to have the setting CELERY_RESULT_BACKEND = 'db+sqlite:///dojo.celeryresults.sqlite' set in settings.py."
            celery_status = "Unkown"

    add_breadcrumb(title="Application settings",
                   top_level=False,
                   request=request)
    return render(
        request, 'dojo/system_settings.html', {
            'form': form,
            'celery_bool': celery_bool,
            'celery_msg': celery_msg,
            'celery_status': celery_status
        })
예제 #48
0
def view_product_metrics(request, pid):
    prod = get_object_or_404(Product, id=pid)
    engs = Engagement.objects.filter(product=prod, active=True)

    result = EngagementFilter(
        request.GET,
        queryset=Engagement.objects.filter(product=prod, active=False).order_by('-target_end'))

    i_engs_page = get_page_items(request, result.qs, 10)

    scan_sets = ScanSettings.objects.filter(product=prod)
    auth = request.user.is_staff or request.user in prod.authorized_users.all()

    if not auth:
        # will render 403
        raise PermissionDenied

    ct = ContentType.objects.get_for_model(prod)
    product_cf = CustomField.objects.filter(content_type=ct)
    product_metadata = {}

    for cf in product_cf:
        cfv = CustomFieldValue.objects.filter(field=cf, object_id=prod.id)
        if len(cfv):
            product_metadata[cf.name] = cfv[0].value

    try:
        start_date = Finding.objects.filter(test__engagement__product=prod).order_by('date')[:1][0].date
    except:
        start_date = timezone.now()

    end_date = timezone.now()

    tests = Test.objects.filter(engagement__product=prod)

    risk_acceptances = Risk_Acceptance.objects.filter(engagement__in=Engagement.objects.filter(product=prod))

    accepted_findings = [finding for ra in risk_acceptances
                         for finding in ra.accepted_findings.all()]

    verified_findings = Finding.objects.filter(test__engagement__product=prod,
                                               date__range=[start_date, end_date],
                                               false_p=False,
                                               verified=True,
                                               duplicate=False,
                                               out_of_scope=False).order_by("date")

    week_date = end_date - timedelta(days=7)  # seven days and /newnewer are considered "new"

    new_verified_findings = Finding.objects.filter(test__engagement__product=prod,
                                                   date__range=[week_date, end_date],
                                                   false_p=False,
                                                   verified=True,
                                                   duplicate=False,
                                                   out_of_scope=False).order_by("date")

    open_findings = Finding.objects.filter(test__engagement__product=prod,
                                           date__range=[start_date, end_date],
                                           false_p=False,
                                           verified=True,
                                           duplicate=False,
                                           out_of_scope=False,
                                           active=True,
                                           mitigated__isnull=True)

    closed_findings = Finding.objects.filter(test__engagement__product=prod,
                                             date__range=[start_date, end_date],
                                             false_p=False,
                                             verified=True,
                                             duplicate=False,
                                             out_of_scope=False,
                                             mitigated__isnull=False)

    open_vulnerabilities = Finding.objects.filter(
        test__engagement__product=prod,
        false_p=False,
        verified=True,
        duplicate=False,
        out_of_scope=False,
        active=True,
        mitigated__isnull=True,
    ).order_by('cwe').values(
        'cwe'
    ).annotate(
        count=Count('cwe')
    )

    all_vulnerabilities = Finding.objects.filter(
        test__engagement__product=prod,
        duplicate=False,
    ).order_by('cwe').values(
        'cwe'
    ).annotate(
        count=Count('cwe')
    )

    start_date = timezone.make_aware(datetime.combine(start_date, datetime.min.time()))

    r = relativedelta(end_date, start_date)
    weeks_between = int(ceil((((r.years * 12) + r.months) * 4.33) + (r.days / 7)))
    if weeks_between <= 0:
        weeks_between += 2

    punchcard, ticks, highest_count = get_punchcard_data(verified_findings, weeks_between, start_date)
    add_breadcrumb(parent=prod, top_level=False, request=request)

    open_close_weekly = OrderedDict()
    new_weekly = OrderedDict()
    severity_weekly = OrderedDict()
    critical_weekly = OrderedDict()
    high_weekly = OrderedDict()
    medium_weekly = OrderedDict()

    for v in verified_findings:
        iso_cal = v.date.isocalendar()
        x = iso_to_gregorian(iso_cal[0], iso_cal[1], 1)
        y = x.strftime("<span class='small'>%m/%d<br/>%Y</span>")
        x = (tcalendar.timegm(x.timetuple()) * 1000)
        if x not in critical_weekly:
            critical_weekly[x] = {'count': 0, 'week': y}
        if x not in high_weekly:
            high_weekly[x] = {'count': 0, 'week': y}
        if x not in medium_weekly:
            medium_weekly[x] = {'count': 0, 'week': y}

        if x in open_close_weekly:
            if v.mitigated:
                open_close_weekly[x]['closed'] += 1
            else:
                open_close_weekly[x]['open'] += 1
        else:

            if v.mitigated:
                open_close_weekly[x] = {'closed': 1, 'open': 0, 'accepted': 0}
            else:
                open_close_weekly[x] = {'closed': 0, 'open': 1, 'accepted': 0}
            open_close_weekly[x]['week'] = y

        if x in severity_weekly:
            if v.severity in severity_weekly[x]:
                severity_weekly[x][v.severity] += 1
            else:
                severity_weekly[x][v.severity] = 1
        else:
            severity_weekly[x] = {'Critical': 0, 'High': 0,
                                  'Medium': 0, 'Low': 0, 'Info': 0}
            severity_weekly[x][v.severity] = 1
            severity_weekly[x]['week'] = y

        if v.severity == 'Critical':
            if x in critical_weekly:
                critical_weekly[x]['count'] += 1
            else:
                critical_weekly[x] = {'count': 1, 'week': y}
        elif v.severity == 'High':
            if x in high_weekly:
                high_weekly[x]['count'] += 1
            else:
                high_weekly[x] = {'count': 1, 'week': y}
        elif v.severity == 'Medium':
            if x in medium_weekly:
                medium_weekly[x]['count'] += 1
            else:
                medium_weekly[x] = {'count': 1, 'week': y}

    for a in accepted_findings:
        iso_cal = a.date.isocalendar()
        x = iso_to_gregorian(iso_cal[0], iso_cal[1], 1)
        y = x.strftime("<span class='small'>%m/%d<br/>%Y</span>")
        x = (tcalendar.timegm(x.timetuple()) * 1000)

        if x in open_close_weekly:
            open_close_weekly[x]['accepted'] += 1
        else:
            open_close_weekly[x] = {'closed': 0, 'open': 0, 'accepted': 1}
            open_close_weekly[x]['week'] = y

    test_data = {}
    for t in tests:
        if t.test_type.name in test_data:
            test_data[t.test_type.name] += t.verified_finding_count()
        else:
            test_data[t.test_type.name] = t.verified_finding_count()

    product_tab = Product_Tab(pid, title="Product", tab="metrics")
    return render(request,
                  'dojo/product_metrics.html',
                  {'prod': prod,
                   'product_tab': product_tab,
                   'product_metadata': product_metadata,
                   'engs': engs,
                   'i_engs': i_engs_page,
                   'scan_sets': scan_sets,
                   'verified_findings': verified_findings,
                   'open_findings': open_findings,
                   'closed_findings': closed_findings,
                   'accepted_findings': accepted_findings,
                   'new_findings': new_verified_findings,
                   'open_vulnerabilities': open_vulnerabilities,
                   'all_vulnerabilities': all_vulnerabilities,
                   'start_date': start_date,
                   'punchcard': punchcard,
                   'ticks': ticks,
                   'highest_count': highest_count,
                   'open_close_weekly': open_close_weekly,
                   'severity_weekly': severity_weekly,
                   'critical_weekly': critical_weekly,
                   'high_weekly': high_weekly,
                   'medium_weekly': medium_weekly,
                   'test_data': test_data,
                   'user': request.user,
                   'authorized': auth})
예제 #49
0
def product_endpoint_report(request, pid):
    user = Dojo_User.objects.get(id=request.user.id)
    product = get_object_or_404(Product.objects.all().prefetch_related(
        'engagement_set__test_set__test_type',
        'engagement_set__test_set__environment'),
                                id=pid)
    endpoint_ids = Endpoint.objects.filter(
        product=product,
        finding__active=True,
        finding__verified=True,
        finding__false_p=False,
        finding__duplicate=False,
        finding__out_of_scope=False,
    ).values_list('id', flat=True)

    endpoints = prefetch_related_endpoints_for_report(
        Endpoint.objects.filter(id__in=endpoint_ids))
    endpoints = EndpointReportFilter(request.GET, queryset=endpoints)

    paged_endpoints = get_page_items(request, endpoints.qs, 25)
    report_format = request.GET.get('report_type', 'AsciiDoc')
    include_finding_notes = int(request.GET.get('include_finding_notes', 0))
    include_finding_images = int(request.GET.get('include_finding_images', 0))
    include_executive_summary = int(
        request.GET.get('include_executive_summary', 0))
    include_table_of_contents = int(
        request.GET.get('include_table_of_contents', 0))
    include_disclaimer = int(request.GET.get('include_disclaimer', 0))
    disclaimer = get_system_setting('disclaimer')
    if include_disclaimer and len(disclaimer) == 0:
        disclaimer = 'Please configure in System Settings.'
    generate = "_generate" in request.GET
    add_breadcrumb(parent=product,
                   title="Vulnerable Product Endpoints Report",
                   top_level=False,
                   request=request)
    report_form = ReportOptionsForm()

    template = "dojo/product_endpoint_pdf_report.html"
    report_name = "Product Endpoint Report: " + str(product)
    report_title = "Product Endpoint Report"
    report_subtitle = str(product)
    report_info = "Generated By %s on %s" % (user.get_full_name(), (
        timezone.now().strftime("%m/%d/%Y %I:%M%p %Z")))

    try:
        start_date = Finding.objects.filter(
            endpoints__in=endpoints.qs).order_by('date')[:1][0].date
    except:
        start_date = timezone.now()

    end_date = timezone.now()

    risk_acceptances = Risk_Acceptance.objects.filter(
        engagement__test__finding__endpoints__in=endpoints.qs)

    accepted_findings = [
        finding for ra in risk_acceptances
        for finding in ra.accepted_findings.filter(endpoints__in=endpoints.qs)
    ]

    verified_findings = Finding.objects.filter(
        endpoints__in=endpoints.qs,
        date__range=[start_date, end_date],
        false_p=False,
        verified=True,
        duplicate=False,
        out_of_scope=False)

    open_findings = Finding.objects.filter(endpoints__in=endpoints.qs,
                                           false_p=False,
                                           verified=True,
                                           duplicate=False,
                                           out_of_scope=False,
                                           active=True,
                                           mitigated__isnull=True)

    closed_findings = Finding.objects.filter(endpoints__in=endpoints.qs,
                                             false_p=False,
                                             verified=True,
                                             duplicate=False,
                                             out_of_scope=False,
                                             mitigated__isnull=False)
    if generate:
        report_form = ReportOptionsForm(request.GET)
        if report_format == 'AsciiDoc':
            return render(
                request, 'dojo/asciidoc_report.html', {
                    'product_type': None,
                    'product': product,
                    'accepted_findings': accepted_findings,
                    'open_findings': open_findings,
                    'closed_findings': closed_findings,
                    'verified_findings': verified_findings,
                    'engagement': None,
                    'test': None,
                    'endpoints': endpoints,
                    'endpoint': None,
                    'findings': None,
                    'include_finding_notes': include_finding_notes,
                    'include_finding_images': include_finding_images,
                    'include_executive_summary': include_executive_summary,
                    'include_table_of_contents': include_table_of_contents,
                    'include_disclaimer': include_disclaimer,
                    'disclaimer': disclaimer,
                    'user': request.user,
                    'title': 'Generate Report',
                })
        elif report_format == 'HTML':
            return render(
                request, template, {
                    'product_type': None,
                    'product': product,
                    'engagement': None,
                    'test': None,
                    'endpoint': None,
                    'endpoints': endpoints.qs,
                    'findings': None,
                    'include_finding_notes': include_finding_notes,
                    'include_finding_images': include_finding_images,
                    'include_executive_summary': include_executive_summary,
                    'include_table_of_contents': include_table_of_contents,
                    'include_disclaimer': include_disclaimer,
                    'disclaimer': disclaimer,
                    'user': request.user,
                    'title': 'Generate Report',
                })
        else:
            raise Http404()

    product_tab = Product_Tab(product.id,
                              "Product Endpoint Report",
                              tab="endpoints")
    return render(
        request, 'dojo/request_endpoint_report.html', {
            "endpoints": paged_endpoints,
            "filtered": endpoints,
            "product_tab": product_tab,
            'report_form': report_form,
            "name": "Vulnerable Product Endpoints",
        })
예제 #50
0
def view_engagement(request, eid):
    eng = get_object_or_404(Engagement, id=eid)
    tests = Test.objects.filter(engagement=eng).prefetch_related(
        'tagged_items__tag', 'test_type').order_by('test_type__name',
                                                   '-updated')
    prod = eng.product
    auth = request.user.is_staff or request.user in prod.authorized_users.all()
    risks_accepted = eng.risk_acceptance.all().select_related('owner')
    preset_test_type = None
    network = None
    if eng.preset:
        preset_test_type = eng.preset.test_type.all()
        network = eng.preset.network_locations.all()
    system_settings = System_Settings.objects.get()
    if not auth:
        # will render 403
        raise PermissionDenied

    try:
        jissue = JIRA_Issue.objects.get(engagement=eng)
    except:
        jissue = None
        pass
    try:
        jconf = JIRA_PKey.objects.get(product=eng.product).conf
    except:
        jconf = None
        pass
    exclude_findings = [
        finding.id for ra in eng.risk_acceptance.all()
        for finding in ra.accepted_findings.all()
    ]
    eng_findings = Finding.objects.filter(test__in=eng.test_set.all()) \
        .exclude(id__in=exclude_findings).order_by('title')

    try:
        check = Check_List.objects.get(engagement=eng)
    except:
        check = None
        pass
    form = DoneForm()
    if request.method == 'POST' and request.user.is_staff:
        eng.progress = 'check_list'
        eng.save()

    creds = Cred_Mapping.objects.filter(
        product=eng.product).select_related('cred_id').order_by('cred_id')
    cred_eng = Cred_Mapping.objects.filter(
        engagement=eng.id).select_related('cred_id').order_by('cred_id')

    add_breadcrumb(parent=eng, top_level=False, request=request)
    if hasattr(settings, 'ENABLE_DEDUPLICATION'):
        if settings.ENABLE_DEDUPLICATION:
            enabled = True
            findings = Finding.objects.filter(test__engagement=eng,
                                              duplicate=False)
        else:
            enabled = False
            findings = None
    else:
        enabled = False
        findings = None

    if findings is not None:
        fpage = get_page_items(request, findings, 15)
    else:
        fpage = None

    # ----------

    try:
        start_date = Finding.objects.filter(
            test__engagement__product=eng.product).order_by('date')[:1][0].date
    except:
        start_date = timezone.now()

    end_date = timezone.now()

    risk_acceptances = Risk_Acceptance.objects.filter(
        engagement__in=Engagement.objects.filter(product=eng.product))

    accepted_findings = [
        finding for ra in risk_acceptances
        for finding in ra.accepted_findings.all()
    ]

    title = ""
    if eng.engagement_type == "CI/CD":
        title = " CI/CD"
    product_tab = Product_Tab(prod.id,
                              title="View" + title + " Engagement",
                              tab="engagements")
    product_tab.setEngagement(eng)
    return render(
        request, 'dojo/view_eng.html', {
            'eng': eng,
            'product_tab': product_tab,
            'system_settings': system_settings,
            'tests': tests,
            'findings': fpage,
            'enabled': enabled,
            'check': check,
            'threat': eng.tmodel_path,
            'risk': eng.risk_path,
            'form': form,
            'risks_accepted': risks_accepted,
            'can_add_risk': eng_findings.count(),
            'jissue': jissue,
            'jconf': jconf,
            'accepted_findings': accepted_findings,
            'start_date': start_date,
            'creds': creds,
            'cred_eng': cred_eng,
            'network': network,
            'preset_test_type': preset_test_type
        })
예제 #51
0
def add_tests(request, eid):
    eng = Engagement.objects.get(id=eid)
    cred_form = CredMappingForm()
    cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(
        engagement=eng).order_by('cred_id')

    if request.method == 'POST':
        form = TestForm(request.POST)
        cred_form = CredMappingForm(request.POST)
        cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(
            engagement=eng).order_by('cred_id')
        if form.is_valid():
            new_test = form.save(commit=False)
            new_test.engagement = eng
            try:
                new_test.lead = User.objects.get(id=form['lead'].value())
            except:
                new_test.lead = None
                pass
            new_test.save()
            tags = request.POST.getlist('tags')
            t = ", ".join(tags)
            new_test.tags = t

            #Save the credential to the test
            if cred_form.is_valid():
                if cred_form.cleaned_data['cred_user']:
                    #Select the credential mapping object from the selected list and only allow if the credential is associated with the product
                    cred_user = Cred_Mapping.objects.filter(
                        pk=cred_form.cleaned_data['cred_user'].id,
                        engagement=eid).first()

                    new_f = cred_form.save(commit=False)
                    new_f.test = new_test
                    new_f.cred_id = cred_user.cred_id
                    new_f.save()

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Test added successfully.',
                                 extra_tags='alert-success')

            create_notification(event='test_added',
                                title='Test added',
                                test=new_test,
                                engagement=eng,
                                url=request.build_absolute_uri(
                                    reverse('view_engagement',
                                            args=(eng.id, ))))

            if '_Add Another Test' in request.POST:
                return HttpResponseRedirect(
                    reverse('add_tests', args=(eng.id, )))
            elif '_Add Findings' in request.POST:
                return HttpResponseRedirect(
                    reverse('add_findings', args=(new_test.id, )))
            elif '_Finished' in request.POST:
                return HttpResponseRedirect(
                    reverse('view_engagement', args=(eng.id, )))
    else:
        form = TestForm()
        form.initial['target_start'] = eng.target_start
        form.initial['target_end'] = eng.target_end
    add_breadcrumb(parent=eng,
                   title="Add Tests",
                   top_level=False,
                   request=request)
    return render(request, 'dojo/add_tests.html', {
        'form': form,
        'cred_form': cred_form,
        'eid': eid
    })
예제 #52
0
def generate_report(request, obj, host_view=False):
    user = Dojo_User.objects.get(id=request.user.id)
    product_type = None
    product = None
    engagement = None
    test = None
    endpoint = None
    endpoints = None
    accepted_findings = None
    open_findings = None
    closed_findings = None
    verified_findings = None
    report_title = None
    report_subtitle = None
    report_info = "Generated By %s on %s" % (user.get_full_name(), (
        timezone.now().strftime("%m/%d/%Y %I:%M%p %Z")))

    if type(obj).__name__ == "Product_Type":
        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, obj,
                                       Permissions.Product_Type_View)
        else:
            if not (request.user.is_staff
                    or check_auth_users_list(request.user, obj)):
                raise PermissionDenied
    elif type(obj).__name__ == "Product":
        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, obj,
                                       Permissions.Product_View)
        else:
            if not (request.user.is_staff
                    or check_auth_users_list(request.user, obj)):
                raise PermissionDenied
    elif type(obj).__name__ == "Engagement":
        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, obj,
                                       Permissions.Engagement_View)
        else:
            if not (request.user.is_staff
                    or check_auth_users_list(request.user, obj)):
                raise PermissionDenied
    elif type(obj).__name__ == "Test":
        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, obj,
                                       Permissions.Test_View)
        else:
            if not (request.user.is_staff
                    or check_auth_users_list(request.user, obj)):
                raise PermissionDenied
    elif type(obj).__name__ == "Endpoint":
        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, obj,
                                       Permissions.Endpoint_View)
        else:
            if not (request.user.is_staff
                    or check_auth_users_list(request.user, obj)):
                raise PermissionDenied
    elif type(obj).__name__ == "QuerySet" or type(
            obj).__name__ == "CastTaggedQuerySet":
        # authorization taken care of by only selecting findings from product user is authed to see
        pass
    else:
        if not request.user.is_staff:
            raise PermissionDenied

    report_format = request.GET.get('report_type', 'AsciiDoc')
    include_finding_notes = int(request.GET.get('include_finding_notes', 0))
    include_finding_images = int(request.GET.get('include_finding_images', 0))
    include_executive_summary = int(
        request.GET.get('include_executive_summary', 0))
    include_table_of_contents = int(
        request.GET.get('include_table_of_contents', 0))
    include_disclaimer = int(request.GET.get('include_disclaimer', 0))
    disclaimer = get_system_setting('disclaimer')
    if include_disclaimer and len(disclaimer) == 0:
        disclaimer = 'Please configure in System Settings.'
    generate = "_generate" in request.GET
    report_name = str(obj)
    report_type = type(obj).__name__
    add_breadcrumb(title="Generate Report", top_level=False, request=request)
    if type(obj).__name__ == "Product_Type":
        product_type = obj
        template = "dojo/product_type_pdf_report.html"
        report_name = "Product Type Report: " + str(product_type)
        report_title = "Product Type Report"
        report_subtitle = str(product_type)

        findings = ReportFindingFilter(
            request.GET,
            prod_type=product_type,
            queryset=prefetch_related_findings_for_report(
                Finding.objects.filter(
                    test__engagement__product__prod_type=product_type)))
        products = Product.objects.filter(
            prod_type=product_type,
            engagement__test__finding__in=findings.qs).distinct()
        engagements = Engagement.objects.filter(
            product__prod_type=product_type,
            test__finding__in=findings.qs).distinct()
        tests = Test.objects.filter(
            engagement__product__prod_type=product_type,
            finding__in=findings.qs).distinct()
        if len(findings.qs) > 0:
            start_date = timezone.make_aware(
                datetime.combine(findings.qs.last().date, datetime.min.time()))
        else:
            start_date = timezone.now()

        end_date = timezone.now()

        r = relativedelta(end_date, start_date)
        months_between = (r.years * 12) + r.months
        # include current month
        months_between += 1

        endpoint_monthly_counts = get_period_counts_legacy(
            findings.qs.order_by('numerical_severity'),
            findings.qs.order_by('numerical_severity'),
            None,
            months_between,
            start_date,
            relative_delta='months')

        context = {
            'product_type':
            product_type,
            'products':
            products,
            'engagements':
            engagements,
            'tests':
            tests,
            'report_name':
            report_name,
            'endpoint_opened_per_month':
            endpoint_monthly_counts['opened_per_period']
            if endpoint_monthly_counts is not None else [],
            'endpoint_active_findings':
            findings.qs.distinct().order_by('numerical_severity'),
            'findings':
            findings.qs.distinct().order_by('numerical_severity'),
            'include_finding_notes':
            include_finding_notes,
            'include_finding_images':
            include_finding_images,
            'include_executive_summary':
            include_executive_summary,
            'include_table_of_contents':
            include_table_of_contents,
            'include_disclaimer':
            include_disclaimer,
            'disclaimer':
            disclaimer,
            'user':
            user,
            'team_name':
            settings.TEAM_NAME,
            'title':
            report_title,
            'host':
            report_url_resolver(request),
            'user_id':
            request.user.id
        }

    elif type(obj).__name__ == "Product":
        product = obj
        template = "dojo/product_pdf_report.html"
        report_name = "Product Report: " + str(product)
        report_title = "Product Report"
        report_subtitle = str(product)
        findings = ReportFindingFilter(
            request.GET,
            product=product,
            queryset=prefetch_related_findings_for_report(
                Finding.objects.filter(test__engagement__product=product)))
        ids = set(finding.id for finding in findings.qs)
        engagements = Engagement.objects.filter(
            test__finding__id__in=ids).distinct()
        tests = Test.objects.filter(finding__id__in=ids).distinct()
        endpoints = Endpoint.objects.filter(product=product).distinct()
        context = {
            'product': product,
            'engagements': engagements,
            'tests': tests,
            'report_name': report_name,
            'findings': findings.qs.distinct().order_by('numerical_severity'),
            'include_finding_notes': include_finding_notes,
            'include_finding_images': include_finding_images,
            'include_executive_summary': include_executive_summary,
            'include_table_of_contents': include_table_of_contents,
            'include_disclaimer': include_disclaimer,
            'disclaimer': disclaimer,
            'user': user,
            'team_name': settings.TEAM_NAME,
            'title': report_title,
            'endpoints': endpoints,
            'host': report_url_resolver(request),
            'user_id': request.user.id
        }

    elif type(obj).__name__ == "Engagement":
        logger.debug('generating report for Engagement')
        engagement = obj
        findings = ReportFindingFilter(
            request.GET,
            engagement=engagement,
            queryset=prefetch_related_findings_for_report(
                Finding.objects.filter(test__engagement=engagement)))
        report_name = "Engagement Report: " + str(engagement)
        template = 'dojo/engagement_pdf_report.html'
        report_title = "Engagement Report"
        report_subtitle = str(engagement)

        ids = set(finding.id for finding in findings.qs)
        tests = Test.objects.filter(finding__id__in=ids).distinct()
        endpoints = Endpoint.objects.filter(
            product=engagement.product).distinct()

        context = {
            'engagement': engagement,
            'tests': tests,
            'report_name': report_name,
            'findings': findings.qs.distinct().order_by('numerical_severity'),
            'include_finding_notes': include_finding_notes,
            'include_finding_images': include_finding_images,
            'include_executive_summary': include_executive_summary,
            'include_table_of_contents': include_table_of_contents,
            'include_disclaimer': include_disclaimer,
            'disclaimer': disclaimer,
            'user': user,
            'team_name': settings.TEAM_NAME,
            'title': report_title,
            'host': report_url_resolver(request),
            'user_id': request.user.id,
            'endpoints': endpoints
        }

    elif type(obj).__name__ == "Test":
        test = obj
        findings = ReportFindingFilter(
            request.GET,
            engagement=test.engagement,
            queryset=prefetch_related_findings_for_report(
                Finding.objects.filter(test=test)))
        template = "dojo/test_pdf_report.html"
        report_name = "Test Report: " + str(test)
        report_title = "Test Report"
        report_subtitle = str(test)

        context = {
            'test': test,
            'report_name': report_name,
            'findings': findings.qs.distinct().order_by('numerical_severity'),
            'include_finding_notes': include_finding_notes,
            'include_finding_images': include_finding_images,
            'include_executive_summary': include_executive_summary,
            'include_table_of_contents': include_table_of_contents,
            'include_disclaimer': include_disclaimer,
            'disclaimer': disclaimer,
            'user': user,
            'team_name': settings.TEAM_NAME,
            'title': report_title,
            'host': report_url_resolver(request),
            'user_id': request.user.id
        }

    elif type(obj).__name__ == "Endpoint":
        endpoint = obj
        if host_view:
            report_name = "Endpoint Host Report: " + endpoint.host
            endpoints = Endpoint.objects.filter(
                host=endpoint.host, product=endpoint.product).distinct()
            report_title = "Endpoint Host Report"
            report_subtitle = endpoint.host
        else:
            report_name = "Endpoint Report: " + str(endpoint)
            endpoints = Endpoint.objects.filter(pk=endpoint.id).distinct()
            report_title = "Endpoint Report"
            report_subtitle = str(endpoint)
        report_type = "Endpoint"
        template = 'dojo/endpoint_pdf_report.html'
        findings = ReportFindingFilter(
            request.GET,
            queryset=prefetch_related_findings_for_report(
                Finding.objects.filter(endpoints__in=endpoints)))

        context = {
            'endpoint': endpoint,
            'endpoints': endpoints,
            'report_name': report_name,
            'findings': findings.qs.distinct().order_by('numerical_severity'),
            'include_finding_notes': include_finding_notes,
            'include_finding_images': include_finding_images,
            'include_executive_summary': include_executive_summary,
            'include_table_of_contents': include_table_of_contents,
            'include_disclaimer': include_disclaimer,
            'disclaimer': disclaimer,
            'user': user,
            'team_name': get_system_setting('team_name'),
            'title': report_title,
            'host': report_url_resolver(request),
            'user_id': request.user.id
        }
    elif type(obj).__name__ == "QuerySet" or type(
            obj).__name__ == "CastTaggedQuerySet":
        findings = ReportFindingFilter(
            request.GET,
            queryset=prefetch_related_findings_for_report(obj).distinct())
        report_name = 'Finding'
        report_type = 'Finding'
        template = 'dojo/finding_pdf_report.html'
        report_title = "Finding Report"
        report_subtitle = ''

        context = {
            'findings': findings.qs.distinct().order_by('numerical_severity'),
            'report_name': report_name,
            'include_finding_notes': include_finding_notes,
            'include_finding_images': include_finding_images,
            'include_executive_summary': include_executive_summary,
            'include_table_of_contents': include_table_of_contents,
            'include_disclaimer': include_disclaimer,
            'disclaimer': disclaimer,
            'user': user,
            'team_name': settings.TEAM_NAME,
            'title': report_title,
            'host': report_url_resolver(request),
            'user_id': request.user.id
        }
    else:
        raise Http404()

    report_form = ReportOptionsForm()

    if generate:
        report_form = ReportOptionsForm(request.GET)
        if report_format == 'AsciiDoc':
            return render(
                request, 'dojo/asciidoc_report.html', {
                    'product_type':
                    product_type,
                    'product':
                    product,
                    'engagement':
                    engagement,
                    'test':
                    test,
                    'endpoint':
                    endpoint,
                    'findings':
                    findings.qs.distinct().order_by('numerical_severity'),
                    'include_finding_notes':
                    include_finding_notes,
                    'include_finding_images':
                    include_finding_images,
                    'include_executive_summary':
                    include_executive_summary,
                    'include_table_of_contents':
                    include_table_of_contents,
                    'include_disclaimer':
                    include_disclaimer,
                    'disclaimer':
                    disclaimer,
                    'user':
                    user,
                    'team_name':
                    settings.TEAM_NAME,
                    'title':
                    report_title,
                    'user_id':
                    request.user.id,
                    'host':
                    report_url_resolver(request),
                    'host_view':
                    host_view,
                    'context':
                    context,
                })
        elif report_format == 'HTML':
            return render(
                request, template, {
                    'product_type':
                    product_type,
                    'product':
                    product,
                    'engagement':
                    engagement,
                    'report_name':
                    report_name,
                    'test':
                    test,
                    'endpoint':
                    endpoint,
                    'endpoints':
                    endpoints,
                    'findings':
                    findings.qs.distinct().order_by('numerical_severity'),
                    'include_finding_notes':
                    include_finding_notes,
                    'include_finding_images':
                    include_finding_images,
                    'include_executive_summary':
                    include_executive_summary,
                    'include_table_of_contents':
                    include_table_of_contents,
                    'include_disclaimer':
                    include_disclaimer,
                    'disclaimer':
                    disclaimer,
                    'user':
                    user,
                    'team_name':
                    settings.TEAM_NAME,
                    'title':
                    report_title,
                    'user_id':
                    request.user.id,
                    'host':
                    "",
                    'host_view':
                    host_view,
                    'context':
                    context,
                })

        else:
            raise Http404()
    paged_findings = get_page_items(
        request,
        findings.qs.distinct().order_by('numerical_severity'), 25)

    product_tab = None
    if engagement:
        product_tab = Product_Tab(engagement.product.id,
                                  title="Engagement Report",
                                  tab="engagements")
        product_tab.setEngagement(engagement)
    elif test:
        product_tab = Product_Tab(test.engagement.product.id,
                                  title="Test Report",
                                  tab="engagements")
        product_tab.setEngagement(test.engagement)
    elif product:
        product_tab = Product_Tab(product.id,
                                  title="Product Report",
                                  tab="findings")
    elif endpoints:
        if host_view:
            product_tab = Product_Tab(endpoint.product.id,
                                      title="Endpoint Host Report",
                                      tab="endpoints")
        else:
            product_tab = Product_Tab(endpoint.product.id,
                                      title="Endpoint Report",
                                      tab="endpoints")

    return render(
        request, 'dojo/request_report.html', {
            'product_type': product_type,
            'product': product,
            'product_tab': product_tab,
            'engagement': engagement,
            'test': test,
            'endpoint': endpoint,
            'findings': findings,
            'paged_findings': paged_findings,
            'report_form': report_form,
            'host_view': host_view,
            'context': context,
        })
예제 #53
0
def cred(request):
    confs = Cred_User.objects.all().order_by('name', 'environment', 'username')
    add_breadcrumb(title="Credential Manager", top_level=True, request=request)
    return render(request, 'dojo/view_cred.html', {
        'confs': confs,
    })
예제 #54
0
def research_metrics(request):
    now = timezone.now()
    findings = Finding.objects.filter(
        test__test_type__name='Security Research')
    findings = findings.filter(date__year=now.year, date__month=now.month)
    verified_month = findings.filter(verified=True)
    month_all_by_product, month_all_aggregate = count_findings(findings)
    month_verified_by_product, month_verified_aggregate = count_findings(
        verified_month)

    end_of_week = now + relativedelta(weekday=6, hour=23, minute=59, second=59)
    day_list = [
        end_of_week -
        relativedelta(weeks=1, weekday=x, hour=0, minute=0, second=0)
        for x in range(end_of_week.weekday())
    ]
    q_objects = (Q(date=d) for d in day_list)
    week_findings = Finding.objects.filter(reduce(operator.or_, q_objects))
    open_week = week_findings.exclude(mitigated__isnull=False)
    verified_week = week_findings.filter(verified=True)
    week_all_by_product, week_all_aggregate = count_findings(week_findings)
    week_verified_by_product, week_verified_aggregate = count_findings(
        verified_week)
    week_remaining_by_product, week_remaining_aggregate = count_findings(
        open_week)

    remaining_by_product, remaining_aggregate = count_findings(
        Finding.objects.filter(mitigated__isnull=True,
                               test__test_type__name='Security Research'))

    closed_findings = Finding.objects.filter(
        mitigated__isnull=False, test__test_type__name='Security Research')
    closed_findings_dict = {
        'S0': closed_findings.filter(severity='Critical'),
        'S1': closed_findings.filter(severity='High'),
        'S2': closed_findings.filter(severity='Medium'),
        'S3': closed_findings.filter(severity='Low')
    }

    time_to_close = {}
    for sev, finds in list(closed_findings_dict.items()):
        total = 0
        for f in finds:
            total += (datetime.date(f.mitigated) - f.date).days
        if finds.count() != 0:
            time_to_close[sev] = total / finds.count()
        else:
            time_to_close[sev] = 'N/A'

    add_breadcrumb(title="Security Research Metrics",
                   top_level=True,
                   request=request)

    return render(
        request, 'dojo/research_metrics.html', {
            'user': request.user,
            'month_all_by_product': month_all_by_product,
            'month_verified_by_product': month_verified_by_product,
            'remaining_by_product': remaining_by_product,
            'remaining_aggregate': remaining_aggregate,
            'time_to_close': time_to_close,
        })
예제 #55
0
def metrics(request, mtype):
    template = 'dojo/metrics.html'
    show_pt_filter = True
    view = identify_view(request)
    page_name = 'Product Type Metrics by '

    age_detail = [0, 0, 0, 0]
    in_period_counts = {
        "Critical": 0,
        "High": 0,
        "Medium": 0,
        "Low": 0,
        "Info": 0,
        "Total": 0
    }
    in_period_details = {}
    closed_in_period_counts = {
        "Critical": 0,
        "High": 0,
        "Medium": 0,
        "Low": 0,
        "Info": 0,
        "Total": 0
    }
    closed_in_period_details = {}
    accepted_in_period_details = {}

    if mtype != 'All':
        pt = Product_Type.objects.filter(id=mtype)
        request.GET._mutable = True
        request.GET.appendlist('test__engagement__product__prod_type', mtype)
        request.GET._mutable = False
        mtype = pt[0].name
        show_pt_filter = False
        page_name = '%s Metrics' % mtype
        prod_type = pt
    elif 'test__engagement__product__prod_type' in request.GET:
        prod_type = Product_Type.objects.filter(id__in=request.GET.getlist(
            'test__engagement__product__prod_type', []))
    else:
        prod_type = Product_Type.objects.all()

    filters = dict()
    if view == 'Finding':
        page_name += 'Findings'
        filters = finding_querys(prod_type, request)
    elif view == 'Endpoint':
        page_name += 'Affected Endpoints'
        filters = endpoint_querys(prod_type, request)

    for obj in queryset_check(filters['all']):
        if view == 'Endpoint':
            obj = obj.finding

        if 0 <= obj.age <= 30:
            age_detail[0] += 1
        elif 30 < obj.age <= 60:
            age_detail[1] += 1
        elif 60 < obj.age <= 90:
            age_detail[2] += 1
        elif obj.age > 90:
            age_detail[3] += 1

        in_period_counts[obj.severity] += 1
        in_period_counts['Total'] += 1

        if obj.test.engagement.product.name not in in_period_details:
            in_period_details[obj.test.engagement.product.name] = {
                'path':
                reverse('product_open_findings',
                        args=(obj.test.engagement.product.id, )),
                'Critical':
                0,
                'High':
                0,
                'Medium':
                0,
                'Low':
                0,
                'Info':
                0,
                'Total':
                0
            }
        in_period_details[obj.test.engagement.product.name][obj.severity] += 1
        in_period_details[obj.test.engagement.product.name]['Total'] += 1

    for obj in filters['accepted']:
        if view == 'Endpoint':
            obj = finding.finding

        if obj.test.engagement.product.name not in accepted_in_period_details:
            accepted_in_period_details[obj.test.engagement.product.name] = {
                'path':
                reverse('accepted_findings') + '?test__engagement__product=' +
                str(obj.test.engagement.product.id),
                'Critical':
                0,
                'High':
                0,
                'Medium':
                0,
                'Low':
                0,
                'Info':
                0,
                'Total':
                0
            }
        accepted_in_period_details[obj.test.engagement.product.name][
            obj.severity] += 1
        accepted_in_period_details[
            obj.test.engagement.product.name]['Total'] += 1

    for obj in filters['closed']:
        if view == 'Endpoint':
            obj = obj.finding
        closed_in_period_counts[obj.severity] += 1
        closed_in_period_counts['Total'] += 1

        if obj.test.engagement.product.name not in closed_in_period_details:
            closed_in_period_details[obj.test.engagement.product.name] = {
                'path':
                reverse('closed_findings') + '?test__engagement__product=' +
                str(obj.test.engagement.product.id),
                'Critical':
                0,
                'High':
                0,
                'Medium':
                0,
                'Low':
                0,
                'Info':
                0,
                'Total':
                0
            }
        closed_in_period_details[obj.test.engagement.product.name][
            obj.severity] += 1
        closed_in_period_details[
            obj.test.engagement.product.name]['Total'] += 1

    punchcard = list()
    ticks = list()
    monthly_counts = filters['monthly_counts']
    weekly_counts = filters['weekly_counts']

    if 'view' in request.GET and 'dashboard' == request.GET['view']:
        punchcard, ticks = get_punchcard_data(queryset_check(filters['all']),
                                              filters['start_date'],
                                              filters['weeks_between'], view)
        page_name = (get_system_setting('team_name')) + " Metrics"
        template = 'dojo/dashboard-metrics.html'

    add_breadcrumb(title=page_name,
                   top_level=not len(request.GET),
                   request=request)

    return render(
        request, template, {
            'name': page_name,
            'start_date': filters['start_date'],
            'end_date': filters['end_date'],
            'findings': filters['all'],
            'opened_per_month': monthly_counts['opened_per_period'],
            'active_per_month': monthly_counts['active_per_period'],
            'opened_per_week': weekly_counts['opened_per_period'],
            'accepted_per_month': monthly_counts['accepted_per_period'],
            'accepted_per_week': weekly_counts['accepted_per_period'],
            'top_ten_products': filters['top_ten'],
            'age_detail': age_detail,
            'in_period_counts': in_period_counts,
            'in_period_details': in_period_details,
            'accepted_in_period_counts': filters['accepted_count'],
            'accepted_in_period_details': accepted_in_period_details,
            'closed_in_period_counts': closed_in_period_counts,
            'closed_in_period_details': closed_in_period_details,
            'punchcard': punchcard,
            'ticks': ticks,
            'show_pt_filter': show_pt_filter,
        })
예제 #56
0
def delete_cred_controller(request, destination_url, id, ttid):
    cred = None
    try:
        cred = Cred_Mapping.objects.get(pk=ttid)
    except:
        pass
    if request.method == 'POST':
        tform = CredMappingForm(request.POST, instance=cred)
        message = ""
        status_tag = ""
        delete_cred = False

        # Determine if the credential can be deleted
        if destination_url == "cred":
            if cred is None:
                delete_cred = True
            else:
                cred_lookup = Cred_Mapping.objects.filter(
                    cred_id=cred.cred_id).exclude(product__isnull=True)
                message = "Credential is associated with product(s). Remove the credential from the product(s) before this credential can be deleted."
                if cred_lookup.exists() is False:
                    delete_cred = True
        elif destination_url == "all_cred_product":
            cred_lookup = Cred_Mapping.objects.filter(
                cred_id=cred.cred_id).exclude(engagement__isnull=True)
            message = "Credential is associated with engagement(s). Remove the credential from the engagement(s) before this credential can be deleted."
            if cred_lookup.exists() is False:
                delete_cred = True
        elif destination_url == "view_engagement":
            cred_lookup = Cred_Mapping.objects.filter(
                cred_id=cred.cred_id).exclude(test__isnull=True)
            message = "Credential is associated with test(s). Remove the test(s) before this credential can be deleted."
            if cred_lookup.exists() is False:
                cred_lookup = Cred_Mapping.objects.filter(
                    cred_id=cred.cred_id).exclude(finding__isnull=True)
                message = "Credential is associated with finding(s). Remove the finding(s) before this credential can be deleted."
                if cred_lookup.exists() is False:
                    delete_cred = True
            else:
                if cred_lookup.exists() is False:
                    delete_cred = True
        elif destination_url == "view_test" or destination_url == "view_finding":
            delete_cred = True

        # Allow deletion if no credentials are associated
        if delete_cred is True:
            message = "Credential Successfully Deleted."
            status_tag = "alert-success"
            # check if main cred delete
            if destination_url == "cred":
                cred = Cred_User.objects.get(pk=ttid)
                cred.delete()
            else:
                cred.delete()
        else:
            status_tag = 'alert-danger'

        messages.add_message(request,
                             messages.SUCCESS,
                             message,
                             extra_tags=status_tag)

        if destination_url == "cred":
            return HttpResponseRedirect(reverse(destination_url))
        else:
            return HttpResponseRedirect(reverse(destination_url, args=(id, )))
    else:
        tform = CredMappingForm(instance=cred)

    add_breadcrumb(title="Delete Credential", top_level=False, request=request)
    product_tab = None
    if id:
        product_tab = Product_Tab(id,
                                  title="Delete Credential Mapping",
                                  tab="settings")
    return render(request, 'dojo/delete_cred_all.html', {
        'tform': tform,
        'product_tab': product_tab
    })
예제 #57
0
def product_endpoint_report(request, pid):
    user = Dojo_User.objects.get(id=request.user.id)
    product = get_object_or_404(Product, id=pid)
    endpoints = Endpoint.objects.filter(product=product,
                                        finding__active=True,
                                        finding__verified=True,
                                        finding__false_p=False,
                                        finding__duplicate=False,
                                        finding__out_of_scope=False,
                                        )

    ids = get_endpoint_ids(endpoints)

    endpoints = Endpoint.objects.filter(id__in=ids)

    if request.user.is_staff or request.user in product.authorized_users.all():
        pass  # user is authorized for this product
    else:
        raise PermissionDenied

    endpoints = EndpointReportFilter(request.GET, queryset=endpoints)

    paged_endpoints = get_page_items(request, endpoints, 25)
    report_format = request.GET.get('report_type', 'AsciiDoc')
    include_finding_notes = int(request.GET.get('include_finding_notes', 0))
    include_executive_summary = int(request.GET.get('include_executive_summary', 0))
    include_table_of_contents = int(request.GET.get('include_table_of_contents', 0))
    generate = "_generate" in request.GET
    add_breadcrumb(parent=product, title="Vulnerable Product Endpoints Report", top_level=False, request=request)
    report_form = ReportOptionsForm()

    filename = "product_endpoint_report.pdf"
    template = "dojo/product_endpoint_pdf_report.html"
    report_name = "Product Endpoint Report: " + str(product)
    report_title = "Product Endpoint Report"
    report_subtitle = str(product)
    report_info = "Generated By %s on %s" % (
        user.get_full_name(), (datetime.now(tz=localtz).strftime("%m/%d/%Y %I:%M%p %Z")))

    try:
        start_date = Finding.objects.filter(endpoints__in=endpoints.qs).order_by('date')[:1][0].date
    except:
        start_date = localtz.localize(datetime.today())

    end_date = localtz.localize(datetime.today())

    risk_acceptances = Risk_Acceptance.objects.filter(engagement__test__finding__endpoints__in=endpoints.qs)

    accepted_findings = [finding for ra in risk_acceptances
                         for finding in ra.accepted_findings.filter(endpoints__in=endpoints.qs)]

    verified_findings = Finding.objects.filter(endpoints__in=endpoints.qs,
                                               date__range=[start_date, end_date],
                                               false_p=False,
                                               verified=True,
                                               duplicate=False,
                                               out_of_scope=False)

    open_findings = Finding.objects.filter(endpoints__in=endpoints.qs,
                                           false_p=False,
                                           verified=True,
                                           duplicate=False,
                                           out_of_scope=False,
                                           active=True,
                                           mitigated__isnull=True)

    closed_findings = Finding.objects.filter(endpoints__in=endpoints.qs,
                                             false_p=False,
                                             verified=True,
                                             duplicate=False,
                                             out_of_scope=False,
                                             mitigated__isnull=False)
    if generate:
        report_form = ReportOptionsForm(request.GET)
        if report_format == 'AsciiDoc':
            return render(request,
                          'dojo/asciidoc_report.html',
                          {'product_type': None,
                           'product': product,
                           'accepted_findings': accepted_findings,
                           'open_findings': open_findings,
                           'closed_findings': closed_findings,
                           'verified_findings': verified_findings,
                           'engagement': None,
                           'test': None,
                           'endpoints': endpoints,
                           'endpoint': None,
                           'findings': None,
                           'include_finding_notes': include_finding_notes,
                           'include_executive_summary': include_executive_summary,
                           'include_table_of_contents': include_table_of_contents,
                           'user': request.user,
                           'title': 'Generate Report',
                           })
        elif report_format == 'PDF':
            endpoints = endpoints.qs.order_by('finding__numerical_severity')
            # lets create the report object and send it in to celery task
            if 'regen' in request.GET:
                # we should already have a report object, lets get and use it
                report = get_object_or_404(Report, id=request.GET['regen'])
                report.datetime = datetime.now(tz=localtz)
                report.status = 'requested'
                if report.requester.username != request.user.username:
                    report.requester = request.user
            else:
                report = Report(name="Product Endpoints " + str(product),
                                type="Product Endpoint",
                                format='PDF',
                                requester=request.user,
                                task_id='tbd',
                                options=request.path + "?" + request.GET.urlencode())
            report.save()
            async_pdf_report.delay(report=report,
                                   template=template,
                                   filename=filename,
                                   report_title=report_title,
                                   report_subtitle=report_subtitle,
                                   report_info=report_info,
                                   context={'product': product,
                                            'endpoints': endpoints,
                                            'accepted_findings': accepted_findings,
                                            'open_findings': open_findings,
                                            'closed_findings': closed_findings,
                                            'verified_findings': verified_findings,
                                            'report_name': report_name,
                                            'include_finding_notes': include_finding_notes,
                                            'include_executive_summary': include_executive_summary,
                                            'include_table_of_contents': include_table_of_contents,
                                            'user': user,
                                            'team_name': settings.TEAM_NAME,
                                            'title': 'Generate Report',
                                            'host': request.scheme + "://" + request.META['HTTP_HOST']},
                                   uri=request.build_absolute_uri(report.get_url()))
            messages.add_message(request, messages.SUCCESS,
                                 'Your report is building, you will receive an email when it is ready.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('reports'))
        else:
            raise Http404()

    return render(request,
                  'dojo/request_endpoint_report.html',
                  {"endpoints": paged_endpoints,
                   "filtered": endpoints,
                   'report_form': report_form,
                   "name": "Vulnerable Product Endpoints",
                   })
예제 #58
0
def generate_report(request, obj):
    user = Dojo_User.objects.get(id=request.user.id)
    product_type = None
    product = None
    engagement = None
    test = None
    endpoint = None
    endpoint_all_findings = None
    endpoint_monthly_counts = None
    endpoint_active_findings = None
    accepted_findings = None
    open_findings = None
    closed_findings = None
    verified_findings = None
    report_title = None
    report_subtitle = None
    report_info = "Generated By %s on %s" % (
        user.get_full_name(), (datetime.now(tz=localtz).strftime("%m/%d/%Y %I:%M%p %Z")))

    if type(obj).__name__ == "Product":
        if request.user.is_staff or request.user in obj.authorized_users.all():
            pass  # user is authorized for this product
        else:
            raise PermissionDenied
    elif type(obj).__name__ == "Endpoint":
        if request.user.is_staff or request.user in obj.product.authorized_users.all():
            pass  # user is authorized for this product
        else:
            raise PermissionDenied
    elif type(obj).__name__ == "QuerySet":
        # authorization taken care of by only selecting findings from product user is authed to see
        pass
    else:
        if not request.user.is_staff:
            raise PermissionDenied

    report_format = request.GET.get('report_type', 'AsciiDoc')
    include_finding_notes = int(request.GET.get('include_finding_notes', 0))
    include_executive_summary = int(request.GET.get('include_executive_summary', 0))
    include_table_of_contents = int(request.GET.get('include_table_of_contents', 0))
    generate = "_generate" in request.GET
    report_name = str(obj)
    report_type = type(obj).__name__
    add_breadcrumb(title="Generate Report", top_level=False, request=request)
    if type(obj).__name__ == "Product_Type":
        product_type = obj
        filename = "product_type_finding_report.pdf"
        template = "dojo/product_type_pdf_report.html"
        report_name = "Product Type Report: " + str(product_type)
        report_title = "Product Type Report"
        report_subtitle = str(product_type)

        findings = ReportFindingFilter(request.GET, queryset=Finding.objects.filter(
                test__engagement__product__prod_type=product_type).distinct().prefetch_related('test',
                                                                                               'test__engagement__product',
                                                                                               'test__engagement__product__prod_type'))
        products = Product.objects.filter(prod_type=product_type,
                                          engagement__test__finding__in=findings.qs).distinct()
        engagements = Engagement.objects.filter(product__prod_type=product_type,
                                                test__finding__in=findings.qs).distinct()
        tests = Test.objects.filter(engagement__product__prod_type=product_type,
                                    finding__in=findings.qs).distinct()
        if findings:
            start_date = localtz.localize(datetime.combine(findings.qs.last().date, datetime.min.time()))
        else:
            start_date = localtz.localize(datetime.today())
        end_date = localtz.localize(datetime.today())

        r = relativedelta(end_date, start_date)
        months_between = (r.years * 12) + r.months
        # include current month
        months_between += 1

        endpoint_monthly_counts = get_period_counts(findings.qs, findings.qs, None,
                                                    months_between, start_date,
                                                    relative_delta='months')

        context = {'product_type': product_type,
                   'products': products,
                   'engagements': engagements,
                   'tests': tests,
                   'report_name': report_name,
                   'endpoint_opened_per_month': endpoint_monthly_counts[
                       'opened_per_period'] if endpoint_monthly_counts is not None else [],
                   'endpoint_active_findings': findings.qs,
                   'findings': findings.qs,
                   'include_finding_notes': include_finding_notes,
                   'include_executive_summary': include_executive_summary,
                   'include_table_of_contents': include_table_of_contents,
                   'user': user,
                   'team_name': settings.TEAM_NAME,
                   'title': 'Generate Report',
                   'host': request.scheme + "://" + request.META['HTTP_HOST']}

    elif type(obj).__name__ == "Product":
        product = obj
        filename = "product_finding_report.pdf"
        template = "dojo/product_pdf_report.html"
        report_name = "Product Report: " + str(product)
        report_title = "Product Report"
        report_subtitle = str(product)
        findings = ReportFindingFilter(request.GET, queryset=Finding.objects.filter(
                test__engagement__product=product).distinct().prefetch_related('test',
                                                                               'test__engagement__product',
                                                                               'test__engagement__product__prod_type'))
        ids = set(finding.id for finding in findings)
        engagements = Engagement.objects.filter(test__finding__id__in=ids).distinct()
        tests = Test.objects.filter(finding__id__in=ids).distinct()

        context = {'product': product,
                   'engagements': engagements,
                   'tests': tests,
                   'report_name': report_name,
                   'findings': findings.qs,
                   'include_finding_notes': include_finding_notes,
                   'include_executive_summary': include_executive_summary,
                   'include_table_of_contents': include_table_of_contents,
                   'user': user,
                   'team_name': settings.TEAM_NAME,
                   'title': 'Generate Report',
                   'host': request.scheme + "://" + request.META['HTTP_HOST']}

    elif type(obj).__name__ == "Engagement":
        engagement = obj
        findings = ReportFindingFilter(request.GET,
                                       queryset=Finding.objects.filter(test__engagement=engagement,
                                                                       ).prefetch_related('test',
                                                                                          'test__engagement__product',
                                                                                          'test__engagement__product__prod_type').distinct())
        report_name = "Engagement Report: " + str(engagement)
        filename = "engagement_finding_report.pdf"
        template = 'dojo/engagement_pdf_report.html'
        report_title = "Engagement Report"
        report_subtitle = str(engagement)

        ids = set(finding.id for finding in findings)
        tests = Test.objects.filter(finding__id__in=ids).distinct()

        context = {'engagement': engagement,
                   'tests': tests,
                   'report_name': report_name,
                   'findings': findings.qs,
                   'include_finding_notes': include_finding_notes,
                   'include_executive_summary': include_executive_summary,
                   'include_table_of_contents': include_table_of_contents,
                   'user': user,
                   'team_name': settings.TEAM_NAME,
                   'title': 'Generate Report',
                   'host': request.scheme + "://" + request.META['HTTP_HOST']}

    elif type(obj).__name__ == "Test":
        test = obj
        findings = ReportFindingFilter(request.GET,
                                       queryset=Finding.objects.filter(test=test).prefetch_related('test',
                                                                                                   'test__engagement__product',
                                                                                                   'test__engagement__product__prod_type').distinct())
        filename = "test_finding_report.pdf"
        template = "dojo/test_pdf_report.html"
        report_name = "Test Report: " + str(test)
        report_title = "Test Report"
        report_subtitle = str(test)

        context = {'test': test,
                   'report_name': report_name,
                   'findings': findings.qs,
                   'include_finding_notes': include_finding_notes,
                   'include_executive_summary': include_executive_summary,
                   'include_table_of_contents': include_table_of_contents,
                   'user': user,
                   'team_name': settings.TEAM_NAME,
                   'title': 'Generate Report',
                   'host': request.scheme + "://" + request.META['HTTP_HOST']}

    elif type(obj).__name__ == "Endpoint":
        endpoint = obj
        host = endpoint.host_no_port
        report_name = "Endpoint Report: " + host
        report_type = "Endpoint"
        endpoints = Endpoint.objects.filter(host__regex="^" + host + ":?",
                                            product=endpoint.product).distinct()
        filename = "endpoint_finding_report.pdf"
        template = 'dojo/endpoint_pdf_report.html'
        report_title = "Endpoint Report"
        report_subtitle = host
        findings = ReportFindingFilter(request.GET,
                                       queryset=Finding.objects.filter(endpoints__in=endpoints,
                                                                       ).prefetch_related('test',
                                                                                          'test__engagement__product',
                                                                                          'test__engagement__product__prod_type').distinct())

        context = {'endpoint': endpoint,
                   'endpoints': endpoints,
                   'report_name': report_name,
                   'findings': findings.qs,
                   'include_finding_notes': include_finding_notes,
                   'include_executive_summary': include_executive_summary,
                   'include_table_of_contents': include_table_of_contents,
                   'user': user,
                   'team_name': settings.TEAM_NAME,
                   'title': 'Generate Report',
                   'host': request.scheme + "://" + request.META['HTTP_HOST']}
    elif type(obj).__name__ == "QuerySet":
        findings = ReportAuthedFindingFilter(request.GET,
                                             queryset=obj.prefetch_related('test',
                                                                           'test__engagement__product',
                                                                           'test__engagement__product__prod_type').distinct(),
                                             user=request.user)
        filename = "finding_report.pdf"
        report_name = 'Finding'
        report_type = 'Finding'
        template = 'dojo/finding_pdf_report.html'
        report_title = "Finding Report"
        report_subtitle = ''

        context = {'findings': findings.qs,
                   'report_name': report_name,
                   'include_finding_notes': include_finding_notes,
                   'include_executive_summary': include_executive_summary,
                   'include_table_of_contents': include_table_of_contents,
                   'user': user,
                   'team_name': settings.TEAM_NAME,
                   'title': 'Generate Report',
                   'host': request.scheme + "://" + request.META['HTTP_HOST']}
    else:
        raise Http404()

    report_form = ReportOptionsForm()

    if generate:
        report_form = ReportOptionsForm(request.GET)
        if report_format == 'AsciiDoc':
            return render(request,
                          'dojo/asciidoc_report.html',
                          {'product_type': product_type,
                           'product': product,
                           'engagement': engagement,
                           'test': test,
                           'endpoint': endpoint,
                           'findings': findings.qs,
                           'include_finding_notes': include_finding_notes,
                           'include_executive_summary': include_executive_summary,
                           'include_table_of_contents': include_table_of_contents,
                           'user': user,
                           'team_name': settings.TEAM_NAME,
                           'title': 'Generate Report',
                           })

        elif report_format == 'PDF':
            if 'regen' in request.GET:
                # we should already have a report object, lets get and use it
                report = get_object_or_404(Report, id=request.GET['regen'])
                report.datetime = datetime.now(tz=localtz)
                report.status = 'requested'
                if report.requester.username != request.user.username:
                    report.requester = request.user
            else:
                # lets create the report object and send it in to celery task
                report = Report(name=report_name,
                                type=report_type,
                                format='PDF',
                                requester=request.user,
                                task_id='tbd',
                                options=request.path + "?" + request.GET.urlencode())
            report.save()
            async_pdf_report.delay(report=report,
                                   template=template,
                                   filename=filename,
                                   report_title=report_title,
                                   report_subtitle=report_subtitle,
                                   report_info=report_info,
                                   context=context,
                                   uri=request.build_absolute_uri(report.get_url()))
            messages.add_message(request, messages.SUCCESS,
                                 'Your report is building, you will receive an email when it is ready.',
                                 extra_tags='alert-success')

            return HttpResponseRedirect(reverse('reports'))
        else:
            raise Http404()
    paged_findings = get_page_items(request, findings, 25)
    return render(request, 'dojo/request_report.html',
                  {'product_type': product_type,
                   'product': product,
                   'engagement': engagement,
                   'test': test,
                   'endpoint': endpoint,
                   'findings': findings,
                   'paged_findings': paged_findings,
                   'report_form': report_form,
                   })
예제 #59
0
def express_new_jira(request):
    if request.method == 'POST':
        jform = ExpressJIRAForm(request.POST, instance=JIRA_Conf())
        if jform.is_valid():
            try:
                jira_server = jform.cleaned_data.get('url').rstrip('/')
                jira_username = jform.cleaned_data.get('username')
                jira_password = jform.cleaned_data.get('password')
                # Instantiate JIRA instance for validating url, username and password
                try:
                    jira = JIRA(server=jira_server,
                                basic_auth=(jira_username, jira_password),
                                options={"verify": settings.JIRA_SSL_VERIFY})
                except Exception as e:
                    logger.exception(e)
                    messages.add_message(
                        request,
                        messages.ERROR,
                        'Unable to authenticate. Please check the URL, username, and password.',
                        extra_tags='alert-danger')
                    return render(request, 'dojo/express_new_jira.html',
                                  {'jform': jform})
                # authentication successful
                # Get the open and close keys
                issue_id = jform.cleaned_data.get('issue_key')
                key_url = jira_server + '/rest/api/latest/issue/' + issue_id + '/transitions?expand=transitions.fields'
                data = json.loads(
                    requests.get(key_url,
                                 auth=(jira_username, jira_password)).text)
                for node in data['transitions']:
                    if node['to']['name'] == 'To Do':
                        open_key = int(node['to']['id'])
                    if node['to']['name'] == 'Done':
                        close_key = int(node['to']['id'])
                # Get the epic id name
                key_url = jira_server + '/rest/api/2/field'
                data = json.loads(
                    requests.get(key_url,
                                 auth=(jira_username, jira_password)).text)
                for node in data:
                    if 'Epic Name' in node['clauseNames']:
                        epic_name = int(node['clauseNames'][0][3:-1])
                        break

                jira_conf = JIRA_Conf(
                    username=jira_username,
                    password=jira_password,
                    url=jira_server,
                    configuration_name=jform.cleaned_data.get(
                        'configuration_name'),
                    info_mapping_severity='Lowest',
                    low_mapping_severity='Low',
                    medium_mapping_severity='Medium',
                    high_mapping_severity='High',
                    critical_mapping_severity='Highest',
                    epic_name_id=epic_name,
                    open_status_key=open_key,
                    close_status_key=close_key,
                    finding_text='',
                    default_issue_type=jform.cleaned_data.get(
                        'default_issue_type'))
                jira_conf.save()
                messages.add_message(
                    request,
                    messages.SUCCESS,
                    'JIRA Configuration Successfully Created.',
                    extra_tags='alert-success')
                create_notification(
                    event='other',
                    title='New addition of JIRA: %s' %
                    jform.cleaned_data.get('configuration_name'),
                    description='JIRA "%s" was added by %s' %
                    (jform.cleaned_data.get('configuration_name'),
                     request.user),
                    url=request.build_absolute_uri(reverse('jira')),
                )
                return HttpResponseRedirect(reverse('jira', ))
            except:
                messages.add_message(
                    request,
                    messages.ERROR,
                    'Unable to query other required fields. They must be entered manually.',
                    extra_tags='alert-danger')
                return HttpResponseRedirect(reverse('add_jira', ))
            return render(request, 'dojo/express_new_jira.html',
                          {'jform': jform})
    else:
        jform = ExpressJIRAForm()
        add_breadcrumb(title="New Jira Configuration (Express)",
                       top_level=False,
                       request=request)
    return render(request, 'dojo/express_new_jira.html', {'jform': jform})
예제 #60
0
def answer_empty_survey(request, esid):
    general_survey = get_object_or_404(General_Survey, id=esid)
    engagement_survey = get_object_or_404(Engagement_Survey, id=general_survey.survey_id)
    engagement, survey = None, None
    
    settings = System_Settings.objects.all()[0]

    if not settings.allow_anonymous_survey_repsonse:
        auth = request.user.is_staff
        if not auth:
            messages.add_message(request,
                                 messages.ERROR,
                                 'You must be logged in to respond. Otherwise, enable anonymous response in system settings.',
                                 extra_tags='alert-danger')
            # will render 403
            raise PermissionDenied

    questions = [q.get_form()(prefix=str(q.id),
                              engagement_survey=engagement_survey,
                              question=q, form_tag=False)
                 for q in engagement_survey.questions.all()
                 ]

    if request.method == 'POST':
        survey = Answered_Survey(survey=engagement_survey)
        survey.save()
        questions = [
            q.get_form()(request.POST or None,
                         prefix=str(q.id),
                         answered_survey=survey,
                         question=q, form_tag=False)
            for q in survey.survey.questions.all()
                    ]

        questions_are_valid = []

        for question in questions:
            valid = question.is_valid()
            questions_are_valid.append(valid)
            if valid:
                question.save()

        questions_are_valid = all(questions_are_valid)
        if questions_are_valid:
            survey.completed = True
            survey.responder = request.user if not request.user.is_anonymous else None
            survey.answered_on = date.today()
            survey.save()
            general_survey.num_responses = general_survey.num_responses + 1
            general_survey.save()
            if request.user.is_anonymous:
                message = 'Your responses have been recorded.'
            else:
                message = 'Successfully answered, all answers valid.'

            messages.add_message(request,
                                 messages.SUCCESS,
                                 message,
                                 extra_tags='alert-success')
            return HttpResponseRedirect(
                    reverse('dashboard'))
        else:
            messages.add_message(request,
                                 messages.ERROR,
                                 'Errors found, please correct.',
                                 extra_tags='alert-danger')
    add_breadcrumb(title="Respond - " + engagement_survey.name + " ", top_level=False, request=request)
    if survey is None:
        survey = engagement_survey
    return render(request,
                  'defectDojo-engagement-survey/answer_survey.html',
                  {'survey': survey,
                   'engagement': engagement,
                   'questions': questions,
                   })