Prevent Host header injections
diff --git a/application/config/config.php b/application/config/config.php
index 479d591..4f8f814 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -11,10 +11,16 @@
 |
 |	http://example.com/
 |
-| If this is not set then CodeIgniter will try guess the protocol, domain
-| and path to your installation. However, you should always configure this
-| explicitly and never rely on auto-guessing, especially in production
-| environments.
+| WARNING: You MUST set this value!
+|
+| If it is not set, then CodeIgniter will try guess the protocol and path
+| your installation, but due to security concerns the hostname will be set
+| to $_SERVER['SERVER_ADDR'] if available, or localhost otherwise.
+| The auto-detection mechanism exists only for convenience during
+| development and MUST NOT be used in production!
+|
+| If you need to allow multiple domains, remember that this file is still
+| a PHP script and you can easily do that on your own.
 |
 */
 $config['base_url'] = '';
diff --git a/system/core/Config.php b/system/core/Config.php
index feea7c8..0264776 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -88,11 +88,9 @@
 		// Set the base_url automatically if none was provided
 		if (empty($this->config['base_url']))
 		{
-			// The regular expression is only a basic validation for a valid "Host" header.
-			// It's not exhaustive, only checks for valid characters.
-			if (isset($_SERVER['HTTP_HOST']) && preg_match('/^((\[[0-9a-f:]+\])|(\d{1,3}(\.\d{1,3}){3})|[a-z0-9\-\.]+)(:\d+)?$/i', $_SERVER['HTTP_HOST']))
+			if (isset($_SERVER['SERVER_ADDR']))
 			{
-				$base_url = (is_https() ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST']
+				$base_url = (is_https() ? 'https' : 'http').'://'.$_SERVER['SERVER_ADDR']
 					.substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])));
 			}
 			else
diff --git a/tests/codeigniter/core/Config_test.php b/tests/codeigniter/core/Config_test.php
index f125fc6..26a5f32 100644
--- a/tests/codeigniter/core/Config_test.php
+++ b/tests/codeigniter/core/Config_test.php
@@ -79,46 +79,33 @@
 		$old_script_name = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : NULL;
 		$old_script_filename = $_SERVER['SCRIPT_FILENAME'];
 		$old_https = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : NULL;
+		$old_server_addr = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : NULL;
 
-		// Setup server vars for detection
-		$host = 'test.com';
-		$path = '/';
-		$script = 'base_test.php';
-		$_SERVER['HTTP_HOST'] = $host;
-		$_SERVER['SCRIPT_NAME'] = $path.$script;
-		$_SERVER['SCRIPT_FILENAME'] = '/foo/bar/'.$script;
-
-		// Rerun constructor
+		// The 'Host' header is user input and must not be trusted
+		$_SERVER['HTTP_HOST'] = 'test.com';
 		$this->config = new $cls;
+		$this->assertEquals('http://localhost/', $this->config->base_url());
 
-		// Test plain detected (root)
-		$this->assertEquals('http://'.$host.$path, $this->config->base_url());
-
-		// Rerun constructor
-		$path = '/path/';
-		$_SERVER['SCRIPT_NAME'] = $path.$script;
-		$_SERVER['SCRIPT_FILENAME'] = '/foo/bar/'.$path.$script;
+		// However, we may fallback to the server's IP address
+		$_SERVER['SERVER_ADDR'] = '127.0.0.1';
+		$_SERVER['SCRIPT_NAME'] = '/base_test.php';
+		$_SERVER['SCRIPT_FILENAME'] = '/foo/bar/base_test.php';
 		$this->config = new $cls;
+		$this->assertEquals('http://127.0.0.1/', $this->config->base_url());
 
-		// Test plain detected (subfolder)
-		$this->assertEquals('http://'.$host.$path, $this->config->base_url());
-
-		// Rerun constructor
+		// Making sure that HTTPS and URI path are also detected
 		$_SERVER['HTTPS'] = 'on';
+		$_SERVER['SCRIPT_NAME'] = '/path/base_test.php';
+		$_SERVER['SCRIPT_FILENAME'] = '/foo/bar/path/base_test.php';
 		$this->config = new $cls;
-
-		// Test secure detected
-		$this->assertEquals('https://'.$host.$path, $this->config->base_url());
+		$this->assertEquals('https://127.0.0.1/path/', $this->config->base_url());
 
 		// Restore server vars
-		if ($old_host === NULL) unset($_SERVER['HTTP_HOST']);
-		else $_SERVER['HTTP_HOST'] = $old_host;
-		if ($old_script_name === NULL) unset($_SERVER['SCRIPT_NAME']);
-		else $_SERVER['SCRIPT_NAME'] = $old_script_name;
-		if ($old_https === NULL) unset($_SERVER['HTTPS']);
-		else $_SERVER['HTTPS'] = $old_https;
-
+		$_SERVER['HTTP_HOST'] = $old_host;
+		$_SERVER['SCRIPT_NAME'] = $old_script_name;
 		$_SERVER['SCRIPT_FILENAME'] = $old_script_filename;
+		$_SERVER['HTTPS'] = $old_https;
+		$_SERVER['SERVER_ADDR'] = $old_server_addr;
 	}
 
 	// --------------------------------------------------------------------