Index: includes/bootstrap.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v retrieving revision 1.44 diff -u -r1.44 bootstrap.inc --- includes/bootstrap.inc 5 Apr 2005 19:00:24 -0000 1.44 +++ includes/bootstrap.inc 30 Nov 2005 20:32:56 -0000 @@ -538,19 +538,6 @@ } /** - * Prepare a URL for use in an HTML attribute. - * - * We replace ( and ) with their url-encoded equivalents to prevent XSS attacks. - */ -function check_url($uri) { - $uri = htmlspecialchars($uri, ENT_QUOTES); - - $uri = strtr($uri, array('(' => '%28', ')' => '%29')); - - return $uri; -} - -/** * Since request_uri() is only available on Apache, we generate an * equivalent using other environment vars. */ @@ -636,6 +623,13 @@ return $messages; } +/** + * Encode special characters in a plain-text string for display as HTML. + */ +function check_plain($text) { + return htmlspecialchars($text, ENT_QUOTES); +} + unset($conf); $config = conf_init(); Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.434.2.10 diff -u -r1.434.2.10 common.inc --- includes/common.inc 29 Jul 2005 19:05:31 -0000 1.434.2.10 +++ includes/common.inc 30 Nov 2005 20:32:56 -0000 @@ -548,13 +548,6 @@ } /** - * Encode special characters in a plain-text string for display as HTML. - */ -function check_plain($text) { - return htmlspecialchars($text, ENT_QUOTES); -} - -/** * @defgroup validation Input validation * @{ * Functions to validate user input. @@ -600,54 +593,6 @@ } /** - * Validate data input by a user. - * - * Ensures that user data cannot be used to perform attacks on the site. - * - * @param $data - * The input to check. - * @return - * TRUE if the input data is acceptable. - */ -function valid_input_data($data) { - if (is_array($data) || is_object($data)) { - // Form data can contain a number of nested arrays. - foreach ($data as $key => $value) { - if (!valid_input_data($key) || !valid_input_data($value)) { - return FALSE; - } - } - } - else if (isset($data)) { - // Detect dangerous input data. - - // Decode all normal character entities. - $data = decode_entities($data, array('<', '&', '"')); - - // Check strings: - $match = preg_match('/\Wjavascript\s*:/i', $data); - $match += preg_match('/\Wexpression\s*\(/i', $data); - $match += preg_match('/\Walert\s*\(/i', $data); - - // Check attributes: - $match += preg_match("/\W(dynsrc|datasrc|data|lowsrc|on[a-z]+)\s*=[^>]+?>/i", $data); - - // Check tags: - $match += preg_match("/<\s*(applet|script|object|style|embed|form|blink|meta|html|frame|iframe|layer|ilayer|head|frameset|xml)/i", $data); - - if ($match) { - watchdog('security', t('Terminated request because of suspicious input data: %data.', array('%data' => theme('placeholder', $data)))); - return FALSE; - } - } - - return TRUE; -} -/** - * @} End of "defgroup validation". - */ - -/** * Register an event for the current visitor (hostname/IP) to the flood control mechanism. * * @param $name @@ -679,6 +624,17 @@ } /** + * Prepare a URL for use in an HTML attribute. Strips harmful protocols. + * + */ +function check_url($uri) { + $uri = htmlspecialchars($uri, ENT_QUOTES); + $uri = filter_xss_bad_protocol($uri, FALSE); + + return $uri; +} + +/** * @defgroup format Formatting * @{ * Functions to format numbers, strings, dates, etc. @@ -1054,7 +1010,7 @@ * A themed HTML string representing the form item group. */ function form_group($legend, $group, $description = NULL) { - return '
' . ($legend ? ''. $legend .'' : '') . $group . ($description ? '
'. $description .'
' : '') . "
\n"; + return '
' . ($legend ? ''. check_plain($legend) .'' : '') . $group . ($description ? '
'. $description .'
' : '') . "
\n"; } /** @@ -1078,7 +1034,7 @@ * A themed HTML string representing the radio button. */ function form_radio($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) { - $element = ''; + $element = ''; if (!is_null($title)) { $element = ''; } @@ -1110,7 +1066,7 @@ if (count($options) > 0) { $choices = ''; foreach ($options as $key => $choice) { - $choices .= '
'; + $choices .= '
'; } return theme('form_element', $title, $choices, $description, NULL, $required, _form_get_error($name)); } @@ -1137,7 +1093,7 @@ * A themed HTML string representing the checkbox. */ function form_checkbox($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) { - $element = ''; + $element = ''; if (!is_null($title)) { $element = ''; } @@ -1174,7 +1130,7 @@ } $choices = ''; foreach ($options as $key => $choice) { - $choices .= '
'; + $choices .= '
'; } // Note: because unchecked boxes are not included in the POST data, we // include a form_hidden() which will be overwritten as soon as there is at @@ -1260,7 +1216,6 @@ function form_password($title, $name, $v * A themed HTML string representing the field. */ function form_textarea($title, $name, $value, $cols, $rows, $description = NULL, $attributes = NULL, $required = FALSE) { - $cols = $cols ? ' cols="'. $cols .'"' : ''; $pre = ''; $post = ''; @@ -1272,7 +1227,7 @@ function form_textarea($title, $name, $v } } - return theme('form_element', $title, $pre .''. $post, $description, 'edit-'. $name, $required, _form_get_error($name)); + return theme('form_element', $title, $pre .''. $post, $description, 'edit-'. $name, $required, _form_get_error($name)); } /** @@ -1307,14 +1263,14 @@ $select = ''; foreach ($options as $key => $choice) { if (is_array($choice)) { - $select .= ''; + $select .= ''; foreach ($choice as $key => $choice) { - $select .= ''; + $select .= ''; } $select .= ''; } else { - $select .= ''; + $select .= ''; } } return theme('form_element', $title, '', $description, 'edit-'. $name, $required, _form_get_error($name)); @@ -1799,6 +1755,10 @@ if ($prefix == '#x') { $codepoint = base_convert($codepoint, 16, 10); } + else { + // Decimal numerical entity (strip leading zeros to avoid PHP octal notation) + $codepoint = preg_replace('/^0+/', '', $codepoint); + } // Encode codepoint as UTF-8 bytes if ($codepoint < 0x80) { $str = chr($codepoint); @@ -1918,18 +1878,6 @@ // Initialize all enabled modules. module_init(); -if (!user_access('bypass input data check')) { - // We can't use $_REQUEST because it consists of the contents of $_POST, - // $_GET and $_COOKIE: if any of the input arrays share a key, only one - // value will be verified. - if (!valid_input_data($_GET) - || !valid_input_data($_POST) - || !valid_input_data($_COOKIE) - || !valid_input_data($_FILES)) { - die('Terminated request because of suspicious input data.'); - } -} - // Initialize the localization system. $locale = locale_initialize(); Index: includes/database.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v retrieving revision 1.27.2.2 diff -u -r1.27.2.2 database.mysql.inc --- includes/database.mysql.inc 14 Aug 2005 09:58:26 -0000 1.27.2.2 +++ includes/database.mysql.inc 30 Nov 2005 20:32:56 -0000 @@ -63,7 +63,7 @@ return $result; } else { - trigger_error(mysql_error() ."\nquery: ". htmlspecialchars($query), E_USER_ERROR); + trigger_error(check_plain(mysql_error() ."\nquery: ". $query), E_USER_ERROR); return FALSE; } } Index: includes/database.pgsql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.pgsql.inc,v retrieving revision 1.6.2.2 diff -u -r1.6.2.2 database.pgsql.inc --- includes/database.pgsql.inc 14 Aug 2005 09:58:26 -0000 1.6.2.2 +++ includes/database.pgsql.inc 30 Nov 2005 20:32:56 -0000 @@ -59,7 +59,7 @@ return $last_result; } else { - trigger_error(pg_last_error() ."\nquery: ". htmlspecialchars($query), E_USER_ERROR); + trigger_error(check_plain(pg_last_error() ."\nquery: ". $query), E_USER_ERROR); return FALSE; } } Index: modules/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator.module,v retrieving revision 1.233.2.6 diff -u -r1.233.2.6 aggregator.module --- modules/aggregator.module 3 Jul 2005 16:09:12 -0000 1.233.2.6 +++ modules/aggregator.module 30 Nov 2005 20:32:56 -0000 @@ -483,9 +483,7 @@ foreach ($item as $key => $value) { // TODO: Make handling of aggregated HTML more flexible/configurable. $value = decode_entities(trim($value)); - $value = strip_tags($value, '