Exemplo n.º 1
0
    def test_clear(self):
        dl = DiskList()

        dl.append('a')
        dl.append('b')

        self.assertEqual(len(dl), 2)

        dl.clear()

        self.assertEqual(len(dl), 0)
Exemplo n.º 2
0
    def test_clear(self):
        dl = DiskList()

        dl.append('a')
        dl.append('b')

        self.assertEqual(len(dl), 2)

        dl.clear()

        self.assertEqual(len(dl), 0)
Exemplo n.º 3
0
class html_file(OutputPlugin):
    """
    Generate HTML report with identified vulnerabilities and log messages.

    :author: Andres Riancho (([email protected]))
    """
    def __init__(self):
        OutputPlugin.__init__(self)

        # Internal variables
        self._initialized = False
        self._additional_info = DiskList(table_prefix='html_file')
        self._enabled_plugins = {}
        self.template_root = os.path.join(ROOT_PATH, 'plugins', 'output',
                                          'html_file', 'templates')

        # User configured parameters
        self._verbose = False
        self._output_file_name = '~/report.html'
        self._template = os.path.join(self.template_root, 'complete.html')

    def debug(self, message, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take
        an action for debug messages.
        """
        if self._verbose:
            to_print = self._clean_string(message)
            self._append_additional_info(to_print, 'debug')

    def do_nothing(self, *args, **kwargs):
        pass

    information = vulnerability = do_nothing

    def error(self, message, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take
        an action for error messages.
        """
        to_print = self._clean_string(message)
        self._append_additional_info(to_print, 'error')

    def console(self, message, new_line=True):
        """
        This method is used by the w3af console to print messages to the
        outside.
        """
        to_print = self._clean_string(message)
        self._append_additional_info(to_print, 'console')

    def _append_additional_info(self, message, msg_type):
        """
        Add a message to the debug table.

        :param message: The message to add to the table. It's in HTML.
        :param msg_type: The type of message
        """
        now = time.localtime(time.time())
        the_time = time.strftime("%c", now)
        self._additional_info.append((the_time, msg_type, message))

    def set_options(self, option_list):
        """
        Sets the Options given on the OptionList to self. The options are the
        result of a user entering some data on a window that was constructed
        using the XML Options that was retrieved from the plugin using
        get_options()

        This method MUST be implemented on every plugin.

        :return: No value is returned.
        """
        self._output_file_name = option_list['output_file'].get_value()
        self._verbose = option_list['verbose'].get_value()
        self._template = option_list['template'].get_value()

    def get_options(self):
        """
        :return: A list of option objects for this plugin.
        """
        ol = OptionList()

        d = 'The path to the HTML template used to render the report.'
        o = opt_factory('template', self._template, d, INPUT_FILE)
        ol.add(o)

        d = 'File name where this plugin will write to'
        o = opt_factory('output_file', self._output_file_name, d, OUTPUT_FILE)
        ol.add(o)

        d = 'True if debug information will be appended to the report.'
        o = opt_factory('verbose', self._verbose, d, 'boolean')
        ol.add(o)

        return ol

    def log_enabled_plugins(self, plugins_dict, options_dict):
        """
        This method is called from the output manager object. This method
        should take an action for the enabled plugins and their configuration.
        Usually, write the info to a file or print it somewhere.

        :param plugins_dict: A dict with all the plugin types and the
                                enabled plugins for that type of plugin.
        :param options_dict: A dict with the options for every plugin.
        """
        self._enabled_plugins = {}

        # TODO: Improve so it contains the plugin configuration too
        for plugin_type, enabled in plugins_dict.iteritems():
            self._enabled_plugins[plugin_type] = enabled

    def end(self):
        try:
            self.flush()
        finally:
            self._additional_info.clear()
            self._enabled_plugins = {}

    def flush(self):
        """
        This method is called when we want to write the data to the html,
        performs these main tasks:
            * Get the target URLs
            * Get the enabled plugins
            * Get the vulnerabilities and infos from the KB
            * Get the debug data
            * Send all the data to jinja2 for rendering the template
        """
        target_urls = [t.url_string for t in cf.cf.get('targets')]

        target_domain = 'unknown'

        target_domains = cf.cf.get('target_domains')
        if target_domains and len(target_domains) > 0:
            target_domain = target_domains[0]

        enabled_plugins = self._enabled_plugins
        findings = kb.kb.get_all_findings_iter()
        debug_log = ((t, l, smart_unicode(m))
                     for (t, l, m) in self._additional_info)
        known_urls = kb.kb.get_all_known_urls()

        context = {
            'target_urls': target_urls,
            'target_domain': target_domain,
            'enabled_plugins': enabled_plugins,
            'findings': findings,
            'debug_log': debug_log,
            'known_urls': known_urls
        }

        # The file was verified to exist when setting the plugin configuration
        template_fh = file(os.path.expanduser(self._template), 'r')
        output_fh = file(os.path.expanduser(self._output_file_name), 'w')

        self._render_html_file(template_fh, context, output_fh)

    def _render_html_file(self, template_fh, context, output_fh):
        """
        Renders the HTML file using the configured template. Separated as a
        method to be able to easily test.

        :param context: A dict containing target urls, enabled plugins, etc.
        :return: True on successful rendering
        """
        severity_icon = functools.partial(get_severity_icon,
                                          self.template_root)

        env_config = {
            'undefined': StrictUndefined,
            'trim_blocks': True,
            'autoescape': True,
            'lstrip_blocks': True
        }

        try:
            jinja2_env = Environment(**env_config)
        except TypeError:
            # Kali uses a different jinja2 version, which doesn't have the same
            # Environment kwargs, so we first try with the version we expect
            # to have available, and then if it doesn't work apply this
            # workaround for Kali
            #
            # https://github.com/andresriancho/w3af/issues/9552
            env_config.pop('lstrip_blocks')
            jinja2_env = Environment(**env_config)

        jinja2_env.filters['render_markdown'] = render_markdown
        jinja2_env.filters['request'] = request_dump
        jinja2_env.filters['response'] = response_dump
        jinja2_env.filters['severity_icon'] = severity_icon
        jinja2_env.filters['severity_text'] = get_severity_text
        jinja2_env.globals['get_current_date'] = get_current_date
        jinja2_env.loader = FileSystemLoader(self.template_root)

        template = jinja2_env.from_string(template_fh.read())

        report_stream = template.stream(context)
        report_stream.enable_buffering(5)

        for report_section in report_stream:
            output_fh.write(report_section.encode('utf-8'))

        return True

    def get_long_desc(self):
        """
        :return: A DETAILED description of the plugin functions and features.
        """
        return """
Exemplo n.º 4
0
class html_file(OutputPlugin):
    """
    Generate HTML report with identified vulnerabilities and log messages.

    :author: Andres Riancho (([email protected]))
    """
    def __init__(self):
        OutputPlugin.__init__(self)

        # Internal variables
        self._initialized = False
        self._additional_info = DiskList(table_prefix='html_file')
        self._enabled_plugins = {}
        self.template_root = os.path.join(ROOT_PATH, 'plugins', 'output',
                                          'html_file', 'templates')

        # User configured parameters
        self._verbose = False
        self._output_file_name = '~/report.html'
        self._template = os.path.join(self.template_root, 'complete.html')

    def debug(self, message, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take
        an action for debug messages.
        """
        if self._verbose:
            to_print = self._clean_string(message)
            self._append_additional_info(to_print, 'debug')

    def do_nothing(self, *args, **kwargs):
        pass

    information = vulnerability = do_nothing

    def error(self, message, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take
        an action for error messages.
        """
        to_print = self._clean_string(message)
        self._append_additional_info(to_print, 'error')

    def console(self, message, new_line=True):
        """
        This method is used by the w3af console to print messages to the
        outside.
        """
        to_print = self._clean_string(message)
        self._append_additional_info(to_print, 'console')

    def _append_additional_info(self, message, msg_type):
        """
        Add a message to the debug table.

        :param message: The message to add to the table. It's in HTML.
        :param msg_type: The type of message
        """
        now = time.localtime(time.time())
        the_time = time.strftime("%c", now)
        self._additional_info.append((the_time, msg_type, message))

    def set_options(self, option_list):
        """
        Sets the Options given on the OptionList to self. The options are the
        result of a user entering some data on a window that was constructed
        using the XML Options that was retrieved from the plugin using
        get_options()

        This method MUST be implemented on every plugin.

        :return: No value is returned.
        """
        self._output_file_name = option_list['output_file'].get_value()
        self._verbose = option_list['verbose'].get_value()
        self._template = option_list['template'].get_value()

    def get_options(self):
        """
        :return: A list of option objects for this plugin.
        """
        ol = OptionList()

        d = 'The path to the HTML template used to render the report.'
        o = opt_factory('template', self._template, d, INPUT_FILE)
        ol.add(o)

        d = 'File name where this plugin will write to'
        o = opt_factory('output_file', self._output_file_name, d, OUTPUT_FILE)
        ol.add(o)

        d = 'True if debug information will be appended to the report.'
        o = opt_factory('verbose', self._verbose, d, 'boolean')
        ol.add(o)

        return ol

    def log_enabled_plugins(self, plugins_dict, options_dict):
        """
        This method is called from the output manager object. This method
        should take an action for the enabled plugins and their configuration.
        Usually, write the info to a file or print it somewhere.

        :param plugins_dict: A dict with all the plugin types and the
                                enabled plugins for that type of plugin.
        :param options_dict: A dict with the options for every plugin.
        """
        self._enabled_plugins = {}

        # TODO: Improve so it contains the plugin configuration too
        for plugin_type, enabled in plugins_dict.iteritems():
            self._enabled_plugins[plugin_type] = enabled

    def end(self):
        try:
            self.flush()
        finally:
            self._additional_info.clear()
            self._enabled_plugins = {}

    def flush(self):
        """
        This method is called when we want to write the data to the html,
        performs these main tasks:
            * Get the target URLs
            * Get the enabled plugins
            * Get the vulnerabilities and infos from the KB
            * Get the debug data
            * Send all the data to jinja2 for rendering the template
        """
        target_urls = [t.url_string for t in cf.cf.get('targets')]
        target_domain = cf.cf.get('target_domains')[0]
        enabled_plugins = self._enabled_plugins
        findings = kb.kb.get_all_findings()
        debug_log = ((t, l, smart_unicode(m)) for (t, l, m) in self._additional_info)
        known_urls = kb.kb.get_all_known_urls()

        context = {'target_urls': target_urls,
                   'target_domain': target_domain,
                   'enabled_plugins': enabled_plugins,
                   'findings': findings,
                   'debug_log': debug_log,
                   'known_urls': known_urls}

        # The file was verified to exist when setting the plugin configuration
        template_fh = file(os.path.expanduser(self._template), 'r')
        output_fh = file(os.path.expanduser(self._output_file_name), 'w')

        self._render_html_file(template_fh, context, output_fh)

    def _render_html_file(self, template_fh, context, output_fh):
        """
        Renders the HTML file using the configured template. Separated as a
        method to be able to easily test.

        :param context: A dict containing target urls, enabled plugins, etc.
        :return: True on successful rendering
        """
        severity_icon = functools.partial(get_severity_icon, self.template_root)

        env_config = {'undefined': StrictUndefined,
                      'trim_blocks': True,
                      'autoescape': True,
                      'lstrip_blocks': True}

        try:
            jinja2_env = Environment(**env_config)
        except TypeError:
            # Kali uses a different jinja2 version, which doesn't have the same
            # Environment kwargs, so we first try with the version we expect
            # to have available, and then if it doesn't work apply this
            # workaround for Kali
            #
            # https://github.com/andresriancho/w3af/issues/9552
            env_config.pop('lstrip_blocks')
            jinja2_env = Environment(**env_config)

        jinja2_env.filters['render_markdown'] = render_markdown
        jinja2_env.filters['request'] = request_dump
        jinja2_env.filters['response'] = response_dump
        jinja2_env.filters['severity_icon'] = severity_icon
        jinja2_env.filters['severity_text'] = get_severity_text
        jinja2_env.globals['get_current_date'] = get_current_date
        jinja2_env.loader = FileSystemLoader(self.template_root)

        template = jinja2_env.from_string(template_fh.read())

        try:
            rendered_output = template.render(context)
        except Exception, e:
            msg = u'Failed to render html report template. Exception: "%s"'
            om.out.error(msg % e)
            return False

        try:
            output_fh.write(rendered_output.encode('utf-8'))
        except Exception, e:
            msg = u'Failed to write html report to output file. Exception: "%s"'
            om.out.error(msg % e)
            return False