Example #1
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:

            # Write the report.
            self.write_report_to_open_file(f)

        # 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)
Example #2
0
def command_update(parser, P, cmdParams, auditParams):

    # Fail if we got any arguments.
    if P.targets:
        parser.error("too many arguments")

    # Setup a dummy environment so we can call the API.
    with PluginTester(autoinit=False) as t:
        t.orchestrator_config.ui_mode = "console"
        t.orchestrator_config.verbose = cmdParams.verbose
        t.orchestrator_config.color   = cmdParams.color
        t.init_environment(mock_audit=False)

        # Run Git here to download the latest version.
        if cmdParams.verbose:
            Logger.log("Updating GoLismero...")
        run_external_tool("git", ["pull"], cwd = here,
            callback = Logger.log if cmdParams.verbose else lambda x: x)

        # Update the TLD names.
        if cmdParams.verbose:
            Logger.log("Updating list of TLD names...")
        import tldextract
        tldextract.TLDExtract().update(True)

        # Done!
        if cmdParams.verbose:
            Logger.log("Update complete.")
        exit(0)
Example #3
0
    def make_injection(self, target, command, args):
        """
        Run sqlmap over the target.

        :param target: Base URL to scan.
        :type target: BaseUrl

        :param command: Path to the Nikto script.
        :type command: str

        :param args: Arguments to pass to Nikto.
        :type args: list(str)

        :return: True if runs is ok. False otherwise.
        :rtype: bool
        """
        # Run Nmap and capture the text output.
        Logger.log("Launching sqlmap against: %s" % target)
        Logger.log_more_verbose("sqlmap arguments: %s" % " ".join(args))

        with ConnectionSlot(target):
            t1 = time()
            code = run_external_tool(command, args, callback=Logger.log_verbose)
            t2 = time()

        # Log in extra verbose mode.
        if code:
            Logger.log_error("sqlmap execution failed, status code: %d" % code)
            return False
        else:
            Logger.log("sqlmap scan finished in %s seconds for target: %s"% (t2 - t1, target))
            return True
Example #4
0
    def run_xsser(self, hostname, url, args):
        """
        Run XSSer against the given target.

        :param url: The URL to be tested.
        :type url: str

        :param command: Path to the XSSer script.
        :type command: str

        :param args: The arguments to pass to XSSer.
        :type args: list

        :return: True id successful, False otherwise.
        :rtype: bool
        """

        Logger.log("Launching XSSer against: %s" % url)
        Logger.log_more_verbose("XSSer arguments: %s" % " ".join(args))

        xsser_script = join(get_tools_folder(), "xsser", "xsser.py")

        with ConnectionSlot(hostname):
            t1 = time()
            code = run_external_tool(xsser_script, args, callback=Logger.log_verbose)
            t2 = time()

        if code:
            Logger.log_error("XSSer execution failed, status code: %d" % code)
            return False
        Logger.log("XSSer scan finished in %s seconds for target: %s" % (t2 - t1, url))
        return True
Example #5
0
    def make_injection(self, target, args):
        """
        Run SQLMap against the given target.

        :param target: URL to scan.
        :type target: Url

        :param args: Arguments to pass to SQLMap.
        :type args: list(str)

        :return: True on success, False on failure.
        :rtype: bool
        """

        Logger.log("Launching SQLMap against: %s" % target)
        Logger.log_more_verbose("SQLMap arguments: %s" % " ".join(args))

        sqlmap_script = join(get_tools_folder(), "sqlmap", "sqlmap.py")

        with ConnectionSlot(target):
            t1 = time()
            code = run_external_tool(sqlmap_script, args,
                                     callback=Logger.log_verbose)
            t2 = time()

        if code:
            Logger.log_error("SQLMap execution failed, status code: %d" % code)
            return False
        Logger.log(
            "SQLMap scan finished in %s seconds for target: %s"
            % (t2 - t1, target))
        return True
Example #6
0
    def run_xsser(self,url,command,args):
        """
        Run xsser target
        
        :param url: the url to be tested
        :type url: str
        
        :param command: path to xsser script
        :type command: str
        
        :param args: the arguments pass to xsser
        :type args: list
        
        :return: return True is run successful, or False for fail
        :rtype: bool   
        """
        Logger.log("Launching xsser against: %s" % url)
        Logger.log_more_verbose("xsser arguments: %s" % " ".join(args))

        t1 = time()
        code = run_external_tool(command, args, callback=Logger.log_verbose)
        t2 = time()

        # Log in extra verbose mode.
        if code:
            Logger.log_error("xsser execution failed, status code: %d" % code)
            return False
        else:
            Logger.log("xsser scan finished in %s seconds for target: %s"% (t2 - t1, url))
            return True
Example #7
0
    def run(self, info):

        # Build the command line arguments for Nmap.
        args = shlex.split(Config.plugin_args["args"])
        if info.version == 6 and "-6" not in args:
            args.append("-6")
        args.append(info.address)

        # The Nmap output will be saved in XML format in a temporary file.
        with tempfile(suffix=".xml") as output:
            args.append("-oX")
            args.append(output)

            # Run Nmap and capture the text output.
            Logger.log("Launching Nmap against: %s" % info.address)
            Logger.log_more_verbose("Nmap arguments: %s" % " ".join(args))
            with ConnectionSlot(info.address):
                t1 = time()
                code = run_external_tool("nmap", args, callback=Logger.log_verbose)
                t2 = time()

            # Log the output in extra verbose mode.
            if code:
                Logger.log_error("Nmap execution failed, status code: %d" % code)
            else:
                Logger.log("Nmap scan finished in %s seconds for target: %s" % (t2 - t1, info.address))

            # Parse and return the results.
            return self.parse_nmap_results(info, output)
Example #8
0
    def recv_info(self, info):

        # Get the hostname to test.
        m_host = info.hostname

        # Workaround for a bug in SSLScan: if the target port doesn't answer
        # back the SSL handshake (i.e. if port 443 is open but another protocol
        # is being used) then SSLScan just blocks indefinitely.
        try:
            with ConnectionSlot(m_host):
                s = socket(AF_INET, SOCK_STREAM)
                try:
                    s.settimeout(4.0)
                    s.connect( (m_host, 443) )
                    s = wrap_socket(s)
                    s.shutdown(2)
                finally:
                    s.close()
        except Exception:
            Logger.log_error_more_verbose(
                "Host %r doesn't seem to support SSL, aborting." % m_host)
            return

        # Create a temporary output file.
        with tempfile(suffix = ".xml") as output:

            # Build the command line arguments.
            args = [
                "--no-failed",
                "--xml=" + output,  # non standard cmdline parsing :(
                m_host
            ]

            # Run SSLScan and capture the text output.
            Logger.log("Launching SSLScan against: %s" % m_host)
            Logger.log_more_verbose("SSLScan arguments: %s" % " ".join(args))
            with ConnectionSlot(m_host):
                t1 = time()
                code = run_external_tool("sslscan", args, callback=Logger.log_verbose)
                t2 = time()
            if code:
                Logger.log_error(
                    "SSLScan execution failed, status code: %d" % code)
            else:
                Logger.log("SSLScan scan finished in %s seconds for target: %s"
                           % (t2 - t1, m_host))

            # Parse and return the results.
            r, v = self.parse_sslscan_results(output)
            if v:
                Logger.log("Found %s SSL vulnerabilities." % v)
            else:
                Logger.log("No SSL vulnerabilities found.")
            return r
Example #9
0
    def recv_info(self, info):

        m_host = info.hostname

        # Create a temporary output file.
        with tempfile(suffix = ".xml") as output:

            # Build the command line arguments.
            args = [
                "--no-failed",
                "--xml=%s" % output,
                m_host
            ]

            # Run Nmap and capture the text output.
            Logger.log("Launching SSLscan against: %s" % m_host)
            Logger.log_more_verbose("SSLscan arguments: %s" % " ".join(args))

            t1 = time()
            code = run_external_tool("sslscan", args, callback=Logger.log_verbose)
            t2 = time()

            # Log the output in extra verbose mode.
            if code:
                Logger.log_error(
                    "SSLscan execution failed, status code: %d" % code)
            else:
                Logger.log("SSLscan scan finished in %s seconds for target: %s"
                           % (t2 - t1, m_host))

            # Parse and return the results.
            r =  self.parse_sslscan_results(info, output)

            if r:
                Logger.log("Found %s SSL vulns." % len(r))
            else:
                Logger.log("No SSL vulns found.")

            return r
Example #10
0
        # Fail if we got any arguments.
        if P.targets:
            parser.error("too many arguments")

        # Setup a dummy environment so we can call the API.
        with PluginTester(autoinit=False) as t:
            t.orchestrator_config.ui_mode = "console"
            t.orchestrator_config.verbose = cmdParams.verbose
            t.orchestrator_config.color   = cmdParams.color
            t.init_environment(mock_audit=False)

            # Run Git here to download the latest version.
            if cmdParams.verbose:
                Logger.log("Updating GoLismero...")
            run_external_tool("git", ["pull"], cwd = here,
                callback = Logger.log if cmdParams.verbose else lambda x: x)

            # Update the NIST CPE database.
            if cmdParams.verbose:
                Logger.log("Updating NIST CPE database...")
            t.orchestrator.cpedb.update()
            t.orchestrator.cpedb.vacuum()

            # Done!
            Logger.log("Update complete.")
            exit(0)


    #--------------------------------------------------------------------------
    # Check if all options are correct.
Example #11
0
    def run_nikto(self, info, output_filename, command, args):
        """
        Run Nikto and convert the output to the GoLismero data model.

        :param info: Base URL to scan.
        :type info: BaseUrl

        :param output_filename: Path to the output filename.
            The format should always be CSV.
        :type output_filename:

        :param command: Path to the Nikto executable.
            May also be the Perl interpreter executable, with the
            Nikto script as its first argument.
        :type command: str

        :param args: Arguments to pass to the executable.
        :type args: list(str)

        :returns: Results from the Nikto scan.
        :rtype: list(Data)
        """

        # Append the output file name to the arguments.
        args.append("-output")
        args.append(output_filename)

        # Turn off DOS path warnings for Cygwin.
        # Does nothing on other platforms.
        env = os.environ.copy()
        cygwin = env.get("CYGWIN", "")
        if "nodosfilewarning" not in cygwin:
            if cygwin:
                cygwin += " "
            cygwin += "nodosfilewarning"
        env["CYGWIN"] = cygwin

        # Run Nikto and capture the text output.
        Logger.log("Launching Nikto against: %s" % info.hostname)
        Logger.log_more_verbose("Nikto arguments: %s %s" % (command, " ".join(args)))
        ##output, code = run_external_tool("C:\\cygwin\\bin\\perl.exe", ["-V"], env) # DEBUG
        output, code = run_external_tool(command, args, env)

        # Log the output in extra verbose mode.
        if code:
            Logger.log_error("Nikto execution failed, status code: %d" % code)
            if output:
                Logger.log_error_more_verbose(output)
        elif output:
            Logger.log_more_verbose(output)

        # Parse the results.
        results, vuln_count = self.parse_nikto_results(info, output_filename)

        # Log how many results we found.
        msg = (
            "Nikto found %d vulnerabilities for host: %s" % (
                vuln_count,
                info.hostname,
            )
        )
        if vuln_count:
            Logger.log(msg)
        else:
            Logger.log_verbose(msg)

        # Return the results.
        return results
Example #12
0
    def launch_sslscan(self, hostname, port):
        """
        Launch SSLScan against the specified hostname and port.

        :param hostname: Hostname to test.
        :type hostname: str

        :param port: TCP port to test.
        :type port: int
        """

        # Don't scan the same host and port twice.
        if self.state.put("%s:%d" % (hostname, port), True):
            Logger.log_more_verbose(
                "Host %s:%d already scanned, skipped."
                % (hostname, port))
            return

        # Workaround for a bug in SSLScan: if the target port doesn't
        # answer back the SSL handshake (i.e. if port 443 is open but
        # another protocol is being used) then SSLScan just blocks
        # indefinitely.
        try:
            with ConnectionSlot(hostname):
                s = socket(AF_INET, SOCK_STREAM)
                try:
                    s.settimeout(4.0)
                    s.connect( (hostname, port) )
                    s = wrap_socket(s)
                    s.shutdown(2)
                finally:
                    s.close()
        except Exception:
            Logger.log_error_more_verbose(
                "Host %s:%d doesn't seem to support SSL, aborting."
                % (hostname, port))
            return

        # Create a temporary output file.
        with tempfile(suffix = ".xml") as output:

            # Build the command line arguments.
            args = [
                "--no-failed",
                "--xml=" + output,  # non standard cmdline parsing :(
                "%s:%d" % (hostname, port),
            ]

            # Run SSLScan and capture the text output.
            Logger.log("Launching SSLScan against: %s" % hostname)
            Logger.log_more_verbose("SSLScan arguments: %s" % " ".join(args))
            with ConnectionSlot(hostname):
                t1 = time()
                code = run_external_tool("sslscan", args,
                                         callback=Logger.log_verbose)
                t2 = time()
            if code:
                if code < 0 and sep == "\\":
                    asc_code = "0x%.8X" % code
                else:
                    asc_code = str(code)
                Logger.log_error(
                    "SSLScan execution failed, status code: %s" % asc_code)
            else:
                Logger.log("SSLScan scan finished in %s seconds for target: %s"
                           % (t2 - t1, hostname))

            # Parse and return the results.
            r, v = self.parse_sslscan_results(output)
            if v:
                Logger.log("Found %s SSL vulnerabilities." % v)
            else:
                Logger.log("No SSL vulnerabilities found.")
            return r
Example #13
0
def command_update(parser, P, cmdParams, auditParams):

    # Fail if we got any arguments.
    if P.targets:
        parser.error("too many arguments")

    # Setup a dummy environment so we can call the API.
    with PluginTester(autoinit=False) as t:
        t.orchestrator_config.ui_mode = "console"
        t.orchestrator_config.verbose = cmdParams.verbose
        t.orchestrator_config.color   = cmdParams.color
        t.init_environment(mock_audit=False)

        # Flag to tell if we fetched new code.
        did_update = False

        # Run Git here to download the latest version.
        if cmdParams.verbose:
            Logger.log("Updating GoLismero...")
        if os.path.exists(os.path.join(here, ".git")):
            helper = _GitHelper(cmdParams.verbose)
            run_external_tool("git", ["pull"], cwd = here, callback = helper)
            did_update = helper.did_update
        elif cmdParams.verbose:
            Logger.log_error(
                "Cannot update GoLismero if installed from a zip file! You"
                " must install it from the Git repository to get updates.")

        # Update the TLD names.
        if cmdParams.verbose:
            Logger.log("Updating list of TLD names...")
        import tldextract
        tldextract.TLDExtract().update(True)

        # If no code was updated, just quit here.
        if not did_update:
            if cmdParams.verbose:
                Logger.log("Update complete.")
            exit(0)

        # Tell the user we're about to restart.
        if cmdParams.verbose:
            Logger.log("Reloading GoLismero...")

    # Unload GoLismero.
    import golismero.patches.mp
    golismero.patches.mp.undo()
    x = here
    if not x.endswith(os.path.sep):
        x += os.path.sep
    our_modules = {
        n: m for n, m in sys.modules.iteritems()
        if n.startswith("golismero.") or (
            hasattr(m, "__file__") and m.__file__.startswith(x)
        )
    }
    for n in our_modules.iterkeys():
        if n.startswith("golismero.") or n.startswith("plugin_"):
            del sys.modules[n]

    # Restart GoLismero.
    # Note that after this point we need to explicitly import the classes we
    # use, and make sure they're the newer versions of them. That means:
    # ALWAYS USE FULLY QUALIFIED NAMES FROM HERE ON.
    import golismero.api.logger
    import golismero.main.testing
    with golismero.main.testing.PluginTester(autoinit=False) as t:
        t.orchestrator_config.ui_mode = "console"
        t.orchestrator_config.verbose = cmdParams.verbose
        t.orchestrator_config.color   = cmdParams.color
        t.init_environment(mock_audit=False)

        # Call the plugin hooks.
        all_plugins = sorted(
            t.orchestrator.pluginManager.load_plugins().iteritems())
        for plugin_id, plugin in all_plugins:
            if hasattr(plugin, "update"):
                if cmdParams.verbose:
                    golismero.api.logger.Logger.log(
                        "Updating plugin %r..." % plugin_id)
                try:
                    t.run_plugin_method(plugin_id, "update")
                except Exception:
                    golismero.api.logger.Logger.log_error(format_exc())

        # Done!
        if cmdParams.verbose:
            golismero.api.logger.Logger.log("Update complete.")
        exit(0)
Example #14
0
    def run_nikto(self, info, output_filename, command, args):
        """
        Run Nikto and convert the output to the GoLismero data model.

        :param info: Base URL to scan.
        :type info: BaseURL

        :param output_filename: Path to the output filename.
            The format should always be CSV.
        :type output_filename: str

        :param command: Path to the Nikto script.
        :type command: str

        :param args: Arguments to pass to Nikto.
        :type args: list(str)

        :returns: Results from the Nikto scan.
        :rtype: list(Data)
        """

        # Get the Nikto directory.
        cwd = split(abspath(command))[0]

        # On Windows, we must run Perl explicitly.
        # Also it only works under Cygwin.
        if sep == "\\":
            perl = find_cygwin_binary_in_path("perl.exe")
            if not perl:
                Logger.log_error(
                    "Perl interpreter not found, cannot run Nikto!")
            args.insert(0, command)
            command = perl

        # Run Nikto and capture the text output.
        Logger.log("Launching Nikto against: %s" % info.hostname)
        Logger.log_more_verbose("Nikto arguments: %s %s" %
                                (command, " ".join(args)))
        with ConnectionSlot(info.hostname):
            code = run_external_tool(command,
                                     args,
                                     cwd=cwd,
                                     callback=Logger.log_verbose)

        # Log the output in extra verbose mode.
        if code:
            Logger.log_error("Nikto execution failed, status code: %d" % code)

        # Parse the results.
        results, vuln_count = self.parse_nikto_results(info, output_filename)

        # Log how many results we found.
        msg = ("Nikto found %d vulnerabilities for host: %s" % (
            vuln_count,
            info.hostname,
        ))
        if vuln_count:
            Logger.log(msg)
        else:
            Logger.log_verbose(msg)

        # Return the results.
        return results
Example #15
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)
Example #16
0
    def run_nikto(self, info, output_filename, command, args):
        """
        Run Nikto and convert the output to the GoLismero data model.

        :param info: Base URL to scan.
        :type info: BaseURL

        :param output_filename: Path to the output filename.
            The format should always be CSV.
        :type output_filename: str

        :param command: Path to the Nikto script.
        :type command: str

        :param args: Arguments to pass to Nikto.
        :type args: list(str)

        :returns: Results from the Nikto scan.
        :rtype: list(Data)
        """

        # Get the Nikto directory.
        cwd = split(abspath(command))[0]

        # On Windows, we must run Perl explicitly.
        # Also it only works under Cygwin.
        if sep == "\\":
            perl = find_cygwin_binary_in_path("perl.exe")
            if not perl:
                Logger.log_error("Perl interpreter not found, cannot run Nikto!")
            args.insert(0, command)
            command = perl

        # Run Nikto and capture the text output.
        Logger.log("Launching Nikto against: %s" % info.hostname)
        Logger.log_more_verbose(
            "Nikto arguments: %s %s" % (command, " ".join(args)))
        with ConnectionSlot(info.hostname):
            code = run_external_tool(command, args, cwd = cwd,
                                     callback = Logger.log_verbose)

        # Log the output in extra verbose mode.
        if code:
            Logger.log_error("Nikto execution failed, status code: %d" % code)

        # Parse the results.
        results, vuln_count = self.parse_nikto_results(info, output_filename)

        # Log how many results we found.
        msg = (
            "Nikto found %d vulnerabilities for host: %s" % (
                vuln_count,
                info.hostname,
            )
        )
        if vuln_count:
            Logger.log(msg)
        else:
            Logger.log_verbose(msg)

        # Return the results.
        return results
Example #17
0
    def generate_report(self, output_file):
        Logger.log_verbose("Writing audit results to file: %s" % output_file)

        # Parse the audit times.
        start_time, stop_time = get_audit_times()
        run_time = stop_time - start_time

        # Create the root element.
        xml = ET.Element("golismero")
        xml.set("output_time", str(datetime.now()))
        xml.set("audit_name", Config.audit_name)
        if start_time:
            xml.set("start_time", str(start_time))
        if stop_time:
            xml.set("stop_time", str(stop_time))
        if run_time:
            xml.set("run_time", str(run_time))

        # 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

        # 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 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)

        # 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)
Example #18
0
def command_update(parser, P, cmdParams, auditParams):

    # Fail if we got any arguments.
    if P.targets:
        parser.error("too many arguments")

    # Setup a dummy environment so we can call the API.
    with PluginTester(autoinit=False) as t:
        t.orchestrator_config.ui_mode = "console"
        t.orchestrator_config.verbose = cmdParams.verbose
        t.orchestrator_config.color = cmdParams.color
        t.init_environment(mock_audit=False)

        # Flag to tell if we fetched new code.
        did_update = False

        # Run Git here to download the latest version.
        if cmdParams.verbose:
            Logger.log("Updating GoLismero...")
        if os.path.exists(os.path.join(here, ".git")):
            helper = _GitHelper(cmdParams.verbose)
            run_external_tool("git", ["pull"], cwd=here, callback=helper)
            did_update = helper.did_update
        elif cmdParams.verbose:
            Logger.log_error(
                "Cannot update GoLismero if installed from a zip file! You"
                " must install it from the Git repository to get updates.")

        # Update the TLD names.
        if cmdParams.verbose:
            Logger.log("Updating list of TLD names...")
        import tldextract
        tldextract.TLDExtract().update(True)

        # If no code was updated, just quit here.
        if not did_update:
            if cmdParams.verbose:
                Logger.log("Update complete.")
            exit(0)

        # Tell the user we're about to restart.
        if cmdParams.verbose:
            Logger.log("Reloading GoLismero...")

    # Unload GoLismero.
    import golismero.patches.mp
    golismero.patches.mp.undo()
    x = here
    if not x.endswith(os.path.sep):
        x += os.path.sep
    our_modules = {
        n: m
        for n, m in sys.modules.iteritems() if n.startswith("golismero.") or (
            hasattr(m, "__file__") and m.__file__.startswith(x))
    }
    for n in our_modules.iterkeys():
        if n.startswith("golismero.") or n.startswith("plugin_"):
            del sys.modules[n]

    # Restart GoLismero.
    # Note that after this point we need to explicitly import the classes we
    # use, and make sure they're the newer versions of them. That means:
    # ALWAYS USE FULLY QUALIFIED NAMES FROM HERE ON.
    import golismero.api.logger
    import golismero.main.testing
    with golismero.main.testing.PluginTester(autoinit=False) as t:
        t.orchestrator_config.ui_mode = "console"
        t.orchestrator_config.verbose = cmdParams.verbose
        t.orchestrator_config.color = cmdParams.color
        t.init_environment(mock_audit=False)

        # Call the plugin hooks.
        all_plugins = sorted(
            t.orchestrator.pluginManager.load_plugins().iteritems())
        for plugin_id, plugin in all_plugins:
            if hasattr(plugin, "update"):
                if cmdParams.verbose:
                    golismero.api.logger.Logger.log("Updating plugin %r..." %
                                                    plugin_id)
                try:
                    t.run_plugin_method(plugin_id, "update")
                except Exception:
                    golismero.api.logger.Logger.log_error(format_exc())

        # Done!
        if cmdParams.verbose:
            golismero.api.logger.Logger.log("Update complete.")
        exit(0)