Beispiel #1
0
    def generate_report(self, output_file):
        Logger.log_verbose(
            "Writing CSV report to file: %s" % output_file)

        # All rows have the same format but the first.
        # There's always 26 columns in every row.
        # Most columns are for Vulnerability objects, empty for other types.
        # Read the source code for more details, it's really simple. :)

        # Open the output file.
        with open(output_file, "w") as f:
            writer = csv.writer(f)

            # Write the first row, describing the report itself.
            report_time = datetime.utcnow()
            start_time, stop_time, run_time = parse_audit_times(
                                                        *get_audit_times())
            row = [
                "GoLismero " + VERSION,
                1,  # format version
                Config.audit_name,
                start_time,
                stop_time,
                run_time,
                report_time,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                pickle.dumps(Config.audit_config, protocol=0).encode("hex"),
                pickle.dumps(Config.audit_scope, protocol=0).encode("hex"),
            ]
            row = [to_utf8(x) if x is not None else "" for x in row]
            writer.writerow(row)

            # Used to convert the false_positive flag to a string value.
            fp = {
                True: 1,
                False: 0,
                None: -1,
            }

            # Just the vulnerabilities?
            if Config.audit_config.only_vulns:

                # Dump only Vulnerability objects that are not false positives.
                for vuln in self.__iterate_data(
                        data_type=Data.TYPE_VULNERABILITY):
                    if vuln.false_positive:
                        continue
                    target = vuln.target
                    row = [
                        vuln.identity,
                        vuln.data_type,
                        vuln.data_subtype,
                        None,
                        vuln.display_name,
                        vuln.plugin_id,
                        vuln.tool_id,
                        vuln.custom_id,
                        vuln.level,
                        vuln.risk,
                        vuln.severity,
                        vuln.impact,
                        vuln.cvss_base,
                        vuln.cvss_score,
                        vuln.cvss_vector,
                        fp[vuln.false_positive],
                        target.identity,
                        target.display_name,
                        vuln.title,
                        vuln.description,
                        vuln.solution,
                        "\n".join(vuln.references),
                        "\n".join(vuln.taxonomies),
                        str(target),
                        pickle.dumps(vuln, protocol=0).encode("hex"),
                        pickle.dumps(target, protocol=0).encode("hex"),
                    ]
                    row = [to_utf8(x) if x is not None else "" for x in row]
                    writer.writerow(row)

            # Full database dump?
            else:

                # Dump all objects in the database.
                for data in self.__iterate_data():
                    if data.data_type == Data.TYPE_VULNERABILITY:
                        vuln = data
                        target = vuln.target
                        row = [
                            vuln.identity,
                            vuln.data_type,
                            vuln.data_subtype,
                            None,
                            vuln.display_name,
                            vuln.plugin_id,
                            vuln.tool_id,
                            vuln.custom_id,
                            vuln.level,
                            vuln.risk,
                            vuln.severity,
                            vuln.impact,
                            vuln.cvss_base,
                            vuln.cvss_score,
                            vuln.cvss_vector,
                            fp[vuln.false_positive],
                            target.identity,
                            target.display_name,
                            vuln.title,
                            vuln.description,
                            vuln.solution,
                            "\n".join(vuln.references),
                            "\n".join(vuln.taxonomies),
                            str(target),
                            pickle.dumps(vuln, protocol=0).encode("hex"),
                            pickle.dumps(target, protocol=0).encode("hex"),
                        ]
                    else:
                        row = [
                            data.identity,
                            data.data_type,
                            data.data_subtype,
                            getattr(data, "category", None),
                            data.display_name,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            0,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            str(data),
                            None,
                            pickle.dumps(data, protocol=0).encode("hex"),
                        ]
                    row = [to_utf8(x) if x is not None else "" for x in row]
                    writer.writerow(row)
Beispiel #2
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, ""
Beispiel #3
0
    def write_report_to_open_file(self, f):
        """
        Write the report into the given open file.

        :param f: Open file.
        :type f: file
        """

        # Determine the report type.
        self.__full_report = not Config.audit_config.only_vulns

        # Print the main header.
        print >>f, "GoLismero Report"
        print >>f, "================"
        print >>f, ""
        print >>f, ".. title:: %s - GoLismero" % self.__format_rst(Config.audit_name)
        print >>f, ""
        print >>f, ".. footer:: Report generation date: %s UTC" % datetime.utcnow()
        print >>f, ""
        print >>f, ".. contents:: Table of Contents"
        print >>f, "   :depth: 3"
        print >>f, "   :backlinks: top"
        print >>f, ""

        # Print the summary.
        start_time, stop_time, run_time = parse_audit_times( *get_audit_times() )
        print >>f, "Summary"
        print >>f, "-------"
        print >>f, ""
        print >>f, "- Audit name: " + self.__format_rst(Config.audit_name)
        print >>f, "- Start date: " + start_time
        print >>f, "- End date: " + stop_time
        print >>f, "- Execution time: " + run_time
        print >>f, "- Report type: " + (
            "Full" if self.__full_report else "Brief")
        print >>f, ""

        # Print the audit scope.
        print >>f, "Audit Scope"
        print >>f, "-----------"
        print >>f, ""
        print >>f, "- IP Addresses: "
        for address in Config.audit_scope.addresses:
            print >>f, "  + " + self.__format_rst(address)
        print >>f, "- Domains:"
        scope_domains = ["*." + r for r in Config.audit_scope.roots]
        scope_domains.extend(Config.audit_scope.domains)
        for domain in scope_domains:
            print >>f, "  + " + self.__format_rst(domain)
        print >>f, "- Web Pages:"
        for url in Config.audit_scope.web_pages:
            print >>f, "  + " + self.__format_rst(url)
        print >>f, ""

        # Collect the vulnerabilities that are not false positives.
        datas = self.__collect_vulns(False)

        # If it's a brief report and we have no vulnerabilities,
        # write a message and stop.
        if not datas and not self.__full_report:
            print >>f, "No vulnerabilities found."
            print >>f, ""
            return

        # Collect the false positives.
        # In brief mode, this is used to eliminate the references to them.
        fp = self.__collect_vulns(True)
        self.__fp = set()
        for ids in fp.itervalues():
            self.__fp.update(ids)

        try:

            # This dictionary tracks which data to show
            # and which not to in brief report mode.
            self.__vulnerable = set()

            # Report the vulnerabilities.
            if datas:
                self.__write_rst(f, datas, Data.TYPE_VULNERABILITY, "Vulnerabilities")

            try:

                # Show the resources in the report.
                datas = self.__collect_data(Data.TYPE_RESOURCE)
                if datas:
                    self.__write_rst(f, datas, Data.TYPE_RESOURCE,
                            "Resources" if self.__full_report else "Assets")

                # Show the informations in the report.
                datas = self.__collect_data(Data.TYPE_INFORMATION)
                if datas:
                    self.__write_rst(f, datas, Data.TYPE_INFORMATION,
                            "Informations" if self.__full_report else "Evidences")

            finally:
                self.__vulnerable.clear()

        finally:
            self.__fp.clear()

        # Show the false positives in the full report.
        if self.__full_report and fp:
            self.__write_rst(f, fp, Data.TYPE_VULNERABILITY, "False Positives")
Beispiel #4
0
    def generate_report(self, output_file):
        Logger.log_verbose("Writing audit results to file: %s" % output_file)

        # Determine the report type.
        self.__full_report = not Config.audit_config.only_vulns

        # Parse the audit times.
        report_time = "%s UTC" % datetime.utcnow()
        start_time, stop_time = get_audit_times()
        start_time, stop_time, run_time = parse_audit_times(
            start_time, stop_time)

        # Create the root element.
        xml = ET.Element("golismero")
        xml.set("audit_name", Config.audit_name)
        if start_time:
            xml.set("start_time", start_time)
        if stop_time:
            xml.set("stop_time", stop_time)
        if run_time:
            xml.set("run_time", run_time)
        xml.set("report_time", report_time)
        xml.set("report_type", "full" if self.__full_report else "brief")

        # Create the audit scope element and subelements.
        xml_scope = ET.SubElement(xml, "audit_scope")
        for address in Config.audit_scope.addresses:
            xml_ip = ET.SubElement(xml_scope, "address")
            xml_ip.text = address
        for root_domain in Config.audit_scope.roots:
            xml_root = ET.SubElement(xml_scope, "root_domain")
            xml_root.text = root_domain
        for domain in Config.audit_scope.domains:
            xml_domain = ET.SubElement(xml_scope, "domain")
            xml_domain.text = domain
        for web_page in Config.audit_scope.web_pages:
            xml_web = ET.SubElement(xml_scope, "web_page")
            xml_web.text = web_page

        # Collect the vulnerabilities that are not false positives.
        datas = self.__collect_vulns(False)

        # If we have vulnerabilities and/or it's a full report...
        if datas or self.__full_report:

            # Collect the false positives.
            # In brief mode, this is used to eliminate the references to them.
            fp = self.__collect_vulns(True)
            self.__fp = set(fp)

            try:
                # Report the vulnerabilities.
                if datas:
                    xml_vulns = ET.SubElement(xml, "vulnerabilities")
                    self.__add_to_xml(xml_vulns, datas,
                                      Data.TYPE_VULNERABILITY, "vulnerability")

                # This dictionary tracks which data to show
                # and which not to in brief report mode.
                self.__vulnerable = set()

                try:

                    # Show the resources in the report.
                    datas = self.__collect_data(Data.TYPE_RESOURCE)
                    if datas:
                        xml_res = ET.SubElement(xml, "resources")
                        self.__add_to_xml(xml_res, datas, Data.TYPE_RESOURCE,
                                         "resource")

                    # Show the informations in the report.
                    datas = self.__collect_data(Data.TYPE_INFORMATION)
                    if datas:
                        xml_info = ET.SubElement(xml, "informations")
                        self.__add_to_xml(xml_info, datas,
                                          Data.TYPE_INFORMATION, "information")

                finally:
                    self.__vulnerable.clear()

            finally:
                self.__fp.clear()

            # Show the false positives in the full report.
            if self.__full_report and fp:
                xml_fp = ET.SubElement(xml, "false_positives")
                self.__add_to_xml(xml_fp, fp, Data.TYPE_VULNERABILITY,
                                 "vulnerability")

        # Write the XML data to disk.
        tree = ET.ElementTree(xml)
        tree.write(output_file, encoding="utf-8")

        # Launch the build command, if any.
        self.launch_command(output_file)
Beispiel #5
0
    def generate_report(self, output_file):
        Logger.log_verbose("Writing reStructured text report to file: %s" %
                           output_file)

        # Open the output file.
        with open(output_file, "w") as f:

            # Print the main header.
            print >> f, "GoLismero Report"
            print >> f, "================"
            print >> f, ""
            print >> f, ".. title:: %s - GoLismero" % self.__format_rst(
                Config.audit_name)
            print >> f, ""
            print >> f, ".. footer:: Report generation date: %s" % datetime.now(
            )
            print >> f, ""
            print >> f, ".. contents:: Table of Contents"
            print >> f, "   :depth: 3"
            print >> f, "   :backlinks: top"
            print >> f, ""

            # Print the summary.
            start_time, stop_time, run_time = parse_audit_times(
                *get_audit_times())
            print >> f, "Summary"
            print >> f, "-------"
            print >> f, ""
            print >> f, "- Audit name: " + self.__format_rst(Config.audit_name)
            print >> f, "- Start date: " + start_time
            print >> f, "- End date: " + stop_time
            print >> f, "- Execution time: " + run_time
            print >> f, ""

            # Print the audit scope.
            print >> f, "Audit Scope"
            print >> f, "-----------"
            print >> f, ""
            print >> f, "- IP Addresses: "
            for address in Config.audit_scope.addresses:
                print >> f, "  + " + self.__format_rst(address)
            print >> f, "- Domains:"
            scope_domains = ["*." + r for r in Config.audit_scope.roots]
            scope_domains.extend(Config.audit_scope.domains)
            for domain in scope_domains:
                print >> f, "  + " + self.__format_rst(domain)
            print >> f, "- Web Pages:"
            for url in Config.audit_scope.web_pages:
                print >> f, "  + " + self.__format_rst(url)
            print >> f, ""

            # Determine the report type.
            self.__full_report = not Config.audit_config.only_vulns

            # Collect the vulnerabilities that are not false positives.
            datas = self.__collect_vulns(False)

            # If it's a brief report and we have no vulnerabilities,
            # write a message and stop.
            if not datas and not self.__full_report:
                print >> f, "No vulnerabilities found."
                print >> f, ""
                return

            # Collect the false positives.
            # In brief mode, this is used to eliminate the references to them.
            fp = self.__collect_vulns(True)
            self.__fp = set()
            for ids in fp.itervalues():
                self.__fp.update(ids)

            try:

                # Report the vulnerabilities.
                self.__write_rst(f, datas, Data.TYPE_VULNERABILITY,
                                 "Vulnerabilities")

                # This dictionary tracks which data to show
                # and which not to in brief report mode.
                self.__vulnerable = set()

                try:

                    # Show the resources in the report.
                    datas = self.__collect_data(Data.TYPE_RESOURCE)
                    if datas:
                        self.__write_rst(
                            f, datas, Data.TYPE_RESOURCE,
                            "Resources" if self.__full_report else "Assets")

                    # Show the informations in the report.
                    datas = self.__collect_data(Data.TYPE_INFORMATION)
                    if datas:
                        self.__write_rst(
                            f, datas, Data.TYPE_INFORMATION, "Informations"
                            if self.__full_report else "Evidences")

                finally:
                    self.__vulnerable.clear()

            finally:
                self.__fp.clear()

            # Show the false positives in the full report.
            if self.__full_report and fp:
                self.__write_rst(f, fp, Data.TYPE_VULNERABILITY,
                                 "False Positives")

        # Launch the build command, if any.
        command = Config.plugin_config.get("command", "")
        if command:
            Logger.log_verbose("Launching command: %s" % command)
            args = split(command)
            for i in xrange(len(args)):
                token = args[i]
                p = token.find("$1")
                while p >= 0:
                    if p == 0 or (p > 0 and token[p - 1] != "$"):
                        token = token[:p] + output_file + token[p + 2:]
                    p = token.find("$1", p + len(output_file))
                args[i] = token
            cwd = os.path.split(output_file)[0]
            log = lambda x: Logger.log_verbose(x[:-1]
                                               if x.endswith("\n") else x)
            run_external_tool(args[0], args[1:], cwd=cwd, callback=log)
Beispiel #6
0
    def write_report_to_open_file(self, f):
        """
        Write the report into the given open file.

        :param f: Open file.
        :type f: file
        """

        # Determine the report type.
        self.__full_report = not Config.audit_config.only_vulns

        # Print the main header.
        print >> f, "GoLismero Report"
        print >> f, "================"
        print >> f, ""
        print >> f, ".. title:: %s - GoLismero" % self.__format_rst(
            Config.audit_name)
        print >> f, ""
        print >> f, ".. footer:: Report generation date: %s UTC" % datetime.utcnow(
        )
        print >> f, ""
        print >> f, ".. contents:: Table of Contents"
        print >> f, "   :depth: 3"
        print >> f, "   :backlinks: top"
        print >> f, ""

        # Print the summary.
        start_time, stop_time, run_time = parse_audit_times(*get_audit_times())
        print >> f, "Summary"
        print >> f, "-------"
        print >> f, ""
        print >> f, "- Audit name: " + self.__format_rst(Config.audit_name)
        print >> f, "- Start date: " + start_time
        print >> f, "- End date: " + stop_time
        print >> f, "- Execution time: " + run_time
        print >> f, "- Report type: " + ("Full"
                                         if self.__full_report else "Brief")
        print >> f, ""

        # Print the audit scope.
        print >> f, "Audit Scope"
        print >> f, "-----------"
        print >> f, ""
        print >> f, "- IP Addresses: "
        for address in Config.audit_scope.addresses:
            print >> f, "  + " + self.__format_rst(address)
        print >> f, "- Domains:"
        scope_domains = ["*." + r for r in Config.audit_scope.roots]
        scope_domains.extend(Config.audit_scope.domains)
        for domain in scope_domains:
            print >> f, "  + " + self.__format_rst(domain)
        print >> f, "- Web Pages:"
        for url in Config.audit_scope.web_pages:
            print >> f, "  + " + self.__format_rst(url)
        print >> f, ""

        # Collect the vulnerabilities that are not false positives.
        datas = self.__collect_vulns(False)

        # If it's a brief report and we have no vulnerabilities,
        # write a message and stop.
        if not datas and not self.__full_report:
            print >> f, "No vulnerabilities found."
            print >> f, ""
            return

        # Collect the false positives.
        # In brief mode, this is used to eliminate the references to them.
        fp = self.__collect_vulns(True)
        self.__fp = set()
        for ids in fp.itervalues():
            self.__fp.update(ids)

        try:

            # This dictionary tracks which data to show
            # and which not to in brief report mode.
            self.__vulnerable = set()

            # Report the vulnerabilities.
            if datas:
                self.__write_rst(f, datas, Data.TYPE_VULNERABILITY,
                                 "Vulnerabilities")

            try:

                # Show the resources in the report.
                datas = self.__collect_data(Data.TYPE_RESOURCE)
                if datas:
                    self.__write_rst(
                        f, datas, Data.TYPE_RESOURCE,
                        "Resources" if self.__full_report else "Assets")

                # Show the informations in the report.
                datas = self.__collect_data(Data.TYPE_INFORMATION)
                if datas:
                    self.__write_rst(
                        f, datas, Data.TYPE_INFORMATION,
                        "Informations" if self.__full_report else "Evidences")

            finally:
                self.__vulnerable.clear()

        finally:
            self.__fp.clear()

        # Show the false positives in the full report.
        if self.__full_report and fp:
            self.__write_rst(f, fp, Data.TYPE_VULNERABILITY, "False Positives")
Beispiel #7
0
    def get_report_data(self):
        """
        Get the data to be included in the report as a Python dictionary.
        There are two supported modes: "nice" and "dump". The output mode is
        taken directly from the plugin configuration.

        :returns: Data to include in the report.
        :rtype: dict(str -> *)
        """

        # Determine the report type.
        self.__full_report = not Config.audit_config.only_vulns

        # Parse the audit times.
        report_time = str(datetime.utcnow())
        start_time, stop_time = get_audit_times()
        start_time, stop_time, run_time = parse_audit_times(
            start_time, stop_time)

        # Get the output mode.
        mode = Config.plugin_args.get("mode", "dump")
        mode = mode.replace(" ", "")
        mode = mode.replace("\r", "")
        mode = mode.replace("\n", "")
        mode = mode.replace("\t", "")
        mode = mode.lower()
        if mode not in ("dump", "nice"):
            Logger.log_error("Invalid output mode: %s" % mode)
            mode = "dump"
        self.__dumpmode = (mode == "dump")
        Logger.log_more_verbose("Output mode: %s" %
                                ("dump" if self.__dumpmode else "nice"))

        # Create the root element.
        root = dict()

        # Add the GoLismero version property.
        if self.__dumpmode:
            root["version"] = "GoLismero " + VERSION
        else:
            root["GoLismero Version"] = "GoLismero " + VERSION

        # Add the report type property.
        if self.__dumpmode:
            root["report_type"] = "full" if self.__full_report else "brief"
        else:
            root["Report Type"] = "Full" if self.__full_report else "Brief"

        # Add the summary element.
        if self.__dumpmode:
            root["summary"] = {
                "audit_name":  Config.audit_name,
                "start_time":  start_time,
                "stop_time":   stop_time,
                "run_time":    run_time,
                "report_time": report_time,
            }
        else:
            root["Summary"] = {
                "Audit Name":  Config.audit_name,
                "Start Time":  start_time,
                "Stop Time":   stop_time,
                "Run Time":    run_time,
                "Report Time": report_time,
            }

        # Add the audit scope element.
        if self.__dumpmode:
            wildcards = [ "*." + x for x in Config.audit_scope.roots ]
            root["audit_scope"] = {
                "addresses": Config.audit_scope.addresses,
                "roots":     wildcards,
                "domains":   Config.audit_scope.domains,
                "web_pages": Config.audit_scope.web_pages,
            }
        else:
            domains = [ "*." + x for x in Config.audit_scope.roots ]
            domains.extend(Config.audit_scope.domains)
            domains.sort()
            root["Audit Scope"] = {
                "IP Addresses": Config.audit_scope.addresses,
                "Domains":      domains,
                "Web Pages":    Config.audit_scope.web_pages,
            }

        # Create the elements for the data.
        key_vuln = "vulnerabilities" if self.__dumpmode else "Vulnerabilities"
        key_res  = "resources"       if self.__dumpmode else "Assets"
        key_info = "informations"    if self.__dumpmode else "Evidences"
        key_fp   = "false_positives" if self.__dumpmode else "False Positives"
        root[key_vuln] = dict()
        root[key_res]  = dict()
        root[key_info] = dict()
        root[key_fp]   = dict()

        # This dictionary tracks which data to show
        # and which not to in brief report mode.
        self.__vulnerable = set()

        try:

            # Collect the vulnerabilities that are not false positives.
            datas = self.__collect_vulns(False)

            # If we have vulnerabilities and/or it's a full report...
            if datas or self.__full_report:

                # Collect the false positives.
                # In brief mode, this is used to eliminate
                # the references to them.
                fp = self.__collect_vulns(True)
                self.__fp = set(fp)

                try:

                    # Report the vulnerabilities.
                    if datas:
                        self.__add_data(
                            root[key_vuln], datas,
                            Data.TYPE_VULNERABILITY)

                    # Show the resources in the report.
                    datas = self.__collect_data(Data.TYPE_RESOURCE)
                    if datas:
                        self.__add_data(
                            root[key_res], datas,
                            Data.TYPE_RESOURCE)

                    # Show the informations in the report.
                    datas = self.__collect_data(Data.TYPE_INFORMATION)
                    if datas:
                        self.__add_data(
                            root[key_info], datas,
                            Data.TYPE_INFORMATION)

                finally:
                    self.__fp.clear()

                # Show the false positives in the full report.
                if self.__full_report and fp:
                    self.__add_data(
                        root[key_fp], fp,
                        Data.TYPE_VULNERABILITY)

        finally:
            self.__vulnerable.clear()

        # Return the data.
        return root
Beispiel #8
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, ""
Beispiel #9
0
    def get_report_data(self):
        """
        Get the data to be included in the report as a Python dictionary.
        There are two supported modes: "nice" and "dump". The output mode is
        taken directly from the plugin configuration.

        :returns: Data to include in the report.
        :rtype: dict(str -> *)
        """

        # Determine the report type.
        self.__full_report = not Config.audit_config.only_vulns

        # Parse the audit times.
        report_time = str(datetime.utcnow())
        start_time, stop_time = get_audit_times()
        start_time, stop_time, run_time = parse_audit_times(
            start_time, stop_time)

        # Get the output mode.
        mode = Config.plugin_args.get("mode", "dump")
        mode = mode.replace(" ", "")
        mode = mode.replace("\r", "")
        mode = mode.replace("\n", "")
        mode = mode.replace("\t", "")
        mode = mode.lower()
        if mode not in ("dump", "nice"):
            Logger.log_error("Invalid output mode: %s" % mode)
            mode = "dump"
        self.__dumpmode = (mode == "dump")
        Logger.log_more_verbose("Output mode: %s" %
                                ("dump" if self.__dumpmode else "nice"))

        # Create the root element.
        root = dict()

        # Add the GoLismero version property.
        if self.__dumpmode:
            root["version"] = "GoLismero " + VERSION
        else:
            root["GoLismero Version"] = "GoLismero " + VERSION

        # Add the report type property.
        if self.__dumpmode:
            root["report_type"] = "full" if self.__full_report else "brief"
        else:
            root["Report Type"] = "Full" if self.__full_report else "Brief"

        # Add the summary element.
        if self.__dumpmode:
            root["summary"] = {
                "audit_name": Config.audit_name,
                "start_time": start_time,
                "stop_time": stop_time,
                "run_time": run_time,
                "report_time": report_time,
            }
        else:
            root["Summary"] = {
                "Audit Name": Config.audit_name,
                "Start Time": start_time,
                "Stop Time": stop_time,
                "Run Time": run_time,
                "Report Time": report_time,
            }

        # Add the audit scope element.
        if self.__dumpmode:
            wildcards = ["*." + x for x in Config.audit_scope.roots]
            root["audit_scope"] = {
                "addresses": Config.audit_scope.addresses,
                "roots": wildcards,
                "domains": Config.audit_scope.domains,
                "web_pages": Config.audit_scope.web_pages,
            }
        else:
            domains = ["*." + x for x in Config.audit_scope.roots]
            domains.extend(Config.audit_scope.domains)
            domains.sort()
            root["Audit Scope"] = {
                "IP Addresses": Config.audit_scope.addresses,
                "Domains": domains,
                "Web Pages": Config.audit_scope.web_pages,
            }

        # Create the elements for the data.
        key_vuln = "vulnerabilities" if self.__dumpmode else "Vulnerabilities"
        key_res = "resources" if self.__dumpmode else "Assets"
        key_info = "informations" if self.__dumpmode else "Evidences"
        key_fp = "false_positives" if self.__dumpmode else "False Positives"
        root[key_vuln] = dict()
        root[key_res] = dict()
        root[key_info] = dict()
        root[key_fp] = dict()

        # This dictionary tracks which data to show
        # and which not to in brief report mode.
        self.__vulnerable = set()

        try:

            # Collect the vulnerabilities that are not false positives.
            datas = self.__collect_vulns(False)

            # If we have vulnerabilities and/or it's a full report...
            if datas or self.__full_report:

                # Collect the false positives.
                # In brief mode, this is used to eliminate
                # the references to them.
                fp = self.__collect_vulns(True)
                self.__fp = set(fp)

                try:

                    # Report the vulnerabilities.
                    if datas:
                        self.__add_data(root[key_vuln], datas,
                                        Data.TYPE_VULNERABILITY)

                    # Show the resources in the report.
                    datas = self.__collect_data(Data.TYPE_RESOURCE)
                    if datas:
                        self.__add_data(root[key_res], datas,
                                        Data.TYPE_RESOURCE)

                    # Show the informations in the report.
                    datas = self.__collect_data(Data.TYPE_INFORMATION)
                    if datas:
                        self.__add_data(root[key_info], datas,
                                        Data.TYPE_INFORMATION)

                finally:
                    self.__fp.clear()

                # Show the false positives in the full report.
                if self.__full_report and fp:
                    self.__add_data(root[key_fp], fp, Data.TYPE_VULNERABILITY)

        finally:
            self.__vulnerable.clear()

        # Return the data.
        return root
Beispiel #10
0
    def generate_report(self, output_file):
        Logger.log_verbose("Writing CSV report to file: %s" % output_file)

        # All rows have the same format but the first.
        # There's always 26 columns in every row.
        # Most columns are for Vulnerability objects, empty for other types.
        # Read the source code for more details, it's really simple. :)

        # Open the output file.
        with open(output_file, "w") as f:
            writer = csv.writer(f)

            # Write the first row, describing the report itself.
            report_time = datetime.utcnow()
            start_time, stop_time, run_time = parse_audit_times(
                *get_audit_times())
            row = [
                "GoLismero " + VERSION,
                1,  # format version
                Config.audit_name,
                start_time,
                stop_time,
                run_time,
                report_time,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                pickle.dumps(Config.audit_config, protocol=0).encode("hex"),
                pickle.dumps(Config.audit_scope, protocol=0).encode("hex"),
            ]
            row = [to_utf8(x) if x is not None else "" for x in row]
            writer.writerow(row)

            # Used to convert the false_positive flag to a string value.
            fp = {
                True: 1,
                False: 0,
                None: -1,
            }

            # Just the vulnerabilities?
            if Config.audit_config.only_vulns:

                # Dump only Vulnerability objects that are not false positives.
                for vuln in self.__iterate_data(
                        data_type=Data.TYPE_VULNERABILITY):
                    if vuln.false_positive:
                        continue
                    target = vuln.target
                    row = [
                        vuln.identity,
                        vuln.data_type,
                        vuln.data_subtype,
                        None,
                        vuln.display_name,
                        vuln.plugin_id,
                        vuln.tool_id,
                        vuln.custom_id,
                        vuln.level,
                        vuln.risk,
                        vuln.severity,
                        vuln.impact,
                        vuln.cvss_base,
                        vuln.cvss_score,
                        vuln.cvss_vector,
                        fp[vuln.false_positive],
                        target.identity,
                        target.display_name,
                        vuln.title,
                        vuln.description,
                        vuln.solution,
                        "\n".join(vuln.references),
                        "\n".join(vuln.taxonomies),
                        str(target),
                        pickle.dumps(vuln, protocol=0).encode("hex"),
                        pickle.dumps(target, protocol=0).encode("hex"),
                    ]
                    row = [to_utf8(x) if x is not None else "" for x in row]
                    writer.writerow(row)

            # Full database dump?
            else:

                # Dump all objects in the database.
                for data in self.__iterate_data():
                    if data.data_type == Data.TYPE_VULNERABILITY:
                        vuln = data
                        target = vuln.target
                        row = [
                            vuln.identity,
                            vuln.data_type,
                            vuln.data_subtype,
                            None,
                            vuln.display_name,
                            vuln.plugin_id,
                            vuln.tool_id,
                            vuln.custom_id,
                            vuln.level,
                            vuln.risk,
                            vuln.severity,
                            vuln.impact,
                            vuln.cvss_base,
                            vuln.cvss_score,
                            vuln.cvss_vector,
                            fp[vuln.false_positive],
                            target.identity,
                            target.display_name,
                            vuln.title,
                            vuln.description,
                            vuln.solution,
                            "\n".join(vuln.references),
                            "\n".join(vuln.taxonomies),
                            str(target),
                            pickle.dumps(vuln, protocol=0).encode("hex"),
                            pickle.dumps(target, protocol=0).encode("hex"),
                        ]
                    else:
                        row = [
                            data.identity,
                            data.data_type,
                            data.data_subtype,
                            getattr(data, "category", None),
                            data.display_name,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            0,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            str(data),
                            None,
                            pickle.dumps(data, protocol=0).encode("hex"),
                        ]
                    row = [to_utf8(x) if x is not None else "" for x in row]
                    writer.writerow(row)
Beispiel #11
0
    def generate_report(self, output_file):
        Logger.log_verbose("Writing reStructured text report to file: %s" % output_file)

        # Open the output file.
        with open(output_file, "w") as f:

            # Print the main header.
            print >>f, "GoLismero Report"
            print >>f, "================"
            print >>f, ""
            print >>f, ".. title:: %s - GoLismero" % self.__format_rst(Config.audit_name)
            print >>f, ""
            print >>f, ".. footer:: Report generation date: %s" % datetime.now()
            print >>f, ""
            print >>f, ".. contents:: Table of Contents"
            print >>f, "   :depth: 3"
            print >>f, "   :backlinks: top"
            print >>f, ""

            # Print the summary.
            start_time, stop_time, run_time = parse_audit_times( *get_audit_times() )
            print >>f, "Summary"
            print >>f, "-------"
            print >>f, ""
            print >>f, "- Audit name: " + self.__format_rst(Config.audit_name)
            print >>f, "- Start date: " + start_time
            print >>f, "- End date: " + stop_time
            print >>f, "- Execution time: " + run_time
            print >>f, ""

            # Print the audit scope.
            print >>f, "Audit Scope"
            print >>f, "-----------"
            print >>f, ""
            print >>f, "- IP Addresses: "
            for address in Config.audit_scope.addresses:
                print >>f, "  + " + self.__format_rst(address)
            print >>f, "- Domains:"
            scope_domains = ["*." + r for r in Config.audit_scope.roots]
            scope_domains.extend(Config.audit_scope.domains)
            for domain in scope_domains:
                print >>f, "  + " + self.__format_rst(domain)
            print >>f, "- Web Pages:"
            for url in Config.audit_scope.web_pages:
                print >>f, "  + " + self.__format_rst(url)
            print >>f, ""

            # Determine the report type.
            self.__full_report = not Config.audit_config.only_vulns

            # Collect the vulnerabilities that are not false positives.
            datas = self.__collect_vulns(False)

            # If it's a brief report and we have no vulnerabilities,
            # write a message and stop.
            if not datas and not self.__full_report:
                print >>f, "No vulnerabilities found."
                print >>f, ""
                return

            # Collect the false positives.
            # In brief mode, this is used to eliminate the references to them.
            fp = self.__collect_vulns(True)
            self.__fp = set()
            for ids in fp.itervalues():
                self.__fp.update(ids)

            try:

                # Report the vulnerabilities.
                self.__write_rst(f, datas, Data.TYPE_VULNERABILITY, "Vulnerabilities")

                # This dictionary tracks which data to show
                # and which not to in brief report mode.
                self.__vulnerable = set()

                try:

                    # Show the resources in the report.
                    datas = self.__collect_data(Data.TYPE_RESOURCE)
                    if datas:
                        self.__write_rst(f, datas, Data.TYPE_RESOURCE,
                                "Resources" if self.__full_report else "Assets")

                    # Show the informations in the report.
                    datas = self.__collect_data(Data.TYPE_INFORMATION)
                    if datas:
                        self.__write_rst(f, datas, Data.TYPE_INFORMATION,
                                "Informations" if self.__full_report else "Evidences")

                finally:
                    self.__vulnerable.clear()

            finally:
                self.__fp.clear()

            # Show the false positives in the full report.
            if self.__full_report and fp:
                self.__write_rst(f, fp, Data.TYPE_VULNERABILITY, "False Positives")

        # Launch the build command, if any.
        command = Config.plugin_config.get("command", "")
        if command:
            Logger.log_verbose("Launching command: %s" % command)
            args = split(command)
            for i in xrange(len(args)):
                token = args[i]
                p = token.find("$1")
                while p >= 0:
                    if p == 0 or (p > 0 and token[p-1] != "$"):
                        token = token[:p] + output_file + token[p+2:]
                    p = token.find("$1", p + len(output_file))
                args[i] = token
            cwd = os.path.split(output_file)[0]
            log = lambda x: Logger.log_verbose(x[:-1] if x.endswith("\n") else x)
            run_external_tool(args[0], args[1:], cwd=cwd, callback=log)
Beispiel #12
0
    def generate_report(self, output_file):
        Logger.log_verbose("Writing audit results to file: %s" % output_file)

        # Determine the report type.
        self.__full_report = not Config.audit_config.only_vulns

        # Parse the audit times.
        report_time = "%s UTC" % datetime.utcnow()
        start_time, stop_time = get_audit_times()
        start_time, stop_time, run_time = parse_audit_times(
            start_time, stop_time)

        # Create the root element.
        xml = ET.Element("golismero")
        xml.set("audit_name", Config.audit_name)
        if start_time:
            xml.set("start_time", start_time)
        if stop_time:
            xml.set("stop_time", stop_time)
        if run_time:
            xml.set("run_time", run_time)
        xml.set("report_time", report_time)
        xml.set("report_type", "full" if self.__full_report else "brief")

        # Create the audit scope element and subelements.
        xml_scope = ET.SubElement(xml, "audit_scope")
        for address in Config.audit_scope.addresses:
            xml_ip = ET.SubElement(xml_scope, "address")
            xml_ip.text = address
        for root_domain in Config.audit_scope.roots:
            xml_root = ET.SubElement(xml_scope, "root_domain")
            xml_root.text = root_domain
        for domain in Config.audit_scope.domains:
            xml_domain = ET.SubElement(xml_scope, "domain")
            xml_domain.text = domain
        for web_page in Config.audit_scope.web_pages:
            xml_web = ET.SubElement(xml_scope, "web_page")
            xml_web.text = web_page

        # Collect the vulnerabilities that are not false positives.
        datas = self.__collect_vulns(False)

        # If we have vulnerabilities and/or it's a full report...
        if datas or self.__full_report:

            # Collect the false positives.
            # In brief mode, this is used to eliminate the references to them.
            fp = self.__collect_vulns(True)
            self.__fp = set(fp)

            try:
                # Report the vulnerabilities.
                if datas:
                    xml_vulns = ET.SubElement(xml, "vulnerabilities")
                    self.__add_to_xml(xml_vulns, datas,
                                      Data.TYPE_VULNERABILITY, "vulnerability")

                # This dictionary tracks which data to show
                # and which not to in brief report mode.
                self.__vulnerable = set()

                try:

                    # Show the resources in the report.
                    datas = self.__collect_data(Data.TYPE_RESOURCE)
                    if datas:
                        xml_res = ET.SubElement(xml, "resources")
                        self.__add_to_xml(xml_res, datas, Data.TYPE_RESOURCE,
                                          "resource")

                    # Show the informations in the report.
                    datas = self.__collect_data(Data.TYPE_INFORMATION)
                    if datas:
                        xml_info = ET.SubElement(xml, "informations")
                        self.__add_to_xml(xml_info, datas,
                                          Data.TYPE_INFORMATION, "information")

                finally:
                    self.__vulnerable.clear()

            finally:
                self.__fp.clear()

            # Show the false positives in the full report.
            if self.__full_report and fp:
                xml_fp = ET.SubElement(xml, "false_positives")
                self.__add_to_xml(xml_fp, fp, Data.TYPE_VULNERABILITY,
                                  "vulnerability")

        # Write the XML data to disk.
        tree = ET.ElementTree(xml)
        tree.write(output_file, encoding="utf-8")

        # Launch the build command, if any.
        self.launch_command(output_file)