diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index fbde69187694a9b4ab18a6203dd15ab7d1636c37..66249c5340631de866adbcc2bce2fd9d63412d0d 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 9cbf27e45ba59a216d6bdd703457a8dcfc092d5f..2110edc4e2132696c4d0f71afb1c0da7e21bae6d 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');
     }