DefectDojo / django-DefectDojo

DevSecOps, ASPM, Vulnerability Management. All on one platform.
https://defectdojo.com
BSD 3-Clause "New" or "Revised" License
3.72k stars 1.56k forks source link

sslscan import issue #2428

Closed himani-dangwal closed 4 years ago

himani-dangwal commented 4 years ago

Bug description I performed a sslscan and generated a xml report out of it. But when the import is being done it throws errors . while there is no issue with the xml.

Steps to reproduce Steps to reproduce the behavior:

  1. Go to import scan results
  2. Select scan type "sslscan"
  3. Scroll down to file upload and import the file
  4. Click on Submit it will throw the error

Expected behavior Report should have been imported

Deployment method (select with an X)

Sample scan files (optional) If applicable, add sample scan files to help reproduce your problem.

Screenshots (optional) If applicable, add screenshots to help explain your problem. image

Below is the file where it is throwing the issue.. As checked it is expecting an attribute strength in the xml which is not there dojo/tools/sslscan/parser.py

from xml.dom import NamespaceErr import hashlib from urllib.parse import urlparse from defusedxml import ElementTree as ET from dojo.models import Endpoint, Finding

author = 'dr3dd589'

class SslscanXMLParser(object): def init(self, file, test): self.dupes = dict() self.items = () if file is None: return

    tree = ET.parse(file)
    # get root of tree.
    root = tree.getroot()
    if 'document' not in root.tag:
        raise NamespaceErr("This doesn't seem to be a valid sslscan xml file.")

    for ssltest in root:
        for target in ssltest:
            title = ""
            severity = ""
            description = ""
            severity = "Info"
            url = ssltest.attrib['host']
            port = ssltest.attrib['port']
            parsedUrl = urlparse(url)
            protocol = parsedUrl.scheme
            query = parsedUrl.query
            fragment = parsedUrl.fragment
            path = parsedUrl.path
            try:
                (host, port) = parsedUrl.netloc.split(':')
            except:
                host = parsedUrl.netloc
            if target.tag == "heartbleed" and target.attrib['vulnerable'] == '1':
                title = "heartbleed" + " | " + target.attrib['sslversion']
                description = "**heartbleed** :" + "\n\n" + \
                            "**sslversion** : " + target.attrib['sslversion'] + "\n"
            if target.tag == "cipher" and target.attrib['strength'] not in ['acceptable', 'strong']:
                title = "cipher" + " | " + target.attrib['sslversion']
                description = "**Cipher** : " + target.attrib['cipher'] + "\n\n" + \
                            "**Status** : " + target.attrib['status'] + "\n\n" + \
                            "**strength** : " + target.attrib['strength'] + "\n\n" + \
                            "**sslversion** : " + target.attrib['sslversion'] + "\n"

            if title and description is not None:
                dupe_key = hashlib.md5(str(description + title).encode('utf-8')).hexdigest()
                if dupe_key in self.dupes:
                    finding = self.dupes[dupe_key]
                    if finding.references:
                        finding.references = finding.references
                    self.dupes[dupe_key] = finding
                else:
                    self.dupes[dupe_key] = True

                    finding = Finding(
                        title=title,
                        test=test,
                        active=False,
                        verified=False,
                        description=description,
                        severity=severity,
                        numerical_severity=Finding.get_numerical_severity(severity),
                        dynamic_finding=True,)
                    finding.unsaved_endpoints = list()
                    self.dupes[dupe_key] = finding

                    if url is not None:
                        finding.unsaved_endpoints.append(Endpoint(
                            host=host,
                            port=port,
                            path=path,
                            protocol=protocol,
                            query=query,
                            fragment=fragment,))
            self.items = self.dupes.values()

Request Method: POST Request URL: https://XXXXXXXXX/engagement/850/import_scan_results

Django Version: 2.2.9 Python Version: 3.5.9 Installed Applications: ('django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'polymorphic', 'overextends', 'django.contrib.admin', 'django.contrib.humanize', 'gunicorn', 'tastypie', 'auditlog', 'defectDojo_engagement_survey', 'dojo', 'tastypie_swagger', 'watson', 'tagging', 'custom_field', 'imagekit', 'multiselectfield', 'rest_framework', 'rest_framework.authtoken', 'rest_framework_swagger', 'dbbackup', 'taggit_serializer', 'django_celery_results', 'social_django', 'drf_yasg') Installed Middleware: ['django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'dojo.middleware.LoginRequiredMiddleware', 'dojo.middleware.TimezoneMiddleware', 'social_django.middleware.SocialAuthExceptionMiddleware']

Traceback:

File "/usr/local/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner

  1. response = get_response(request)

File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response

  1. response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response

  1. response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.5/site-packages/django/contrib/auth/decorators.py" in _wrapped_view

  1. return view_func(request, *args, **kwargs)

File "./dojo/engagement/views.py" in import_scan_results

  1. parser = import_parser_factory(file, t, active, verified)

File "./dojo/tools/factory.py" in import_parser_factory

  1. parser = SslscanXMLParser(file, test)

File "./dojo/tools/sslscan/parser.py" in init

  1. if target.tag == "cipher" and target.attrib['strength'] not in ['acceptable', 'strong']:

Exception Type: KeyError at /engagement/850/import_scan_results Exception Value: 'strength'

output xml snippet image

himani-dangwal commented 4 years ago

Hi All, can you please update me on this

valentijnscholten commented 4 years ago

It might be that the format of sslscan output xml has changed. Could you attach some example files?That would help us to make it work again.

himani-dangwal commented 4 years ago

It might be that the format of sslscan output xml has changed. Could you attach some example files?That would help us to make it work again.

Here is the sample xml of sslscan sslscan_sample.zip

himani-dangwal commented 4 years ago

@valentijnscholten any update on this

steeve85 commented 4 years ago

Good catch! There is indeed a change in the format between version 1.X branch and version 2.X branch (which is still in beta). The strength field disappeared in version 2.

rbsec commented 4 years ago

Hi,

The missing strength attribute was a regression. It's fixed in tag 2.0.0-beta3, so once you update to the latest version this should work again.

himani-dangwal commented 4 years ago

Hi,

The missing strength attribute was a regression. It's fixed in tag 2.0.0-beta3, so once you update to the latest version this should work again.

Thanks, the issue is resolved with the new version.