Exemplo n.º 1
0
class NMAPXMLOutputFile(object):
    def __init__(self,path):
        self.path = path
        try:
            self.tree = etree.parse(self.path)
        except etree.XMLSyntaxError,e:
            raise ReportParserError('Error parsing %s: %s' % (self.path,e))

        root = self.tree.getroot()
        if root.tag != 'nmaprun':
            raise ReportParserError('Input is not supported NMAP XML output file') 
        self.scanner = root.get('scanner') 
        self.version = root.get('version') 
        self.args = root.get('args') 
        self.start_ts = int(root.get('start'))
        self.scaninfo = NMAPScanInfo(self.tree.find('scaninfo'))
        self.runstats = NMAPRunStats(self.tree.find('runstats'))

        try:
            self.hosts = map(lambda h:
                NMAPTargetHostEntry(h),
                self.tree.findall('host')
            )
        except ReportParserError,e:
            raise ReportParserError('Error parsing %s: %s' % (self.path,e))
Exemplo n.º 2
0
    def __init__(self, path):
        if not os.path.isfile(path):
            raise ReportParserError('No such file: %s' % path)

        self.path = path
        try:
            self.tree = etree.parse(path)
        except etree.XMLSyntaxError, e:
            raise ReportParserError('Error parsing %s: %s' % (self.path, e))
Exemplo n.º 3
0
 def __resolve_level(self,level):
     if level in self['levels'].keys():
         return level
     try:
         level = int(level)
         return filter(lambda l:
             level==self['levels'][l]['level'],
             self['levels'].keys()
         )[0]
     except IndexError:
         raise ReportParserError('Invalid level: %s' % level) 
     except ValueError:
         raise ReportParserError('Invalid level: %s' % level) 
Exemplo n.º 4
0
    def __init__(self, host, node):
        self.host = host
        self.node = node
        self.name = node.get('name')
        self.update(node.items())

        for k in filter(lambda k: self.has_key(k), REPORT_INT_VALUES):
            try:
                self[k] = int(self[k])
            except ValueError:
                raise ReportParserError('Invalid integer value: %s' % self[k])

        for n in node.getchildren():
            if n.tag in REPORT_INT_VALUES:
                try:
                    self[n.tag] = int(n.text)
                except ValueError:
                    raise ReportParserError(
                        'Invalid integer value %s: %s' % n.tag, n.text)

            elif n.tag in REPORT_DECIMAL_VALUES:
                try:
                    self[n.tag] = decimal.Decimal(n.text)
                except ValueError:
                    raise ReportParserError('Invalid decimal value %s: %s' %
                                            (n.tag, n.text))

            elif n.tag in REPORT_TEXT_VALUES:
                self[n.tag] = []
                for l in n.text.split('\n'):
                    if l.strip() == '':
                        continue
                    self[n.tag].append(l)

            elif n.tag in REPORT_DATE_VALUES:
                dates = []
                for d in filter(lambda d: d.strip(), n.text.split()):
                    try:
                        dates.append(time.strptime(d, '%Y/%m/%d'))
                    except ValueError, e:
                        raise ReportParserError('Invalid date %s: %s' % (k, d))
                self[n.tag] = dates

            elif n.tag in REPORT_BOOLEAN_VALUES:
                if n.text.lower() in ['true', 'yes']:
                    self[n.tag] = True
                else:
                    self[n.tag] = False
Exemplo n.º 5
0
class NessusXMLReport(list):
    def __init__(self, path):
        if not os.path.isfile(path):
            raise ReportParserError('No such file: %s' % path)

        self.path = path
        try:
            self.tree = etree.parse(path)
        except etree.XMLSyntaxError, e:
            raise ReportParserError('Error parsing %s: %s' % (self.path, e))

        root = self.tree.getroot()
        if root.tag not in NESSUS_REPORT_FORMATS:
            raise ReportParserError('Unsupported nessus report format: %s' %
                                    root.tag)

        self.preferences = NessusReportPreferences(
            self.tree.find('Preferences'))
        self.target_families = NessusTargetFamilies(
            self.tree.find('FamilySelection'))
        self.plugins = NessusPluginList(
            self.tree.find('IndividualPluginSelection'))

        for node in self.tree.findall('Report'):
            # May raise ReportParserError
            self.append(NessusReport(self, node))
Exemplo n.º 6
0
 def background(self,level):
     if level == 'header':
         return self['header']['background']
     level = self.__resolve_level(level)
     try:
         return self['levels'][level]['background']
     except KeyError:
         raise ReportParserError('No background defined for level %s' % level)
Exemplo n.º 7
0
 def __init__(self,node):
     self.finished = dict(node.find('finished').items())
     self.hosts = dict(node.find('hosts').items())
     for k in self.hosts.keys():
         try:
             self.hosts[k] = int(self.hosts[k])
         except ValueError:
             raise ReportParserError('Runstats hosts attribute %s not integer' % k)
Exemplo n.º 8
0
 def color(self,level):
     if level == 'header':
         return self['header']['color']
     level = self.__resolve_level(level)
     try:
         return self['levels'][level]['color']
     except KeyError:
         raise ReportParserError('No color defined for level %s' % level)
Exemplo n.º 9
0
 def merge_pluginlist_file(self, path, filtered_ids):
     try:
         for l in open(path, 'r').readlines():
             if l.startswith('#'): continue
             (pid, description) = l.strip().split(None, 1)
             try:
                 filtered_ids.add(int(pid))
             except ValueError:
                 sys.exit(error('Invalid Plugin ID: %s' % pid))
     except IOError, (ecode, emsg):
         raise ReportParserError(
             'Error reading filtered plugin list file %s %s' %
             (opts.filter_plugins, emsg))
Exemplo n.º 10
0
 def load_addresslist(self, values):
     self.log.debug('Loading address list %s' % values)
     addresses = []
     for address in values:
         try:
             address = IPv4Address(address)
         except ValueError:
             try:
                 address = IPv6Address(address)
             except ValueError:
                 raise ReportParserError('Invalid address: %s' % address)
         addresses.append(address)
     return addresses
Exemplo n.º 11
0
    def __init__(self, path):
        self.path = path
        self.update(dict((k, {}) for k in SEVERITY_MAP.keys()))

        if not os.path.isfile(self.path):
            raise ReportParserError('No such file: %s' % self.path)
        self.parser = BeautifulSoup(markup=open(self.path, 'r').read())

        contents = self.parser.find('div', {'id': 'contents'})
        if contents is None:
            raise ReportParserError('No table of contents found')

        self.device = None
        self.name = None
        t = self.parser.find('title').text
        for re_match in DEVICE_TITLES:
            m = re_match.match(t)
            if m:
                self.device = m.group(1)
                self.name = m.group(2)
                break

        if self.device is None or self.name is None:
            raise ReportParserError('Could not parse device type and name')

        for d in self.parser.findChildren('div'):
            d_id = d.get('id')
            if d_id is None or d_id in SKIP_DIVS:
                continue
            r = NipperReportedIssue(self, d)
            try:
                severity = filter(lambda k: r.severity in SEVERITY_MAP[k],
                                  SEVERITY_MAP.keys())[0]
            except IndexError:
                ReportParserError('Unknown severity level: %s' % r.severity)
            if not self[severity].has_key(r.issue):
                self[severity][r.issue] = []
            self[severity][r.issue].append(r)
Exemplo n.º 12
0
    def __init__(self, report, node):
        self.report = report
        self.node = node
        self.address = node.get('name')
        self.properties = NessusTargetHostProperties(
            node.find('HostProperties'))

        if self.address is None:
            raise ReportParserError('No address')
        try:
            self.address = IPv4Address(self.address)
        except ValueError:
            try:
                self.address = IPv6Address(self.address)
            except ValueError:
                self.address = IPv4Address(
                    socket.gethostbyaddr(self.address)[2][0])

        try:
            for i in self.node.findall('ReportItem'):
                self.append(NessusTargetResultItem(self, i))
        except ReportParserError, e:
            raise ReportParserError('Error parsing %s: %s' % (self.address, e))
Exemplo n.º 13
0
 def __init__(self,node):
     self.nmapscans = [ NMAPHostScan(node) ]
     try:
         self.ports = map(lambda p: 
             NMAPTargetPortEntry(p),
             node.find('ports').findall('port'),
         )
         self.addresses = map(lambda a:
             NMAPHostAddressEntry(a),
             node.findall('address'),
         )
         self.osinfo = NMAPHostOSGuesses(node.find('os'))
     except AttributeError:
         raise ReportParserError(
             'No ports or addresses in target entry %s' % node.items()
         )
Exemplo n.º 14
0
 def __init__(self,node):
     self.update(node.items())   
     if self.has_key('numservices'):
         self['numservices'] = int(self['numservices'])
     if self.has_key('services'):
         services = []
         try:
             service_list = self['services'].split(',')
             for s in service_list: 
                 try:
                     start,end = map(lambda x: int(x), s.split('-'))
                     for i in range(start,end+1):
                         services.append(i)
                 except ValueError:
                     try:
                         services.append(int(s))
                     except ValueError:
                         raise ValueError
         except ValueError:
             raise ReportParserError('Error parsing services: %s' % self['services'])
         self['services'] = services
Exemplo n.º 15
0
    def __init__(self, report, section):
        self.report = report
        m = RE_ISSUE_HEADER.match(section.find('h3').text)
        if not m:
            raise ReportParserError('Could not parse report h3 header: %s' %
                                    section)
        self.issue = m.group(1)

        for sub in section.findChildren('div'):
            sub_id = sub.get('class')
            if sub_id == 'ratings':
                self['severity'] = NipperIssueRatings(sub)
            elif sub_id == 'finding':
                self['finding'] = NipperIssueFinding(sub)
            elif sub_id == 'impact':
                self['impoct'] = NipperIssueImpact(sub)
            elif sub_id == 'ease':
                self['ease'] = NipperIssueEase(sub)
            elif sub_id == 'recommendation':
                self['recommendation'] = NipperIssueRecommendation(sub)
            else:
                print sub_id
Exemplo n.º 16
0
 def read(self,path):
     try:
         entry = NMAPXMLOutputFile(path)
     except ReportParserError,e:
         raise ReportParserError(e)
Exemplo n.º 17
0
 def __init__(self,path):
     self.path = path
     try:
         self.tree = etree.parse(self.path)
     except etree.XMLSyntaxError,e:
         raise ReportParserError('Error parsing %s: %s' % (self.path,e))
Exemplo n.º 18
0
class NessusResultSet(list):
    def __init__(self):
        self.log = logging.getLogger('modules')
        self.pluginid_hostmap = {}

    def __sortkeys__(self, *argv):
        return lambda mapping: tuple(-mapping[name[1:]]
                                     if name.startswith('-') else mapping[name]
                                     for name in argv)

    def load(self, reports, filtered, addresses=[]):
        networks = filter(lambda address:
            (type(address)==IPv4Address and address.bitmask!=32) or\
            (type(address)==IPv6Address and address.bitmask!=128),
            addresses
        )

        def match_address(address, addresses, networks):
            if address in addresses:
                return True
            networks = filter(lambda n: type(n) == type(address), networks)
            for n in networks:
                if n.addressInNetwork(address):
                    return True
            return False

        for source in reports:
            self.log.debug('Merging report with %d plugin IDs filtered: %s' %
                           (len(filtered), source))
            filtered_count = 0
            filter_address_count = 0
            for r in [
                    result for report in source for host in report
                    for result in host
            ]:
                if r.pluginID in filtered:
                    filtered_count += 1
                    continue
                if addresses != [] and not match_address(
                        r.address, addresses, networks):
                    filter_address_count += 1
                    continue
                if not self.pluginid_hostmap.has_key(r.pluginID):
                    self.pluginid_hostmap[r.pluginID] = []
                if r.port != 0:
                    r_key = '%s:%s' % (r.address.ipaddress, r.port)
                else:
                    r_key = '%s' % r.address.ipaddress
                if r_key not in self.pluginid_hostmap[r.pluginID]:
                    self.pluginid_hostmap[r.pluginID].append(r_key)
                self.append(r)
            if addresses != []:
                self.log.debug('Filtered out %d plugins %d addresses' %
                               (filtered_count, filter_address_count))
            else:
                self.log.debug('Filtered out %d plugins' % filtered_count)

    def order_by(self, *argv):
        self.log.debug('Ordering results')
        decorated = [([
            -result[k[1:]] if k.startswith('-') else result[k] for k in argv
        ], index, result) for index, result in enumerate(self)]
        decorated.sort()
        self.__delslice__(0, len(self))
        self.extend([d[-1] for d in decorated])

    def pluginid_hosts(self, result):
        self.log.debug('Grouping hosts for plugin: %s %s' %
                       (SEVERITY_NAMES[result.severity], result.pluginName))
        return [
            h.ipaddress for h in sorted(
                set(r.address for r in self if r.pluginID == result.pluginID))
        ]

    def filter(self, fn):
        self.log.debug('Filtering %d results' % len(self))
        total = len(self)
        processed = 0
        for r in self:
            processed += 1
            if not fn(r):
                self.remove(r)
            if processed % 1000 == 0:
                self.log.debug('Processed: %d/%d results' % (processed, total))

    def counters(self):
        values = dict([(r, 0) for r in range(0, 4)])
        for r in self:
            values[r.severity] += 1
        return values

    def merge_pluginlist_file(self, path, filtered_ids):
        try:
            for l in open(path, 'r').readlines():
                if l.startswith('#'): continue
                (pid, description) = l.strip().split(None, 1)
                try:
                    filtered_ids.add(int(pid))
                except ValueError:
                    sys.exit(error('Invalid Plugin ID: %s' % pid))
        except IOError, (ecode, emsg):
            raise ReportParserError(
                'Error reading filtered plugin list file %s %s' %
                (opts.filter_plugins, emsg))
        except OSError, (ecode, emsg):
            raise ReportParserError(
                'Error reading filtered plugin list file %s %s' %
                (opts.filter_plugins, emsg))
Exemplo n.º 19
0
class NessusTargetResultItem(dict):
    def __init__(self, host, node):
        self.host = host
        self.node = node
        self.name = node.get('name')
        self.update(node.items())

        for k in filter(lambda k: self.has_key(k), REPORT_INT_VALUES):
            try:
                self[k] = int(self[k])
            except ValueError:
                raise ReportParserError('Invalid integer value: %s' % self[k])

        for n in node.getchildren():
            if n.tag in REPORT_INT_VALUES:
                try:
                    self[n.tag] = int(n.text)
                except ValueError:
                    raise ReportParserError(
                        'Invalid integer value %s: %s' % n.tag, n.text)

            elif n.tag in REPORT_DECIMAL_VALUES:
                try:
                    self[n.tag] = decimal.Decimal(n.text)
                except ValueError:
                    raise ReportParserError('Invalid decimal value %s: %s' %
                                            (n.tag, n.text))

            elif n.tag in REPORT_TEXT_VALUES:
                self[n.tag] = []
                for l in n.text.split('\n'):
                    if l.strip() == '':
                        continue
                    self[n.tag].append(l)

            elif n.tag in REPORT_DATE_VALUES:
                dates = []
                for d in filter(lambda d: d.strip(), n.text.split()):
                    try:
                        dates.append(time.strptime(d, '%Y/%m/%d'))
                    except ValueError, e:
                        raise ReportParserError('Invalid date %s: %s' % (k, d))
                self[n.tag] = dates

            elif n.tag in REPORT_BOOLEAN_VALUES:
                if n.text.lower() in ['true', 'yes']:
                    self[n.tag] = True
                else:
                    self[n.tag] = False

            elif n.tag == 'plugin_version':
                plugin_version = None
                for rev in NESSUS_PLUGIN_REVISION_MATCHES:
                    m = rev.match(n.text)
                    if not m:
                        continue
                    plugin_version = m.group(1)
                    break
                if plugin_version is None:
                    raise ReportParserError('Unknown plugin version %s' % pv)
                self['plugin_version'] = plugin_version
Exemplo n.º 20
0
            elif n.tag == 'plugin_version':
                plugin_version = None
                for rev in NESSUS_PLUGIN_REVISION_MATCHES:
                    m = rev.match(n.text)
                    if not m:
                        continue
                    plugin_version = m.group(1)
                    break
                if plugin_version is None:
                    raise ReportParserError('Unknown plugin version %s' % pv)
                self['plugin_version'] = plugin_version

            elif n.tag == 'plugin_type':
                if n.text not in NESSUS_PLUGIN_TYPES:
                    raise ReportParserError('Unknown plugin types: %s' %
                                            n.text)
                self[n.tag] = n.text

            elif n.tag == 'solution':
                if n.text.lower() in ['n/a', '']:
                    self['solution'] = None
                else:
                    self['solution'] = n.text

            elif n.tag == 'risk_factor':
                if n.text in ['None', '']:
                    self[n.tag] = None
                else:
                    self[n.tag] = n.text

            elif n.tag in REPORT_REFERENCE_FIELDS: