? dwtc-link-escape.patch ? insecure_filter_configurations.patch ? insecure_filter_configurations_2.patch ? test.php ? sites/all/modules/codefilter ? sites/all/modules/devel ? sites/all/modules/pgp ? sites/default/files ? sites/default/private ? sites/default/settings.php Index: modules/filter/filter.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.admin.inc,v retrieving revision 1.42 diff -u -p -r1.42 filter.admin.inc --- modules/filter/filter.admin.inc 28 Aug 2009 16:23:04 -0000 1.42 +++ modules/filter/filter.admin.inc 3 Sep 2009 16:01:24 -0000 @@ -112,6 +112,11 @@ function filter_admin_format_page($forma * @see filter_admin_format_form_submit() */ function filter_admin_format_form(&$form_state, $format) { + if (empty($_POST) && !empty($format->format) && !filter_format_is_secure($format->format, $errors)) { + foreach ($errors as $message) { + drupal_set_message($message, 'error'); + } + } $default = ($format->format == variable_get('filter_default_format', 1)); if ($default) { $help = t('All roles for the default format must be enabled and cannot be changed.'); Index: modules/filter/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v retrieving revision 1.287 diff -u -p -r1.287 filter.module --- modules/filter/filter.module 30 Aug 2009 06:04:09 -0000 1.287 +++ modules/filter/filter.module 3 Sep 2009 16:01:25 -0000 @@ -516,6 +516,37 @@ function filter_list_format($format) { } /** + * Determines if a text format is configured securely. + * + * @param $format + * The ID of the format to check. + * @param $errors + * An array to which error messages will be added if the format is insecure, + * explaining the reasons why it is insecure. + * @return + * TRUE if the format is configured securely, FALSE otherwise. + */ +function filter_format_is_secure($format, &$errors) { + // All text formats start off as insecure, because unfiltered HTML is by + // definition not safe. + $errors['html'][] = t('No filter has been added to sanitize raw HTML.'); + $filters = filter_list_format($format); + $filter_info = filter_get_filters(); + foreach ($filters as $name => $filter) { + if (isset($filter_info[$name]['security callback']) && function_exists($filter_info[$name]['security callback'])) { + $callback_function = $filter_info[$name]['security callback']; + $callback_function($errors, $filter); + } + } + + // Flatten the errors into a single array of messages. + $errors = call_user_func_array('array_merge', $errors); + + // Return TRUE (the format is secure) if there are no errors remaining. + return empty($errors); +} + +/** * @name Filtering functions * @{ * Modules which need to have content filtered can use these functions to @@ -736,6 +767,18 @@ function filter_dom_serialize($dom_docum } /** + * Splits a string containing HTML tags into an array of tag names. + * + * @param $tag_string + * A string containing HTML tags; for example, ' '. + * @return + * An array of tag names; for example, array('a', 'em', 'strong'). + */ +function _filter_split_tags($tag_string) { + return preg_split('/\s+|<|>/', $tag_string, -1, PREG_SPLIT_NO_EMPTY); +} + +/** * Format a link to the more extensive filter tips. * * @ingroup themeable @@ -768,6 +811,7 @@ function filter_filter_info() { 'title' => t('Limit allowed HTML tags'), 'description' => t('Allows you to restrict the HTML tags the user can use. It will also remove harmful content such as JavaScript events, JavaScript URLs and CSS styles from those tags that are not removed.'), 'process callback' => '_filter_html', + 'security callback' => '_filter_html_check_security', 'settings callback' => '_filter_html_settings', 'default settings' => array( 'allowed_html' => '
    1. ', @@ -801,6 +845,7 @@ function filter_filter_info() { 'title' => t('Escape all HTML'), 'description' => t('Escapes all HTML tags, so they will be visible instead of being effective.'), 'process callback' => '_filter_html_escape', + 'security callback' => '_filter_html_escape_check_security', 'tips callback' => '_filter_html_escape_tips', ); return $filters; @@ -834,10 +879,29 @@ function _filter_html_settings(&$form_st } /** + * Security callback for the HTML filter. + */ +function _filter_html_check_security(&$errors, $filter) { + $allowed_tags = _filter_split_tags($filter->settings['allowed_html']); + $dangerous_tags = array('object', 'embed', 'script', 'style'); // Obviously we can expand this later! + $tags = array_intersect($dangerous_tags, $allowed_tags); + // If the output is already safe HTML, then allowing dangerous tags here + // will do no harm. Otherwise we want to generate a useful warning. + if ($tags && !empty($errors['html'])) { + $errors['html'][] = t('Allowing these tags is dangerous: %tags', array('%tags' => implode(', ', $tags))); + } + else { + // If no dangerous tags are explicitly allowed, then the output of this + // filter is safe HTML. + $errors['html'] = array(); + } +} + +/** * HTML filter. Provides filtering of input into accepted HTML. */ function _filter_html($text, $filter) { - $allowed_tags = preg_split('/\s+|<|>/', $filter->settings['allowed_html'], -1, PREG_SPLIT_NO_EMPTY); + $allowed_tags = _filter_split_tags($filter->settings['allowed_html']); $text = filter_xss($text, $allowed_tags); if ($filter->settings['filter_html_nofollow']) { @@ -1000,6 +1064,15 @@ function _filter_html_escape($text) { } /** + * Security callback for the HTML escaping filter. + */ +function _filter_html_escape_check_security(&$errors, $filter) { + // Because this filter escapes all HTML, it prevents XSS attacks from going + // through. + $errors['html'] = array(); +} + +/** * @} End of "Standard filters". */ Index: modules/php/php.module =================================================================== RCS file: /cvs/drupal/drupal/modules/php/php.module,v retrieving revision 1.20 diff -u -p -r1.20 php.module --- modules/php/php.module 27 Aug 2009 21:18:19 -0000 1.20 +++ modules/php/php.module 3 Sep 2009 16:01:25 -0000 @@ -127,9 +127,17 @@ function php_filter_info() { 'title' => t('PHP evaluator'), 'description' => t('Executes a piece of PHP code. The usage of this filter should be restricted to administrators only!'), 'process callback' => 'php_eval', + 'security callback' => '_php_check_security', 'tips callback' => '_php_filter_tips', 'cache' => FALSE, ); return $filters; } +/** + * Security callback for the PHP filter. + */ +function _php_check_security(&$errors, $filter) { + // Any format using this filter is insecure. + $errors['php'][] = t('This filter allows users to execute arbitrary PHP code on your site.'); +}