Exemple #1
0
 def __iterate_data(self, identities = None, data_type = None, data_subtype = None):
     if identities is None:
         identities = list(Database.keys(data_type))
     if identities:
         for page in xrange(0, len(identities), 100):
             for data in Database.get_many(identities[page:page + 100], data_type):
                 yield data
Exemple #2
0
 def import_results(self, input_file):
     results = NmapScanPlugin.parse_nmap_results(None, input_file)
     if results:
         Database.async_add_many(results)
         Logger.log("Loaded %d elements from file: %s" % (len(results), input_file))
     else:
         Logger.log_verbose("No data found in file: %s" % input_file)
Exemple #3
0
    def notify_summary(self, audit_name):
        """
        This method is called when an audit ends and when a plugin ends.

        :param audit_name: Name of the audit.
        :type audit_name: str
        """

        # Get the number of vulnerabilities in the database.
        vulns_number = Database.count(Data.TYPE_VULNERABILITY)

        # Count the vulnerabilities by severity.
        vulns_counter = collections.defaultdict(int)
        for l_vuln in Database.iterate(Data.TYPE_VULNERABILITY):
            vulns_counter[l_vuln.level] += 1

        # Get the number of IP addresses and hostnames.
        total_hosts  = Database.count(Data.TYPE_RESOURCE,
                                           Resource.RESOURCE_DOMAIN)
        total_hosts += Database.count(Data.TYPE_RESOURCE,
                                           Resource.RESOURCE_IP)

        # Substract the ones that were passed as targets.
        discovered_hosts = total_hosts - len(Config.audit_scope.targets)
        discovered_hosts = discovered_hosts if discovered_hosts > 0 else 0

        # Send the summary.
        packet = ("summary", audit_name, vulns_number, discovered_hosts, total_hosts,
                  vulns_counter['info'], vulns_counter['low'], vulns_counter['medium'],
                  vulns_counter['high'], vulns_counter['critical'],)
        self.bridge.send(packet)
Exemple #4
0
 def import_results(self, input_file):
     results, count = SSLScanPlugin.parse_sslscan_results(input_file)
     if results:
         Database.async_add_many(results)
         Logger.log("Loaded %d hosts and %d vulnerabilities from file: %s" %
                    (len(results) - count, count, input_file))
     else:
         Logger.log_verbose("No data found in file: %s" % input_file)
Exemple #5
0
 def import_results(self, input_file):
     try:
         results, vuln_count = NiktoPlugin.parse_nikto_results(
             None, input_file)
         if results:
             Database.async_add_many(results)
     except Exception, e:
         Logger.log_error(
             "Could not load Nikto results from file: %s" % input_file)
         Logger.log_error_verbose(str(e))
         Logger.log_error_more_verbose(format_exc())
Exemple #6
0
 def import_results(self, input_file):
     try:
         openvas_results = report_parser(input_file);
         golismero_results = OpenVASPlugin.parse_results(openvas_results)
         if golismero_results:
             Database.async_add_many(golismero_results)
     except Exception, e:
         fmt = format_exc()
         Logger.log_error(
             "Could not load OpenVAS results from file: %s" % input_file)
         Logger.log_error_verbose(str(e))
         Logger.log_error_more_verbose(fmt)
Exemple #7
0
 def import_results(self, input_file):
     try:
         xml_results       = etree.parse(input_file)
         openvas_results   = VulnscanManager.transform(xml_results.getroot())
         golismero_results = OpenVASPlugin.parse_results(openvas_results)
         if golismero_results:
             Database.async_add_many(golismero_results)
     except Exception, e:
         Logger.log_error(
             "Could not load OpenVAS results from file: %s" % input_file)
         Logger.log_error_verbose(str(e))
         Logger.log_error_more_verbose(format_exc())
Exemple #8
0
def test_import():
    print "Testing OpenVAS importer..."
    orchestrator_config = OrchestratorConfig()
    orchestrator_config.ui_mode = "disabled"
    audit_config = AuditConfig()
    audit_config.targets  = ["192.168.56.101"]
    audit_config.audit_db = ":memory:"
    with PluginTester(orchestrator_config, audit_config) as t:
        t.run_plugin("import/xml_openvas", path.join(here, "test_openvas.xml"))
        results = Database.get_many( Database.keys(Data.TYPE_VULNERABILITY) )
        assert len(results) == 1, len(results)
        v = results[0]
        assert v.level == "informational", v.level
        assert v.plugin_id == "import/xml_openvas", v.plugin_id
        assert "Remote web server does not reply with 404 error code." in v.description, v.description
    def do_audit_results(self, audit_name, data_type = "all"): # TODO: control audits with error at start
        """
        Implementation of: /audit/results

        :param audit_name: Name of the audit to query.
        :type audit_name: str

        :param data_type: Data type to request. Case insensitive.
            Must be one of the following values:
             - "all": All data types.
             - "information": Information type.
             - "resource": Resource type.
             - "vulnerability": Vulnerability type.
        :type data_type: str

        :returns: Result IDs.
        :rtype: list(str)

        :raises KeyError: Data type unknown.
        """
        if self.is_audit_running(audit_name):
            with SwitchToAudit(audit_name):
                i_data_type = {
                    "all": None,
                    "information": Data.TYPE_INFORMATION,
                    "resource": Data.TYPE_RESOURCE,
                    "vulnerability": Data.TYPE_VULNERABILITY,
                    }[data_type.strip().lower()]
                return sorted( Database.keys(i_data_type) )
        else:
            # XXX TODO open the database manually here
            raise NotImplementedError(
                "Querying finished audits is not implemented yet!")
Exemple #10
0
    def do_scan_details(self, id_list):
        """
        Implementation of: /scan/details

        :param id_list: List of result IDs.
        :type id_list: list(str)
        """
        return Database.get_many(id_list)
Exemple #11
0
    def common_get_resources(self, data_type=None, data_subtype=None):
        """
        Get a list of datas.

        :return: List of resources.
        :rtype: list(Resource)
        """
        # Get each resource
        m_resource = None
        m_len_urls = Database.count(data_type, data_type)
        if m_len_urls < 200:   # increase as you see fit...
            # fast but memory consuming method
            m_resource   = Database.get_many( Database.keys(data_type=data_type, data_subtype=data_subtype))
        else:
            # slow but lean method
            m_resource   = Database.iterate(data_type=data_type, data_subtype=data_subtype)

        return m_resource
Exemple #12
0
 def recv_info(self, info):
     if not isinstance(info, Data):
         raise TypeError("Expected Data, got %r instead" % type(info))
     print "-" * 79
     print "ID:   %s" % info.identity
     print "Data: %r" % info
     history = Database.get_plugin_history(info.identity)
     if history:
         print "History:"
         for plugin_id in history:
             print "  " + plugin_id
     print
Exemple #13
0
    def __common_get_resources(self, data_type=None, data_subtype=None):
        """
        Get a list of datas.

        :return: List of resources.
        :rtype: list(Resource)
        """
        # Get each resource
        m_resource = None
        m_len_urls = Database.count(data_type, data_type)
        if m_len_urls < 200:  # increase as you see fit...
            # fast but memory consuming method
            m_resource = Database.get_many(
                Database.keys(data_type=data_type, data_subtype=data_subtype))
        else:
            # slow but lean method
            m_resource = list(
                Database.iterate(data_type=data_type,
                                 data_subtype=data_subtype))

        return m_resource
Exemple #14
0
 def run(self, info):
     if not isinstance(info, Data):
         raise TypeError("Expected Data, got %r instead" % type(info))
     print "-" * 79
     print "ID:   %s" % info.identity
     print "Data: %r" % info
     history = Database.get_plugin_history(info.identity)
     if history:
         print "History:"
         for plugin_id in history:
             print "  " + plugin_id
     print
Exemple #15
0
    def generate_report(self, output_file):

        # Dump all objects in the database.
        print "-" * 79
        print "Report:"
        for data in Database.iterate():
            print
            print data.identity
            print repr(data)
            print sorted(data.links)
            for linked in data.linked_data:
                print "--> " + linked.identity
                print "--> " + repr(linked)
        print
Exemple #16
0
    def generate_report(self, output_file):

        # Dump all objects in the database.
        print "-" * 79
        print "Report:"
        for data in Database.iterate():
            print
            print data.identity
            print repr(data)
            print sorted(data.links)
            for linked in data.linked_data:
                print "--> " + linked.identity
                print "--> " + repr(linked)
        print
    def do_audit_details(self, audit_name, id_list): # TODO: control audits with error at start
        """
        Implementation of: /audit/details

        :param audit_name: Name of the audit to query.
        :type audit_name: str

        :param id_list: List of result IDs.
        :type id_list: list(str)
        """
        if self.is_audit_running(audit_name):
            with SwitchToAudit(audit_name):
                return Database.get_many(id_list)
        else:
            # XXX TODO open the database manually here
            raise NotImplementedError(
                "Querying finished audits is not implemented yet!")
    def do_audit_summary(self, audit_name):
        """
        Implementation of: /audit/summary

        :param audit_name: Name of the audit to query.
        :type audit_name: str

        :returns:
            Summary in the following format::
                {
                    'vulns_number'     : int,
                    'discovered_hosts' : int,
                    'total_hosts'      : int,
                    'vulns_by_level'   : {
                       'info'     : int,
                       'low'      : int,
                       'medium'   : int,
                       'high'     : int,
                       'critical' : int,
                    },
                }
            Returns None on error.
        :rtype: dict(str -> \\*) | None
        """
        # Checks for errors
        if audit_name in self.audit_error:
            return "error"

        try:
            if self.is_audit_running(audit_name):
                with SwitchToAudit(audit_name):

                    # Get the number of vulnerabilities in the database.
                    vulns_number = Database.count(Data.TYPE_VULNERABILITY)

                    # Count the vulnerabilities by severity.
                    vulns_counter = collections.Counter()
                    for l_vuln in Database.iterate(Data.TYPE_VULNERABILITY):
                        vulns_counter[l_vuln.level] += 1

                    # Get the number of IP addresses and hostnames.
                    total_hosts  = Database.count(Data.TYPE_RESOURCE,
                                                       Resource.RESOURCE_DOMAIN)
                    total_hosts += Database.count(Data.TYPE_RESOURCE,
                                                       Resource.RESOURCE_IP)

                # Substract the ones that were passed as targets.
                discovered_hosts = total_hosts - len(Config.audit_scope.targets)

                # Return the data in the expected format.
                return {
                    'vulns_number'     : vulns_number,
                    'discovered_hosts' : discovered_hosts,
                    'total_hosts'      : total_hosts,
                    'vulns_by_level'   : {
                        'info'     : vulns_counter['info'],
                        'low'      : vulns_counter['low'],
                        'medium'   : vulns_counter['medium'],
                        'high'     : vulns_counter['high'],
                        'critical' : vulns_counter['critical'],
                    }
                }

            else:
                # XXX TODO open the database manually here
                raise NotImplementedError(
                    "Querying finished audits is not implemented yet!")

        except Exception:
            Logger.log_error(traceback.format_exc())
Exemple #19
0
 def __iterate(self, data_type = None, data_subtype = None):
     if Database.count(data_type, data_type) < 100:
         return Database.get_many(
             Database.keys(data_type=data_type, data_subtype=data_subtype)
         )
     return Database.iterate(data_type=data_type, data_subtype=data_subtype)
Exemple #20
0
    def __write_report(self):

        # Header
        print >>self.__fd, ""
        print >>self.__fd, "--= %s =--" % self.__colorize("Report", "cyan")
        print >>self.__fd, ""

        # Summary
        start_time, stop_time, run_time = parse_audit_times( *get_audit_times() )
        host_count  = Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_DOMAIN)
        host_count += Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_IP)
        vuln_count  = Database.count(Data.TYPE_VULNERABILITY)
        print >>self.__fd, "-# %s #- " % self.__colorize("Summary", "yellow")
        print >>self.__fd, ""
        print >>self.__fd, "Audit started:   %s" % self.__colorize(start_time, "yellow")
        print >>self.__fd, "Audit ended:     %s" % self.__colorize(stop_time, "yellow")
        print >>self.__fd, "Execution time:  %s" % self.__colorize(run_time, "yellow")
        print >>self.__fd, ""
        print >>self.__fd, "Scanned hosts:   %s" % self.__colorize(str(host_count), "yellow")
        print >>self.__fd, "Vulnerabilities: %s" % self.__colorize(str(vuln_count), "red" if vuln_count else "yellow")
        print >>self.__fd, ""

        # Audit scope
        if self.__show_data or not self.__console:
            table = Texttable()
            scope_domains = ["*." + r for r in Config.audit_scope.roots]
            scope_domains.extend(Config.audit_scope.domains)
            if Config.audit_scope.addresses:
                table.add_row(("IP addresses", "\n".join(Config.audit_scope.addresses)))
            if scope_domains:
                table.add_row(("Domains", "\n".join(scope_domains)))
            if Config.audit_scope.web_pages:
                table.add_row(("Web pages", "\n".join(Config.audit_scope.web_pages)))
            if table._rows:
                self.__fix_table_width(table)
                print >>self.__fd, "-# %s #- " % self.__colorize("Audit Scope", "yellow")
                print >>self.__fd, ""
                print >>self.__fd, table.draw()
                print >>self.__fd, ""

        # Discovered hosts
        if self.__show_data:
            need_header = True
            for domain in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_DOMAIN):
                table = Texttable()
                self.__add_related(table, domain, Data.TYPE_RESOURCE, Resource.RESOURCE_IP, "IP Address")
                self.__add_related(table, domain, Data.TYPE_INFORMATION, Information.INFORMATION_GEOLOCATION, "Location")
                self.__add_related(table, domain, Data.TYPE_INFORMATION, Information.INFORMATION_WEB_SERVER_FINGERPRINT, "Web Server")
                self.__add_related(table, domain, Data.TYPE_INFORMATION, Information.INFORMATION_OS_FINGERPRINT, "OS Fingerprint")
                if table._rows:
                    if need_header:
                        need_header = False
                        print >>self.__fd, "-# %s #- " % self.__colorize("Hosts", "yellow")
                        print >>self.__fd, ""
                    table.header(("Domain Name", domain.hostname))
                    self.__fix_table_width(table)
                    text = table.draw()
                    if self.__color:
                        text = colorize_substring(text, domain.hostname, "red" if domain.get_links(Data.TYPE_VULNERABILITY) else "green")
                    print >>self.__fd, text
                    print >>self.__fd, ""
            for ip in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_IP):
                table = Texttable()
                self.__add_related(table, ip, Data.TYPE_RESOURCE, Resource.RESOURCE_DOMAIN, "Domain Name")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_GEOLOCATION, "Location")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_WEB_SERVER_FINGERPRINT, "Web Server")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_OS_FINGERPRINT, "OS Fingerprint")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_PORTSCAN, "Port Scan")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_TRACEROUTE, "Network Route")
                if table._rows:
                    if need_header:
                        need_header = False
                        print >>self.__fd, "-# %s #- " % self.__colorize("Hosts", "yellow")
                        print >>self.__fd, ""
                    table.header(("IP Address", ip.address))
                    self.__fix_table_width(table)
                    text = table.draw()
                    if self.__color:
                        text = colorize_substring(text, ip.address, "red" if ip.get_links(Data.TYPE_VULNERABILITY) else "green")
                    print >>self.__fd, text
                    print >>self.__fd, ""

        # Web servers
        if self.__show_data and Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_BASE_URL):
            print >>self.__fd, "-# %s #- " % self.__colorize("Web Servers", "yellow")
            print >>self.__fd, ""
            crawled = defaultdict(list)
            vulnerable = []
            for url in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_URL):
                crawled[url.hostname].append(url.url)
                if self.__color and url.get_links(Data.TYPE_VULNERABILITY):
                    vulnerable.append(url)
            for url in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_BASE_URL):
                table = Texttable()
                table.header(("Base URL", url.url))
                self.__add_related(table, url, Data.TYPE_INFORMATION, Information.INFORMATION_WEB_SERVER_FINGERPRINT, "Server")
                self.__add_related(table, url, Data.TYPE_INFORMATION, Information.INFORMATION_OS_FINGERPRINT, "Platform")
                urls = crawled[url.hostname]
                if urls:
                    urls.sort()
                    table.add_row(("Visited URLs", "\n".join(urls)))
                if table._rows:
                    self.__fix_table_width(table)
                    text = table.draw()
                    if self.__color:
                        p = text.find("\n")
                        p = text.find("\n", p + 1)
                        p = text.find("\n", p + 1)
                        if p > 0:
                            text = colorize_substring(text[:p], url.url, "red" if url.get_links(Data.TYPE_VULNERABILITY) else "green") + text[p:]
                        for u in vulnerable:
                            if u != url.url:
                                text = colorize_substring(text, u, "red")
                    print >>self.__fd, text
                    print >>self.__fd, ""

        # Emails
        if self.__show_data:
            emails = {
                e.address: "red" if e.get_links(Data.TYPE_VULNERABILITY) else "green"
                for e in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_EMAIL)
            }
            if emails:
                print >>self.__fd, "-# %s #- " % self.__colorize("Email Addresses", "yellow")
                print >>self.__fd, ""
                for e in sorted(emails):
                    print >>self.__fd, "* " + self.__colorize(e, emails[e])
                print >>self.__fd, ""

        # Vulnerabilities
        print >>self.__fd, "-# %s #- " % self.__colorize("Vulnerabilities", "yellow")
        print >>self.__fd, ""
        count = Database.count(Data.TYPE_VULNERABILITY)
        if count:
            if self.__show_data:
                print >>self.__fd, self.__colorize("%d vulnerabilities found!" % count, "red")
                print >>self.__fd, ""
            vuln_types = { v.display_name: v.vulnerability_type for v in self.__iterate(Data.TYPE_VULNERABILITY) }
            titles = vuln_types.keys()
            titles.sort()
            if "Uncategorized Vulnerability" in titles:
                titles.remove("Uncategorized Vulnerability")
                titles.append("Uncategorized Vulnerability")
            for title in titles:
                data_subtype = vuln_types[title]
                print >>self.__fd, "-- %s (%s) -- " % (self.__colorize(title, "cyan"), data_subtype)
                print >>self.__fd, ""
                for vuln in self.__iterate(Data.TYPE_VULNERABILITY, data_subtype):
                    table = Texttable()
                    table.header(("Occurrence ID", vuln.identity))
                    w = len(table.draw())
                    table.add_row(("Title", vuln.title))
                    targets = [str(x) for x in vuln.associated_resources]
                    for info in vuln.associated_informations:
                        targets.extend(str(x) for x in info.associated_resources)
                    table.add_row(("Found By", get_plugin_name(vuln.plugin_id)))
                    p = len(table.draw())
                    table.add_row(("Level", vuln.level))
                    table.add_row(("Impact", vuln.impact))
                    table.add_row(("Severity", vuln.severity))
                    table.add_row(("Risk", vuln.risk))
                    q = len(table.draw())
                    if vuln.cvss_base:
                        table.add_row(("CVSS Base", vuln.cvss_base))
                    if vuln.cvss_base_vector:
                        table.add_row(("CVSS Base Vector", vuln.cvss_base_vector))
                    if len(targets) > 1:
                        targets.sort()
                        table.add_row(("Locations", "\n".join(targets)))
                    else:
                        table.add_row(("Location", targets[0]))
                    table.add_row(("Description", vuln.description))
                    table.add_row(("Solution", vuln.solution))
                    taxonomy = []
                    if vuln.bid:
                        taxonomy.extend(vuln.bid)
                    if vuln.cve:
                        taxonomy.extend(vuln.cve)
                    if vuln.cwe:
                        taxonomy.extend(vuln.cwe)
                    if vuln.osvdb:
                        taxonomy.extend(vuln.osvdb)
                    if vuln.sa:
                        taxonomy.extend(vuln.sa)
                    if vuln.sectrack:
                        taxonomy.extend(vuln.sectrack)
                    if vuln.xf:
                        taxonomy.extend(vuln.xf)
                    if taxonomy:
                        table.add_row(("Taxonomy", "\n".join(taxonomy)))
                    if vuln.references:
                        table.add_row(("References", "\n".join(sorted(vuln.references))))
                    details = vuln.display_properties["Details"]
                    if details:
                        props = details.keys()
                        props.sort()
                        table.add_row(("Additional details", "\n".join(("%s: %s" % (x, details[x])) for x in props)))
                    self.__fix_table_width(table)
                    text = table.draw()
                    if self.__color:
                        text_1 = text[:w]
                        text_3 = text[p:q]
                        text_1 = colorize_substring(text_1, vuln.identity, vuln.level.lower())
                        for lvl in Vulnerability.VULN_LEVELS:
                            if lvl in text_3:
                                text_3 = colorize_substring(text_3, lvl, lvl.lower())
                        text = text_1 + text[w:p] + text_3 + text[q:]
                    print >>self.__fd, text
                    print >>self.__fd, ""
        else:
            print >>self.__fd, self.__colorize("No vulnerabilities found.", "green")
            print >>self.__fd, ""
Exemple #21
0
 def __iterate(self, data_type = None, data_subtype = None):
     if Database.count(data_type=data_type, data_subtype=data_subtype) <100:
         return Database.get_many(
             Database.keys(data_type=data_type, data_subtype=data_subtype)
         )
     return Database.iterate(data_type=data_type, data_subtype=data_subtype)
Exemple #22
0
             - "resource": Resource type.
             - "vulnerability": Vulnerability type.
        :type data_type: str

        :returns: Result IDs.
        :rtype: list(str)

        :raises KeyError: Data type unknown.
        """
        i_data_type = {
                      "all": None,
              "information": Data.TYPE_INFORMATION,
                 "resource": Data.TYPE_RESOURCE,
            "vulnerability": Data.TYPE_VULNERABILITY,
        }[data_type.strip().lower()]
        return sorted( Database.keys(i_data_type) )


    #--------------------------------------------------------------------------
    def do_scan_details(self, id_list):
        """
        Implementation of: /scan/details

        :param id_list: List of result IDs.
        :type id_list: list(str)
        """
        return Database.get_many(id_list)


    #--------------------------------------------------------------------------
    def do_plugin_list(self):
Exemple #23
0
    def __write_report(self):

        # Header
        print >>self.__fd, ""
        print >>self.__fd, "--= %s =--" % self.__colorize("Report", "cyan")
        print >>self.__fd, ""

        # Summary
        start_time, stop_time, run_time = parse_audit_times( *get_audit_times() )
        host_count  = Database.count(Data.TYPE_RESOURCE, Domain.data_subtype)
        host_count += Database.count(Data.TYPE_RESOURCE, IP.data_subtype)
        vuln_count  = Database.count(Data.TYPE_VULNERABILITY)
        print >>self.__fd, "-# %s #- " % self.__colorize("Summary", "yellow")
        print >>self.__fd, ""
        print >>self.__fd, "Audit started:   %s" % self.__colorize(start_time, "yellow")
        print >>self.__fd, "Audit ended:     %s" % self.__colorize(stop_time, "yellow")
        print >>self.__fd, "Execution time:  %s" % self.__colorize(run_time, "yellow")
        print >>self.__fd, ""
        print >>self.__fd, "Scanned hosts:   %s" % self.__colorize(str(host_count), "yellow")
        print >>self.__fd, "Vulnerabilities: %s" % self.__colorize(str(vuln_count), "red" if vuln_count else "yellow")
        print >>self.__fd, ""

        # Audit scope
        if self.__show_data or not self.__console:
            table = Texttable()
            scope_domains = ["*." + r for r in Config.audit_scope.roots]
            scope_domains.extend(Config.audit_scope.domains)
            if Config.audit_scope.addresses:
                table.add_row(("IP addresses", "\n".join(Config.audit_scope.addresses)))
            if scope_domains:
                table.add_row(("Domains", "\n".join(scope_domains)))
            if Config.audit_scope.web_pages:
                table.add_row(("Web pages", "\n".join(Config.audit_scope.web_pages)))
            if table._rows:
                self.__fix_table_width(table)
                print >>self.__fd, "-# %s #- " % self.__colorize("Audit Scope", "yellow")
                print >>self.__fd, ""
                print >>self.__fd, table.draw()
                print >>self.__fd, ""

        # Discovered hosts
        if self.__show_data:
            need_header = True
            for domain in self.__iterate(Data.TYPE_RESOURCE, Domain.data_subtype):
                table = Texttable()
                self.__add_related(table, domain, Data.TYPE_RESOURCE, IP.data_subtype, "IP Address")
                self.__add_related(table, domain, Data.TYPE_INFORMATION, Geolocation.data_subtype, "Location")
                self.__add_related(table, domain, Data.TYPE_INFORMATION, WebServerFingerprint.data_subtype, "Web Server")
                self.__add_related(table, domain, Data.TYPE_INFORMATION, OSFingerprint.data_subtype, "OS Fingerprint")
                if table._rows:
                    if need_header:
                        need_header = False
                        print >>self.__fd, "-# %s #- " % self.__colorize("Hosts", "yellow")
                        print >>self.__fd, ""
                    table.header(("Domain Name", domain.hostname))
                    self.__fix_table_width(table)
                    text = table.draw()
                    if self.__color:
                        text = colorize_substring(text, domain.hostname, "red" if domain.get_links(Data.TYPE_VULNERABILITY) else "green")
                    print >>self.__fd, text
                    print >>self.__fd, ""
            for ip in self.__iterate(Data.TYPE_RESOURCE, IP.data_subtype):
                table = Texttable()
                self.__add_related(table, ip, Data.TYPE_RESOURCE, Domain.data_subtype, "Domain Name")
                self.__add_related(table, ip, Data.TYPE_RESOURCE, MAC.data_subtype, "MAC Address")
                self.__add_related(table, ip, Data.TYPE_RESOURCE, BSSID.data_subtype, "WiFi 802.11 BSSID")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, Geolocation.data_subtype, "Location")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, WebServerFingerprint.data_subtype, "Web Server")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, OSFingerprint.data_subtype, "OS Fingerprint")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, ServiceFingerprint.data_subtype, "Service")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, Portscan.data_subtype, "Port Scan")
                self.__add_related(table, ip, Data.TYPE_INFORMATION, Traceroute.data_subtype, "Network Route")
                if table._rows:
                    if need_header:
                        need_header = False
                        print >>self.__fd, "-# %s #- " % self.__colorize("Hosts", "yellow")
                        print >>self.__fd, ""
                    table.header(("IP Address", ip.address))
                    self.__fix_table_width(table)
                    text = table.draw()
                    if self.__color:
                        text = colorize_substring(text, ip.address, "red" if ip.get_links(Data.TYPE_VULNERABILITY) else "green")
                    print >>self.__fd, text
                    print >>self.__fd, ""

        # Web servers
        if self.__show_data and Database.count(Data.TYPE_RESOURCE, BaseURL.data_subtype):
            print >>self.__fd, "-# %s #- " % self.__colorize("Web Servers", "yellow")
            print >>self.__fd, ""
            crawled = defaultdict(list)
            vulnerable = []
            for url in self.__iterate(Data.TYPE_RESOURCE, URL.data_subtype):
                crawled[url.hostname].append(url.url)
                if self.__color and url.get_links(Data.TYPE_VULNERABILITY):
                    vulnerable.append(url)
            for url in self.__iterate(Data.TYPE_RESOURCE, BaseURL.data_subtype):
                table = Texttable()
                table.header(("Base URL", url.url))
                self.__add_related(table, url, Data.TYPE_INFORMATION, WebServerFingerprint.data_subtype, "Server")
                self.__add_related(table, url, Data.TYPE_INFORMATION, OSFingerprint.data_subtype, "Platform")
                urls = crawled[url.hostname]
                if urls:
                    urls.sort()
                    table.add_row(("Visited URLs", "\n".join(urls)))
                if table._rows:
                    self.__fix_table_width(table)
                    text = table.draw()
                    if self.__color:
                        p = text.find("\n")
                        p = text.find("\n", p + 1)
                        p = text.find("\n", p + 1)
                        if p > 0:
                            text = colorize_substring(text[:p], url.url, "red" if url.get_links(Data.TYPE_VULNERABILITY) else "green") + text[p:]
                        for u in vulnerable:
                            if u != url.url:
                                text = colorize_substring(text, u, "red")
                    print >>self.__fd, text
                    print >>self.__fd, ""

        # Emails
        if self.__show_data:
            emails = {
                e.address: "red" if e.get_links(Data.TYPE_VULNERABILITY) else "green"
                for e in self.__iterate(Data.TYPE_RESOURCE, Email.data_subtype)
            }
            if emails:
                print >>self.__fd, "-# %s #- " % self.__colorize("Email Addresses", "yellow")
                print >>self.__fd, ""
                for e in sorted(emails):
                    print >>self.__fd, "* " + self.__colorize(e, emails[e])
                print >>self.__fd, ""

        # Vulnerabilities
        print >>self.__fd, "-# %s #- " % self.__colorize("Vulnerabilities", "yellow")
        print >>self.__fd, ""
        count = Database.count(Data.TYPE_VULNERABILITY)
        if count:
            if self.__show_data:
                print >>self.__fd, self.__colorize("%d vulnerabilities found!" % count, "red")
                print >>self.__fd, ""
            vuln_types = { v.display_name: v.vulnerability_type for v in self.__iterate(Data.TYPE_VULNERABILITY) }
            titles = vuln_types.keys()
            titles.sort()
            if "Uncategorized Vulnerability" in titles:
                titles.remove("Uncategorized Vulnerability")
                titles.append("Uncategorized Vulnerability")
            for title in titles:
                data_subtype = vuln_types[title]
                print >>self.__fd, "-- %s (%s) -- " % (self.__colorize(title, "cyan"), data_subtype)
                print >>self.__fd, ""
                for vuln in self.__iterate(Data.TYPE_VULNERABILITY, data_subtype):
                    table = Texttable()
                    table.header(("Occurrence ID", vuln.identity))
                    w = len(table.draw())
                    table.add_row(("Title", vuln.title))
                    ##targets = self.__gather_vulnerable_resources(vuln)
                    targets = [vuln.target]
                    table.add_row(("Found By", get_plugin_name(vuln.plugin_id)))
                    p = len(table.draw())
                    table.add_row(("Level", vuln.level))
                    #table.add_row(("Impact", vuln.impact))
                    #table.add_row(("Severity", vuln.severity))
                    #table.add_row(("Risk", vuln.risk))
                    q = len(table.draw())
                    if vuln.cvss_base:
                        table.add_row(("CVSS Base", vuln.cvss_base))
                    if vuln.cvss_score:
                        table.add_row(("CVSS Score", vuln.cvss_score))
                    if vuln.cvss_vector:
                        table.add_row(("CVSS Vector", vuln.cvss_vector))
                    if len(targets) > 1:
                        targets.sort()
                        table.add_row(("Locations", "\n".join(targets)))
                    elif targets:
                        table.add_row(("Location", targets[0]))
                    table.add_row(("Description", vuln.description))
                    table.add_row(("Solution", vuln.solution))
                    taxonomy = []
                    if vuln.bid:
                        taxonomy.extend(vuln.bid)
                    if vuln.cve:
                        taxonomy.extend(vuln.cve)
                    if vuln.cwe:
                        taxonomy.extend(vuln.cwe)
                    if vuln.osvdb:
                        taxonomy.extend(vuln.osvdb)
                    if vuln.sa:
                        taxonomy.extend(vuln.sa)
                    if vuln.sectrack:
                        taxonomy.extend(vuln.sectrack)
                    if vuln.xf:
                        taxonomy.extend(vuln.xf)
                    if taxonomy:
                        table.add_row(("Taxonomy", "\n".join(taxonomy)))
                    if vuln.references:
                        table.add_row(("References", "\n".join(sorted(vuln.references))))
                    details = vuln.display_properties.get("Details")
                    if details:
                        props = details.keys()
                        props.sort()
                        table.add_row(("Additional details", "\n".join(("%s: %s" % (x, details[x])) for x in props)))
                    self.__fix_table_width(table)
                    text = table.draw()
                    if self.__color:
                        text_1 = text[:w]
                        text_3 = text[p:q]
                        text_1 = colorize_substring(text_1, vuln.identity, vuln.level.lower())
                        for lvl in Vulnerability.VULN_LEVELS:
                            if lvl in text_3:
                                text_3 = colorize_substring(text_3, lvl, lvl.lower())
                        text = text_1 + text[w:p] + text_3 + text[q:]
                    print >>self.__fd, text
                    print >>self.__fd, ""
        else:
            print >>self.__fd, self.__colorize("No vulnerabilities found.", "green")
            print >>self.__fd, ""