|
| 1 | +from xml.dom import NamespaceErr |
| 2 | +import lxml.etree as le |
| 3 | +import os |
| 4 | +import csv |
| 5 | +import re |
| 6 | +from dojo.models import Endpoint, Finding |
| 7 | +from pprint import pprint |
| 8 | + |
| 9 | +__author__ = 'patriknordlen' |
| 10 | + |
| 11 | +class NmapXMLParser(object): |
| 12 | + def __init__(self, file, test): |
| 13 | + nscan = le.parse(file) |
| 14 | + root = nscan.getroot() |
| 15 | + |
| 16 | + if 'nmaprun' not in root.tag: |
| 17 | + raise NamespaceErr("This doesn't seem to be a valid nmap xml file.") |
| 18 | + dupes = {} |
| 19 | + for host in root.iter("host"): |
| 20 | + ip = host.find("address[@addrtype='ipv4']").attrib['addr'] |
| 21 | + fqdn = host.find("hostnames/hostname[@type='PTR']").attrib['name'] if host.find("hostnames/hostname[@type='PTR']") is not None else None |
| 22 | + |
| 23 | + for portelem in host.xpath("ports/port[state/@state='open']"): |
| 24 | + port = portelem.attrib['portid'] |
| 25 | + protocol = portelem.attrib['protocol'] |
| 26 | + |
| 27 | + title = "Open port: %s/%s" % (port, protocol) |
| 28 | + |
| 29 | + description = "%s:%s A service was found to be listening on this port." % (ip, port) |
| 30 | + |
| 31 | + if portelem.find('service'): |
| 32 | + if hasattr(portelem.find('service'),'product'): |
| 33 | + serviceinfo = " (%s%s)" % (portelem.find('service').attrib['product'], " "+portelem.find('service').attrib['version'] if hasattr(portelem.find('service'),'version') else "") |
| 34 | + else: |
| 35 | + serviceinfo = "" |
| 36 | + description += " It was identified as '%s%s'." % (portelem.find('service').attrib['name'], serviceinfo) |
| 37 | + description += '\n\n' |
| 38 | + |
| 39 | + severity = "Info" |
| 40 | + |
| 41 | + dupe_key = port |
| 42 | + |
| 43 | + if dupe_key in dupes: |
| 44 | + find = dupes[dupe_key] |
| 45 | + if description is not None: |
| 46 | + find.description += description |
| 47 | + else: |
| 48 | + find = Finding(title=title, |
| 49 | + test=test, |
| 50 | + active=False, |
| 51 | + verified=False, |
| 52 | + description=description, |
| 53 | + severity=severity, |
| 54 | + numerical_severity=Finding.get_numerical_severity(severity)) |
| 55 | + find.unsaved_endpoints = list() |
| 56 | + dupes[dupe_key] = find |
| 57 | + |
| 58 | + find.unsaved_endpoints.append(Endpoint(host=ip, fqdn=fqdn, port=port, protocol=protocol)) |
| 59 | + self.items = dupes.values() |
0 commit comments