From 1a66aeb39e3196879862a7d806ea009a095a6ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Hojtsy?= Date: Thu, 30 Aug 2007 15:53:39 +0000 Subject: #171606 by Heine: ported security fix from Drupal 4.7/5; use SCRIPT_NAME instead of PHP_SELF in links to avoid XSS holes --- includes/bootstrap.inc | 20 +++++++++++++------- includes/common.inc | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'includes') diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index fbde69187..66249c534 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -237,7 +237,7 @@ function conf_path($require_settings = TRUE, $reset = FALSE) { } $confdir = 'sites'; - $uri = explode('/', $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_FILENAME']); + $uri = explode('/', $_SERVER['SCRIPT_NAME'] ? $_SERVER['SCRIPT_NAME'] : $_SERVER['SCRIPT_FILENAME']); $server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.'))))); for ($i = count($uri) - 1; $i > 0; $i--) { for ($j = count($server); $j > 0; $j--) { @@ -294,8 +294,14 @@ function conf_init() { else { // Create base URL $base_root = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; - $base_url = $base_root .= '://'. $_SERVER['HTTP_HOST']; - if ($dir = trim(dirname($_SERVER['PHP_SELF']), '\,/')) { + + // As $_SERVER['HTTP_HOST'] is user input, ensure it only contains + // characters allowed in hostnames. + $base_url = $base_root .= '://'. preg_replace('/[^a-z0-9-:._]/i', '', $_SERVER['HTTP_HOST']); + + // $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not + // be modified by a visitor. + if ($dir = trim(dirname($_SERVER['SCRIPT_NAME']), '\,/')) { $base_path = "/$dir"; $base_url .= $base_path; $base_path .= '/'; @@ -313,9 +319,9 @@ function conf_init() { // Otherwise use $base_url as session name, without the protocol // to use the same session identifiers across http and https. list( , $session_name) = explode('://', $base_url, 2); - // We try to set the cookie domain to the hostname. + // We escape the hostname because it can be modified by a visitor. if (!empty($_SERVER['HTTP_HOST'])) { - $cookie_domain = $_SERVER['HTTP_HOST']; + $cookie_domain = check_plain($_SERVER['HTTP_HOST']); } } // Strip leading periods, www., and port numbers from cookie domain. @@ -674,10 +680,10 @@ function request_uri() { } else { if (isset($_SERVER['argv'])) { - $uri = $_SERVER['PHP_SELF'] .'?'. $_SERVER['argv'][0]; + $uri = $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['argv'][0]; } else { - $uri = $_SERVER['PHP_SELF'] .'?'. $_SERVER['QUERY_STRING']; + $uri = $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['QUERY_STRING']; } } diff --git a/includes/common.inc b/includes/common.inc index 9cbf27e45..2110edc4e 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -562,7 +562,7 @@ function drupal_error_handler($errno, $message, $filename, $line, $context) { $entry = $types[$errno] .': '. $message .' in '. $filename .' on line '. $line .'.'; // Force display of error messages in update.php - if (variable_get('error_level', 1) == 1 || strstr($_SERVER['PHP_SELF'], 'update.php')) { + if (variable_get('error_level', 1) == 1 || strstr($_SERVER['SCRIPT_NAME'], 'update.php')) { drupal_set_message($entry, 'error'); } -- cgit v1.2.3