Exemplo n.º 1
0
def get_item(vuln, test):
    finding = Finding(
        test=test,
        unique_id_from_tool=vuln["id"],
        nb_occurences=1,
    )

    # Defining variables
    location = vuln["location"]

    # Endpoint
    #  using url
    if "url" in location and location["url"] and location["url"] != "None":
        endpoint = Endpoint.from_uri(location["url"])
    # fallback to using old way of creating endpoints
    elif "domain" in location and location["domain"] and location["domain"] != "None":
        endpoint = Endpoint(host=str(location["domain"]))
    else:  # no domain, use ip instead
        if "ip" in location and location["ip"] and location["ip"] != "None":
            endpoint = Endpoint(host=str(location["ip"]))
    # check for protocol
    if (
        "applicationProtocol" in location and
        location["applicationProtocol"] and
        location["applicationProtocol"] != "None"
    ):
        endpoint.protocol = location["applicationProtocol"]
    # check for port
    if (
        "port" in location and
        location["port"] in location and
        location["port"] != "None"
    ):
        endpoint.port = location["port"]
    finding.unsaved_endpoints = [endpoint]  # assigning endpoint

    # Title
    finding.title = vuln["name"]

    # Description + CVEs
    description = vuln["classification"]
    cves = "no match"
    if "CVE-NO-MATCH" not in vuln["kb"]["cves"]:
        finding.cve = vuln["kb"]["cves"][0]
        cves = ""
        for cve in vuln["kb"]["cves"]:
            cves += f"{cve}, "
        cves = cves[: len(cves) - 2]  # removing the comma and the blank space

    finding.description = description + "; CVEs: " + cves
    finding.severity = vuln["severity"].title()

    # Date
    date_str = vuln["createdOn"]
    date_str = date_str[: len(date_str) - 3] + date_str[-2:]
    finding.date = datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%S.%f%z")

    # Component Name and Version
    if (
        "applicationCpe" in location and
        location["applicationCpe"] and
        location["applicationCpe"] != "None"
    ):
        cpe = CPE(location["applicationCpe"])

        component_name = cpe.get_vendor()[0] + ":" if len(
            cpe.get_vendor()) > 0 else ""

        component_name += cpe.get_product()[0] if len(
            cpe.get_product()) > 0 else ""

        finding.component_name = component_name if component_name else None
        finding.component_version = (
            cpe.get_version()[0] if len(cpe.get_version()) > 0 else None
        )

    return finding
    def get_items(self, tree, vulns, test):
        x = list()
        for nodes in tree.iter('nodes'):
            for node in nodes.iter('node'):
                host = dict()
                host['name'] = node.get('address')
                host['hostnames'] = set()
                host['os'] = ""
                host['services'] = list()
                host['vulns'] = self.parse_tests_type(node, vulns)

                for names in node.iter('names'):
                    for name in list(names):
                        host['hostnames'].add(name.text)

                for endpoints in node.iter('endpoints'):
                    for endpoint in list(endpoints):
                        svc = {
                            'protocol': endpoint.get('protocol'),
                            'port': endpoint.get('port'),
                            'status': endpoint.get('status'),
                        }
                        for services in endpoint.iter('services'):
                            for service in list(services):
                                svc['name'] = service.get('name')
                                svc['vulns'] = self.parse_tests_type(
                                    service, vulns)

                                for configs in service.iter('configurations'):
                                    for config in list(configs):
                                        if "banner" in config.get('name'):
                                            svc['version'] = config.get('name')

                        host['services'].append(svc)

                x.append(host)

        dupes = {}

        for item in x:
            for service in item['services']:
                for vuln in service['vulns']:
                    dupe_key = vuln['severity'] + vuln['name']

                    find = self.findings(dupe_key, dupes, test, vuln)

                    endpoint = Endpoint(host=item['name'])
                    if 'port' in service:
                        endpoint.port = int(service['port'])
                    find.unsaved_endpoints.append(endpoint)
                    find.unsaved_tags = list()
                    find.unsaved_tags = vuln['tags']

        # manage findings by node only
        for vuln in host['vulns']:
            dupe_key = vuln['severity'] + vuln['name']

            find = self.findings(dupe_key, dupes, test, vuln)

            find.unsaved_tags = list()
            find.unsaved_tags = vuln['tags']

        return list(dupes.values())
Exemplo n.º 3
0
    def get_findings(self, filename, test: Test):
        content = filename.read()
        if type(content) is bytes:
            content = content.decode('utf-8')
        csv.field_size_limit(int(sys.maxsize / 10))  # the request/resp are big
        reader = csv.DictReader(io.StringIO(content))
        dupes = dict()
        for row in reader:
            # manage severity from two possible columns 'Severity' and 'Risk'
            severity = 'Info'
            if 'Severity' in row:
                severity = self._convert_severity(row.get('Severity'))
            elif 'Risk' in row:
                severity = self._convert_severity(row.get('Risk'))
            # manage title from two possible columns 'Nme' and 'Plugin Name'
            title = row.get('Name')
            if title is None and 'Plugin Name' in row:
                title = row.get('Plugin Name')
            # special case to skip empty titles
            if not title:
                continue
            description = row.get('Synopsis')
            mitigation = str(row.get('Solution'))
            impact = row.get('Description', 'N/A')
            references = row.get('See Also', 'N/A')

            dupe_key = severity + title + row.get('Host', 'No host') + str(
                row.get('Port', 'No port')) + row.get('Synopsis',
                                                      'No synopsis')

            detected_cve = self._format_cve(str(row.get('CVE')))
            cve = None
            if detected_cve:
                # FIXME support more than one CVE in Nessus CSV parser
                cve = detected_cve[0]
                if len(detected_cve) > 1:
                    LOGGER.warning(
                        "more than one CVE for a finding. NOT supported by Nessus CSV parser"
                    )

            if dupe_key in dupes:
                find = dupes[dupe_key]
                if 'Plugin Output' in row:
                    find.description += row.get('Plugin Output')
            else:
                if 'Plugin Output' in row:
                    description = description + str(row.get('Plugin Output'))
                find = Finding(title=title,
                               test=test,
                               cve=cve,
                               description=description,
                               severity=severity,
                               mitigation=mitigation,
                               impact=impact,
                               references=references)

                # manage CVSS vector (only v3.x for now)
                if 'CVSS V3 Vector' in row and '' != row.get('CVSS V3 Vector'):
                    find.cvssv3 = CVSS3('CVSS:3.0/' +
                                        str(row.get('CVSS V3 Vector'))
                                        ).clean_vector(output_prefix=False)
                # manage CPE data
                detected_cpe = self._format_cpe(str(row.get('CPE')))
                if detected_cpe:
                    # FIXME support more than one CPE in Nessus CSV parser
                    if len(detected_cpe) > 1:
                        LOGGER.warning(
                            "more than one CPE for a finding. NOT supported by Nessus CSV parser"
                        )
                    cpe_decoded = CPE(detected_cpe[0])
                    find.component_name = cpe_decoded.get_product()[0] if len(
                        cpe_decoded.get_product()) > 0 else None
                    find.component_version = cpe_decoded.get_version(
                    )[0] if len(cpe_decoded.get_version()) > 0 else None

                find.unsaved_endpoints = list()
                dupes[dupe_key] = find
            # manage endpoints
            endpoint = Endpoint(host='localhost')
            if 'Host' in row:
                endpoint.host = row.get('Host')
            elif 'IP Address' in row:
                endpoint.host = row.get('IP Address')
            endpoint.port = row.get('Port')
            if 'Protocol' in row:
                endpoint.protocol = row.get('Protocol').lower()
            find.unsaved_endpoints.append(endpoint)
        return list(dupes.values())
Exemplo n.º 4
0
    def get_findings(self, file, test):
        tree = parse(file)
        root = tree.getroot()
        dupes = dict()
        if 'nmaprun' not in root.tag:
            raise ValueError("This doesn't seem to be a valid Nmap xml file.")

        report_date = None
        try:
            report_date = datetime.datetime.fromtimestamp(
                int(root.attrib['start']))
        except ValueError:
            pass

        for host in root.findall("host"):
            host_info = "### Host\n\n"

            ip = host.find("address[@addrtype='ipv4']").attrib['addr']
            if ip is not None:
                host_info += "**IP Address:** %s\n" % ip

            fqdn = host.find(
                "hostnames/hostname[@type='PTR']").attrib['name'] if host.find(
                    "hostnames/hostname[@type='PTR']") is not None else None
            if fqdn is not None:
                host_info += "**FQDN:** %s\n" % fqdn

            host_info += "\n\n"

            for os in host.iter("os"):
                for os_match in os.iter("osmatch"):
                    if 'name' in os_match.attrib:
                        host_info += "**Host OS:** %s\n" % os_match.attrib[
                            'name']
                    if 'accuracy' in os_match.attrib:
                        host_info += "**Accuracy:** {0}%\n".format(
                            os_match.attrib['accuracy'])

                host_info += "\n\n"

            for port_element in host.findall("ports/port"):
                protocol = port_element.attrib['protocol']
                endpoint = Endpoint(host=ip, fqdn=fqdn, protocol=protocol)
                if 'portid' in port_element.attrib and port_element.attrib[
                        'portid'].isdigit():
                    endpoint.port = int(port_element.attrib['portid'])

                # filter on open ports
                if 'open' != port_element.find("state").attrib.get('state'):
                    continue
                title = "Open port: %s/%s" % (endpoint.port, endpoint.protocol)
                description = host_info
                description += "**Port/Protocol:** %s/%s\n" % (
                    endpoint.port, endpoint.protocol)

                service_info = "\n\n"
                if port_element.find('service') is not None:
                    if 'product' in port_element.find('service').attrib:
                        service_info += "**Product:** %s\n" % port_element.find(
                            'service').attrib['product']

                    if 'version' in port_element.find('service').attrib:
                        service_info += "**Version:** %s\n" % port_element.find(
                            'service').attrib['version']

                    if 'extrainfo' in port_element.find('service').attrib:
                        service_info += "**Extra Info:** %s\n" % port_element.find(
                            'service').attrib['extrainfo']

                    description += service_info

                description += "\n\n"

                # manage some script like https://github.com/vulnersCom/nmap-vulners
                for script_element in port_element.findall(
                        'script[@id="vulners"]'):
                    self.manage_vulner_script(test, dupes, script_element,
                                              endpoint, report_date)

                severity = "Info"
                dupe_key = "nmap:" + str(endpoint.port)
                if dupe_key in dupes:
                    find = dupes[dupe_key]
                    if description is not None:
                        find.description += description
                else:
                    find = Finding(
                        title=title,
                        test=test,
                        description=description,
                        severity=severity,
                        mitigation="N/A",
                        impact="No impact provided",
                    )
                    find.unsaved_endpoints = list()
                    dupes[dupe_key] = find
                    if report_date:
                        find.date = report_date

                find.unsaved_endpoints.append(endpoint)
        return list(dupes.values())