예제 #1
0
def report_builder(request):
    add_breadcrumb(title="Report Builder", top_level=True, request=request)
    findings = get_authorized_findings(Permissions.Finding_View)
    findings = ReportFindingFilter(request.GET, queryset=findings)
    endpoints = Endpoint.objects.filter(
        finding__active=True,
        finding__verified=True,
        finding__false_p=False,
        finding__duplicate=False,
        finding__out_of_scope=False,
    ).distinct()

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

    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
    })
예제 #2
0
def dashboard(request: HttpRequest) -> HttpResponse:
    engagements = get_authorized_engagements(Permissions.Engagement_View).distinct()
    findings = get_authorized_findings(Permissions.Finding_View).distinct()

    findings = findings.filter(duplicate=False)

    engagement_count = engagements.filter(active=True).count()

    today = timezone.now().date()

    date_range = [today - timedelta(days=6), today]  # 7 days (6 days plus today)
    finding_count = findings\
        .filter(created__date__range=date_range)\
        .count()
    mitigated_count = findings\
        .filter(mitigated__date__range=date_range)\
        .count()
    accepted_count = findings\
        .filter(risk_acceptance__created__date__range=date_range)\
        .count()

    severity_count_all = get_severities_all(findings)
    severity_count_by_month = get_severities_by_month(findings, today)
    punchcard, ticks = get_punchcard_data(findings, today - relativedelta(weeks=26), 26)

    if user_has_configuration_permission(request.user, 'dojo.view_engagement_survey', 'staff'):
        unassigned_surveys = Answered_Survey.objects.filter(assignee_id__isnull=True, completed__gt=0, ) \
            .filter(Q(engagement__isnull=True) | Q(engagement__in=engagements))
    else:
        unassigned_surveys = None

    if request.user.is_superuser and not settings.FEATURE_CONFIGURATION_AUTHORIZATION:
        message = '''Legacy authorization for changing configurations based on staff users will be
                     removed with version 2.12.0 / 5. July 2022. If you have set
                     `FEATURE_CONFIGURATION_AUTHORIZATION` to `False` in your local configuration,
                     remove this local setting and start using the new authorization.'''
        messages.add_message(request, messages.WARNING, message, extra_tags='alert-warning')

    add_breadcrumb(request=request, clear=True)
    return render(request, 'dojo/dashboard.html', {
        'engagement_count': engagement_count,
        'finding_count': finding_count,
        'mitigated_count': mitigated_count,
        'accepted_count': accepted_count,
        'critical': severity_count_all['Critical'],
        'high': severity_count_all['High'],
        'medium': severity_count_all['Medium'],
        'low': severity_count_all['Low'],
        'info': severity_count_all['Info'],
        'by_month': severity_count_by_month,
        'punchcard': punchcard,
        'ticks': ticks,
        'surveys': unassigned_surveys,
    })
예제 #3
0
def dashboard(request: HttpRequest) -> HttpResponse:
    engagements = get_authorized_engagements(
        Permissions.Engagement_View).distinct()
    findings = get_authorized_findings(Permissions.Finding_View).distinct()

    findings = findings.filter(duplicate=False)

    engagement_count = engagements.filter(active=True).count()

    today = timezone.now().date()

    date_range = [today - timedelta(days=6),
                  today]  # 7 days (6 days plus today)
    finding_count = findings\
        .filter(created__date__range=date_range)\
        .count()
    mitigated_count = findings\
        .filter(mitigated__date__range=date_range)\
        .count()
    accepted_count = findings\
        .filter(risk_acceptance__created__date__range=date_range)\
        .count()

    severity_count_all = get_severities_all(findings)
    severity_count_by_month = get_severities_by_month(findings, today)
    punchcard, ticks = get_punchcard_data(findings,
                                          today - relativedelta(weeks=26), 26)

    if request.user.is_staff:
        unassigned_surveys = Answered_Survey.objects.filter(assignee_id__isnull=True, completed__gt=0, ) \
            .filter(Q(engagement__isnull=True) | Q(engagement__in=engagements))
    else:
        unassigned_surveys = None

    add_breadcrumb(request=request, clear=True)
    return render(
        request, 'dojo/dashboard.html', {
            'engagement_count': engagement_count,
            'finding_count': finding_count,
            'mitigated_count': mitigated_count,
            'accepted_count': accepted_count,
            'critical': severity_count_all['Critical'],
            'high': severity_count_all['High'],
            'medium': severity_count_all['Medium'],
            'low': severity_count_all['Low'],
            'info': severity_count_all['Info'],
            'by_month': severity_count_by_month,
            'punchcard': punchcard,
            'ticks': ticks,
            'surveys': unassigned_surveys,
        })
예제 #4
0
파일: views.py 프로젝트: manu20202/test1
def components(request):
    add_breadcrumb(title='Components', top_level=True, request=request)
    separator = ', '
    # Get components ordered by component_name and concat component versions to the same row

    component_query = get_authorized_findings(Permissions.Finding_View)

    if connection.vendor == 'postgresql':
        component_query = component_query.values("component_name").order_by(
            'component_name').annotate(component_version=StringAgg(
                'component_version', delimiter=separator, distinct=True))
    else:
        component_query = component_query.values("component_name").order_by(
            'component_name')
        component_query = component_query.annotate(
            component_version=Sql_GroupConcat(
                'component_version', separator=separator, distinct=True))

    # Append counts
    component_query = component_query.annotate(
        total=Count('id')).order_by('component_name')
    component_query = component_query.annotate(
        active=Count('id', filter=Q(active=True)))
    component_query = component_query.annotate(
        duplicate=(Count('id', filter=Q(duplicate=True))))
    component_query = component_query.order_by(
        '-total')  # Default sort by total descending

    comp_filter = ComponentFilter(request.GET, queryset=component_query)
    result = get_page_items(request, comp_filter.qs, 25)

    # Filter out None values for auto-complete
    component_words = component_query.exclude(
        component_name__isnull=True).values_list('component_name', flat=True)

    return render(
        request, 'dojo/components.html', {
            'filter': comp_filter,
            'result': result,
            'component_words': sorted(set(component_words))
        })
예제 #5
0
def product_findings_report(request):
    findings = get_authorized_findings(Permissions.Finding_View)
    return generate_report(request, findings)
예제 #6
0
def finding_querys(prod_type, request):
    findings_query = Finding.objects.filter(
        verified=True,
        severity__in=('Critical', 'High', 'Medium', 'Low', 'Info')
    ).select_related(
        'reporter',
        'test',
        'test__engagement__product',
        'test__engagement__product__prod_type',
    ).prefetch_related(
        'risk_acceptance_set',
        'test__engagement__risk_acceptance',
        'test__test_type',
    )

    findings_query = get_authorized_findings(Permissions.Finding_View, findings_query, request.user)

    active_findings_query = Finding.objects.filter(
        verified=True,
        active=True,
        severity__in=('Critical', 'High', 'Medium', 'Low', 'Info')
    ).select_related(
        'reporter',
        'test',
        'test__engagement__product',
        'test__engagement__product__prod_type',
    ).prefetch_related(
        'risk_acceptance_set',
        'test__engagement__risk_acceptance',
        'test__test_type',
    )

    active_findings_query = get_authorized_findings(Permissions.Finding_View, active_findings_query, request.user)

    findings = MetricsFindingFilter(request.GET, queryset=findings_query)
    active_findings = MetricsFindingFilter(request.GET, queryset=active_findings_query)

    findings_qs = queryset_check(findings)
    active_findings_qs = queryset_check(active_findings)

    if not findings_qs and not findings_query:
        findings = findings_query
        active_findings = active_findings_query
        findings_qs = findings if isinstance(findings, QuerySet) else findings.qs
        active_findings_qs = active_findings if isinstance(active_findings, QuerySet) else active_findings.qs
        messages.add_message(request,
                                     messages.ERROR,
                                     'All objects have been filtered away. Displaying all objects',
                                     extra_tags='alert-danger')

    try:
        start_date = findings_qs.earliest('date').date
        start_date = datetime(start_date.year,
                            start_date.month, start_date.day,
                            tzinfo=timezone.get_current_timezone())
        end_date = findings_qs.latest('date').date
        end_date = datetime(end_date.year,
                            end_date.month, end_date.day,
                            tzinfo=timezone.get_current_timezone())
    except:
        start_date = timezone.now()
        end_date = timezone.now()

    if len(prod_type) > 0:
        findings_closed = Finding.objects.filter(mitigated__date__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_accepted=True, date__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_accepted=True, date__range=[start_date, end_date],
                                                          test__engagement__product__prod_type__in=prod_type). \
            prefetch_related('test__engagement__product')
    else:
        findings_closed = Finding.objects.filter(mitigated__date__range=[start_date, end_date]).prefetch_related(
            'test__engagement__product')
        accepted_findings = Finding.objects.filter(risk_accepted=True, date__range=[start_date, end_date]). \
            prefetch_related('test__engagement__product')
        accepted_findings_counts = Finding.objects.filter(risk_accepted=True, date__range=[start_date, end_date]). \
            prefetch_related('test__engagement__product')

    findings_closed = get_authorized_findings(Permissions.Finding_View, findings_closed, request.user)
    accepted_findings = get_authorized_findings(Permissions.Finding_View, accepted_findings, request.user)
    accepted_findings_counts = get_authorized_findings(Permissions.Finding_View, accepted_findings_counts, request.user)
    accepted_findings_counts = severity_count(accepted_findings_counts, 'aggregate', 'severity')

    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 = get_authorized_products(Permissions.Product_View)
    top_ten = top_ten.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)
    top_ten = severity_count(top_ten, 'annotate', 'engagement__test__finding__severity').order_by('-critical', '-high', '-medium', '-low')[:10]

    return {
        'all': findings,
        'closed': findings_closed,
        'accepted': accepted_findings,
        'accepted_count': accepted_findings_counts,
        'top_ten': top_ten,
        'monthly_counts': monthly_counts,
        'weekly_counts': weekly_counts,
        'weeks_between': weeks_between,
        'start_date': start_date,
        'end_date': end_date,
    }
예제 #7
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

    # if request.method == 'GET' and "query" in request.GET:
    if request.method == 'GET':
        form = SimpleSearchForm(request.GET)
        if form.is_valid():
            cookie = True

            clean_query = form.cleaned_data['query'] or ''
            original_clean_query = clean_query

            operators, keywords = parse_search_query(clean_query)

            search_tags = "tag" in operators or "test-tag" in operators or "engagement-tag" in operators or "product-tag" in operators or \
                          "tags" in operators or "test-tags" in operators or "engagement-tags" in operators or "product-tags" in operators or \
                          "not-tag" in operators or "not-test-tag" in operators or "not-engagement-tag" in operators or "not-product-tag" in operators or \
                          "not-tags" in operators or "not-test-tags" in operators or "not-engagement-tags" in operators or "not-product-tags" in operators

            search_cve = "cve" in operators

            search_finding_id = "id" in operators
            search_findings = "finding" in operators or search_cve or search_finding_id or search_tags or not operators

            search_finding_templates = "template" in operators or search_tags or not (
                operators or search_finding_id or search_cve)
            search_tests = "test" in operators or search_tags or not (
                operators or search_finding_id or search_cve)
            search_engagements = "engagement" in operators or search_tags or not (
                operators or search_finding_id or search_cve)

            search_products = "product" in operators or search_tags or not (
                operators or search_finding_id or search_cve)
            search_endpoints = "endpoint" in operators or search_tags or not (
                operators or search_finding_id or search_cve)
            search_languages = "language" in operators or search_tags or not (
                operators or search_finding_id or search_cve)
            search_technologies = "technology" in operators or search_tags or not (
                operators or search_finding_id or search_cve)

            authorized_findings = get_authorized_findings(
                Permissions.Finding_View)
            authorized_tests = get_authorized_tests(Permissions.Test_View)
            authorized_engagements = get_authorized_engagements(
                Permissions.Engagement_View)
            authorized_products = get_authorized_products(
                Permissions.Product_View)
            authorized_endpoints = get_authorized_endpoints(
                Permissions.Endpoint_View)
            authorized_finding_templates = Finding_Template.objects.all()

            # 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 = authorized_findings
            tests = authorized_tests
            engagements = authorized_engagements
            products = authorized_products
            endpoints = authorized_endpoints

            findings_filter = None
            title_words = None
            component_words = None

            keywords_query = ' '.join(keywords)

            if search_finding_id:
                logger.debug('searching finding id')

                findings = authorized_findings
                findings = findings.filter(id=operators['id'][0])

            elif search_findings:
                logger.debug('searching findings')

                findings_filter = OpenFindingFilter(request.GET,
                                                    queryset=findings,
                                                    user=request.user,
                                                    pid=None,
                                                    prefix='finding')
                # setting initial values for filters is not supported and discouraged: https://django-filter.readthedocs.io/en/stable/guide/tips.html#using-initial-values-as-defaults
                # we could try to modify request.GET before generating the filter, but for now we'll leave it as is

                title_words = get_words_for_field(Finding, 'title')
                component_words = get_words_for_field(Finding,
                                                      'component_name')

                findings = findings_filter.qs

                findings = apply_tag_filters(findings, operators)
                findings = apply_endpoint_filter(findings, operators)
                findings = apply_cve_filter(findings, operators)

                findings = perform_keyword_search_for_operator(
                    findings, operators, 'finding', keywords_query)

            else:
                findings = None
                findings_filter = None
                component_words = None

            # prefetch after watson to avoid inavlid query errors due to watson not understanding prefetching
            if findings is not None:  # check for None to avoid query execution
                logger.debug('prefetching findings')

                findings = get_page_items(request, findings, 25)

                findings.object_list = prefetch_for_findings(
                    findings.object_list)

                # some over the top tag displaying happening...
                findings.object_list = findings.object_list.prefetch_related(
                    'test__engagement__product__tags')

            tag = operators['tag'] if 'tag' in operators else keywords
            tags = operators['tags'] if 'tags' in operators else keywords
            not_tag = operators[
                'not-tag'] if 'not-tag' in operators else keywords
            not_tags = operators[
                'not-tags'] if 'not-tags' in operators else keywords
            if search_tags and tag or tags or not_tag or not_tags:
                logger.debug('searching tags')

                Q1, Q2, Q3, Q4 = Q(), Q(), Q(), Q()

                if tag:
                    tag = ','.join(tag)  # contains needs a single value
                    Q1 = Q(tags__name__contains=tag)

                if tags:
                    Q2 = Q(tags__name__in=tags)

                if not_tag:
                    not_tag = ','.join(
                        not_tag)  # contains needs a single value
                    Q3 = Q(tags__name__contains=not_tag)

                if not_tags:
                    Q4 = Q(tags__name__in=not_tags)

                tagged_findings = authorized_findings.filter(Q1 | Q2).exclude(
                    Q3 | Q4).distinct()[:max_results].prefetch_related('tags')
                tagged_finding_templates = authorized_finding_templates.filter(
                    Q1 | Q2).exclude(Q3 | Q4).distinct()[:max_results]
                tagged_tests = authorized_tests.filter(Q1 | Q2).exclude(
                    Q3 | Q4).distinct()[:max_results].prefetch_related('tags')
                tagged_engagements = authorized_engagements.filter(
                    Q1 | Q2).exclude(
                        Q3
                        | Q4).distinct()[:max_results].prefetch_related('tags')
                tagged_products = authorized_products.filter(Q1 | Q2).exclude(
                    Q3 | Q4).distinct()[:max_results].prefetch_related('tags')
                tagged_endpoints = authorized_endpoints.filter(
                    Q1 | Q2).exclude(
                        Q3
                        | Q4).distinct()[:max_results].prefetch_related('tags')
            else:
                tagged_findings = None
                tagged_finding_templates = None
                tagged_tests = None
                tagged_engagements = None
                tagged_products = None
                tagged_endpoints = None

            tagged_results = tagged_findings or tagged_finding_templates or tagged_tests or tagged_engagements or tagged_products or tagged_endpoints

            if search_finding_templates:
                logger.debug('searching finding templates')

                finding_templates = authorized_finding_templates
                finding_templates = apply_tag_filters(finding_templates,
                                                      operators)

                if keywords_query:
                    watson_results = watson.filter(finding_templates,
                                                   keywords_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:
                logger.debug('searching tests')

                tests = authorized_tests
                tests = apply_tag_filters(tests, operators)

                if keywords_query:
                    watson_results = watson.filter(tests, keywords_query)
                    tests = tests.filter(
                        id__in=[watson.id for watson in watson_results])

                tests = tests.prefetch_related('engagement',
                                               'engagement__product',
                                               'test_type', 'tags',
                                               'engagement__tags',
                                               'engagement__product__tags')
                tests = tests[:max_results]
            else:
                tests = None

            if search_engagements:
                logger.debug('searching engagements')

                engagements = authorized_engagements
                engagements = apply_tag_filters(engagements, operators)

                if keywords_query:
                    watson_results = watson.filter(engagements, keywords_query)
                    engagements = engagements.filter(
                        id__in=[watson.id for watson in watson_results])

                engagements = engagements.prefetch_related(
                    'product', 'product__tags', 'tags')
                engagements = engagements[:max_results]
            else:
                engagements = None

            if search_products:
                logger.debug('searching products')

                products = authorized_products
                products = apply_tag_filters(products, operators)

                if keywords_query:
                    watson_results = watson.filter(products, keywords_query)
                    products = products.filter(
                        id__in=[watson.id for watson in watson_results])

                products = products.prefetch_related('tags')
                products = products[:max_results]
            else:
                products = None

            if search_endpoints:
                logger.debug('searching endpoint')

                endpoints = authorized_endpoints
                endpoints = apply_tag_filters(endpoints, operators)

                endpoints = endpoints.filter(
                    Q(host__icontains=keywords_query)
                    | Q(path__icontains=keywords_query)
                    | Q(protocol__icontains=keywords_query)
                    | Q(query__icontains=keywords_query)
                    | Q(fragment__icontains=keywords_query))
                endpoints = prefetch_for_endpoints(endpoints)
                endpoints = endpoints[:max_results]
            else:
                endpoints = None

            if search_languages:
                logger.debug('searching languages')

                languages = Languages.objects.filter(
                    language__language__icontains=keywords_query)
                languages = languages.prefetch_related('product',
                                                       'product__tags')
                languages = languages[:max_results]
            else:
                languages = None

            if search_technologies:
                logger.debug('searching technologies')

                app_analysis = App_Analysis.objects.filter(
                    name__icontains=keywords_query)
                app_analysis = app_analysis[:max_results]
            else:
                app_analysis = None

            # make sure watson only searches in authorized model instances
            if keywords_query:
                logger.debug('searching generic')
                logger.debug('going generic with: %s', keywords_query)
                generic = watson.search(
                    keywords_query,
                    models=(
                        authorized_findings, authorized_tests,
                        authorized_engagements, authorized_products,
                        authorized_endpoints, authorized_finding_templates,
                        App_Analysis)).prefetch_related('object')[:max_results]
            else:
                generic = None

            # 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')

            logger.debug('all searched')

        else:
            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 \
                            'tagged' if tagged_results else \
                                'generic'

    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=keywords_query,
                            max_age=None,
                            expires=None,
                            path='/',
                            secure=True,
                            httponly=False)
    else:
        response.delete_cookie("highlight", path='/')
    return response
    '''