Пример #1
0
    def processOutput(self, plugin, output, command_id, isReport=False):
        output_queue = multiprocessing.JoinableQueue()
        new_elem_queue = multiprocessing.Queue()

        plugin_process = PluginProcess(
            plugin, output_queue, new_elem_queue, isReport)

        getLogger(self).debug(
            "Created plugin_process (%d) for plugin instance (%d)" %
            (id(plugin_process), id(plugin)))

        plugin_process.start()

        output_queue.put(output)
        output_queue.put(None)
        output_queue.join()

        self._processAction(modelactions.PLUGINSTART, [plugin.id])

        while True:
            try:
                current_action = new_elem_queue.get(block=False)
                if current_action is None:
                    break
                action = current_action[0]
                parameters = current_action[1:]

                if hasattr(parameters[-1], '_metadata'):
                    parameters[-1]._metadata.command_id = command_id

                getLogger(self).debug(
                    "Core: Processing a new '%s', parameters (%s)\n" %
                    (action, str(parameters)))
                self._processAction(action, parameters)

            except Queue.Empty:
                continue
            except IOError, e:
                if e.errno == errno.EINTR:
                    continue
                else:
                    getLogger(self).debug(
                        "new_elem_queue Exception - "
                        "something strange happened... "
                        "unhandled exception?")
                    break
            except Exception:
                getLogger(self).debug(
                    "new_elem_queue Exception - "
                    "something strange happened... "
                    "unhandled exception?")
                break
Пример #2
0
    def processOutput(self, plugin, output, command_id, isReport=False):
        output_queue = multiprocessing.JoinableQueue()
        new_elem_queue = multiprocessing.Queue()

        plugin_process = PluginProcess(plugin, output_queue, new_elem_queue,
                                       isReport)

        getLogger(self).debug(
            "Created plugin_process (%d) for plugin instance (%d)" %
            (id(plugin_process), id(plugin)))

        plugin_process.start()

        output_queue.put(output)
        output_queue.put(None)
        output_queue.join()

        self._processAction(modelactions.PLUGINSTART, [plugin.id])

        while True:
            try:
                current_action = new_elem_queue.get(block=False)
                if current_action is None:
                    break
                action = current_action[0]
                parameters = current_action[1:]

                parameters[-1]._metadata.command_id = command_id

                getLogger(self).debug(
                    "Core: Processing a new '%s', parameters (%s)\n" %
                    (action, str(parameters)))
                self._processAction(action, parameters)

            except Queue.Empty:
                continue
            except IOError, e:
                if e.errno == errno.EINTR:
                    continue
                else:
                    getLogger(self).debug("new_elem_queue Exception - "
                                          "something strange happened... "
                                          "unhandled exception?")
                    break
            except Exception:
                getLogger(self).debug("new_elem_queue Exception - "
                                      "something strange happened... "
                                      "unhandled exception?")
                break
Пример #3
0
    def processOutput(self, plugin, output, command, isReport=False):
        """
            Process the output of the plugin. This will start the PluginProcess
            and also PluginCommiter (thread) that will informa to faraday server
            when the command finished.

        :param plugin: Plugin to execute
        :param output: read output from plugin or term
        :param command_id: command id that started the plugin
        :param isReport: Report or output from shell
        :return: None
        """
        output_queue = JoinableQueue()
        plugin.set_actions_queue(self.pending_actions)

        plugin_process = PluginProcess(
            plugin, output_queue, isReport)

        getLogger(self).debug(
            "Created plugin_process (%d) for plugin instance (%d)" %
            (id(plugin_process), id(plugin)))

        self.pending_actions.put((Modelactions.PLUGINSTART, plugin.id, command.getID()))
        output_queue.put((output, command.getID()))
        plugin_commiter = PluginCommiter(
            output_queue,
            output,
            self.pending_actions,
            plugin,
            command,
            self._mapper_manager,
            self.end_event,
        )
        plugin_commiter.start()
        # This process is stopped when plugin commiter joins output queue
        plugin_process.start()
Пример #4
0
class PluginController(Thread):
    """
    TODO: Doc string.
    """
    def __init__(self, id, plugin_manager, mapper_manager, pending_actions, end_event=None):
        super(PluginController, self).__init__()
        self.plugin_manager = plugin_manager
        self._plugins = plugin_manager.getPlugins()
        self.id = id
        self._actionDispatcher = None
        self._setupActionDispatcher()
        self._mapper_manager = mapper_manager
        self.output_path = os.path.join(
            os.path.expanduser(CONST_FARADAY_HOME_PATH),
            CONST_FARADAY_ZSH_OUTPUT_PATH)
        self._active_plugins = {}
        self.plugin_sets = {}
        self.plugin_manager.addController(self, self.id)
        self.stop = False
        self.pending_actions = pending_actions
        self.end_event = end_event

    def _find_plugin(self, plugin_id):
        return self._plugins.get(plugin_id, None)

    def _is_command_malformed(self, original_command, modified_command):
        """
        Checks if the command to be executed is safe and it's not in the
        block list defined by the user. Returns False if the modified
        command is ok, True if otherwise.
        """
        block_chars = set(["|", "$", "#"])

        if original_command == modified_command:
            return False

        orig_cmd_args = shlex.split(original_command)

        if not isinstance(modified_command, basestring):
            modified_command = ""
        mod_cmd_args = shlex.split(modified_command)

        block_flag = False
        orig_args_len = len(orig_cmd_args)
        for index in xrange(0, len(mod_cmd_args)):
            if (index < orig_args_len and
                    orig_cmd_args[index] == mod_cmd_args[index]):
                continue

            for char in block_chars:
                if char in mod_cmd_args[index]:
                    block_flag = True
                    break

        return block_flag

    def _get_plugins_by_input(self, cmd, plugin_set):
        for plugin in plugin_set.itervalues():
            if plugin.canParseCommandString(cmd):
                return plugin
        return None

    def getAvailablePlugins(self):
        """
        Return a dictionary with the available plugins.
        Plugin ID's as keys and plugin instences as values
        """
        return self._plugins

    def stop(self):
        self.plugin_process.stop()
        self.stop = True

    def processOutput(self, plugin, output, command, isReport=False):
        """
            Process the output of the plugin. This will start the PluginProcess
            and also PluginCommiter (thread) that will informa to faraday server
            when the command finished.

        :param plugin: Plugin to execute
        :param output: read output from plugin or term
        :param command_id: command id that started the plugin
        :param isReport: Report or output from shell
        :return: None
        """
        output_queue = JoinableQueue()
        plugin.set_actions_queue(self.pending_actions)

        self.plugin_process = PluginProcess(
            plugin, output_queue, isReport)

        getLogger(self).debug(
            "Created plugin_process (%d) for plugin instance (%d)" %
            (id(self.plugin_process), id(plugin)))

        self.pending_actions.put((Modelactions.PLUGINSTART, plugin.id, command.getID()))
        output_queue.put((output, command.getID()))
        plugin_commiter = PluginCommiter(
            output_queue,
            output,
            self.pending_actions,
            plugin,
            command,
            self._mapper_manager,
            self.end_event,
        )
        plugin_commiter.start()
        # This process is stopped when plugin commiter joins output queue
        self.plugin_process.start()

    def _processAction(self, action, parameters):
        """
        decodes and performs the action given
        It works kind of a dispatcher
        """
        getLogger(self).debug(
            "_processAction - %s - parameters = %s" %
            (action, str(parameters)))
        self._actionDispatcher[action](*parameters)

    def _setupActionDispatcher(self):
        self._actionDispatcher = {
            Modelactions.ADDHOST: model.api.addHost,
            Modelactions.ADDSERVICEHOST: model.api.addServiceToHost,
            #Vulnerability
            Modelactions.ADDVULNHOST: model.api.addVulnToHost,
            Modelactions.ADDVULNSRV: model.api.addVulnToService,
            #VulnWeb
            Modelactions.ADDVULNWEBSRV: model.api.addVulnWebToService,
            #Note
            Modelactions.ADDNOTEHOST: model.api.addNoteToHost,
            Modelactions.ADDNOTESRV: model.api.addNoteToService,
            Modelactions.ADDNOTENOTE: model.api.addNoteToNote,
            #Creds
            Modelactions.ADDCREDSRV:  model.api.addCredToService,
            #LOG
            Modelactions.LOG: model.api.log,
            Modelactions.DEVLOG: model.api.devlog,
            # Plugin state
            Modelactions.PLUGINSTART: model.api.pluginStart,
            Modelactions.PLUGINEND: model.api.pluginEnd
        }

    def updatePluginSettings(self, plugin_id, new_settings):
        for plugin_set in self.plugin_sets.values():
            if plugin_id in plugin_set:
                plugin_set[plugin_id].updateSettings(new_settings)
        if plugin_id in self._plugins:
            self._plugins[plugin_id].updateSettings(new_settings)

    def createPluginSet(self, pid):
        self.plugin_sets[pid] = self.plugin_manager.getPlugins()

    def processCommandInput(self, pid, cmd, pwd):
        """
        This method tries to find a plugin to parse the command sent
        by the terminal (identiefied by the process id).
        """
        if pid not in self.plugin_sets:
            self.createPluginSet(pid)

        plugin = self._get_plugins_by_input(cmd, self.plugin_sets[pid])

        if plugin:
            modified_cmd_string = plugin.processCommandString("", pwd, cmd)
            if not self._is_command_malformed(cmd, modified_cmd_string):

                cmd_info = CommandRunInformation(
                    **{'workspace': model.api.getActiveWorkspace().name,
                        'itime': time.time(),
                        'import_source': 'shell',
                        'command': cmd.split()[0],
                        'params': ' '.join(cmd.split()[1:])})
                cmd_info.setID(self._mapper_manager.save(cmd_info))

                self._active_plugins[pid] = plugin, cmd_info

                return plugin.id, modified_cmd_string

        return None, None

    def onCommandFinished(self, pid, exit_code, term_output):
        if pid not in self._active_plugins.keys():
            return False
        if exit_code != 0:
            del self._active_plugins[pid]
            return False

        plugin, cmd_info = self._active_plugins.get(pid)

        cmd_info.duration = time.time() - cmd_info.itime
        self._mapper_manager.update(cmd_info)

        self.processOutput(plugin, term_output, cmd_info)
        del self._active_plugins[pid]
        return True

    def processReport(self, plugin, filepath, ws_name=None):

        if not ws_name:
            ws_name = model.api.getActiveWorkspace().name

        cmd_info = CommandRunInformation(
            **{'workspace': ws_name,
               'itime': time.time(),
               'import_source': 'report',
               'command': plugin,
               'params': filepath,
            })

        self._mapper_manager.createMappers(ws_name)
        command_id = self._mapper_manager.save(cmd_info)
        cmd_info.setID(command_id)

        if plugin in self._plugins:
            logger.info('Processing report with plugin {0}'.format(plugin))
            self._plugins[plugin].workspace = ws_name
            with open(filepath, 'rb') as output:
                self.processOutput(self._plugins[plugin], output.read(), cmd_info, True)
            return command_id

        # Plugin to process this report not found, update duration of plugin process
        cmd_info.duration = time.time() - cmd_info.itime
        self._mapper_manager.update(cmd_info)
        return False

    def clearActivePlugins(self):
        self._active_plugins = {}