Commit f818dfe9 authored by Dries's avatar Dries

- Patch #590656 by pwolanin, Pasqualle: harden one-time login links against...

- Patch #590656 by pwolanin, Pasqualle: harden one-time login links against vulnerability from disclosure of SQL backups, or SQL 'SELECT' injection.
parent 913f2c3a
......@@ -532,7 +532,7 @@ function drupal_settings_initialize() {
global $base_url, $base_path, $base_root;
// Export the following settings.php variables to the global namespace
global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $is_https, $base_secure_url, $base_insecure_url;
global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url;
$conf = array();
if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {
......
......@@ -4460,6 +4460,19 @@ function drupal_random_bytes($count) {
return substr($output, 0, $count);
}
/**
* Get a salt useful for hardening against SQL injection.
*
* @return
* A salt based on information in settings.php, not in the database.
*/
function drupal_get_hash_salt() {
global $drupal_hash_salt, $databases;
// If the $drupal_hash_salt variable is empty, a hash of the serialized
// database credentials is used as a fallback salt.
return empty($drupal_hash_salt) ? sha1(serialize($databases)) : $drupal_hash_salt;
}
/**
* Ensure the private key variable used to generate tokens is set.
*
......@@ -4482,7 +4495,9 @@ function drupal_get_private_key() {
*/
function drupal_get_token($value = '') {
$private_key = drupal_get_private_key();
return md5(session_id() . $value . $private_key);
// A single md5() is vulnerable to length-extension attacks, so use it twice.
// @todo: add md5 and sha1 hmac functions to core.
return md5(drupal_get_hash_salt() . md5(session_id() . $value . $private_key));
}
/**
......@@ -4500,7 +4515,7 @@ function drupal_get_token($value = '') {
*/
function drupal_valid_token($token, $value = '', $skip_anonymous = FALSE) {
global $user;
return (($skip_anonymous && $user->uid == 0) || ($token == md5(session_id() . $value . variable_get('drupal_private_key', ''))));
return (($skip_anonymous && $user->uid == 0) || ($token == drupal_get_token($value)));
}
function _drupal_bootstrap_full() {
......
......@@ -262,7 +262,8 @@ function update_fix_d7_requirements() {
global $update_rewrite_settings, $db_url;
if (!empty($update_rewrite_settings)) {
$databases = update_parse_db_url($db_url);
file_put_contents(conf_path() . '/settings.php', "\n" . '$databases = ' . var_export($databases, TRUE) . ';', FILE_APPEND);
$salt = sha1(drupal_random_bytes(64));
file_put_contents(conf_path() . '/settings.php', "\n" . '$databases = ' . var_export($databases, TRUE) . ";\n\$drupal_hash_salt = '$salt';", FILE_APPEND);
}
if (drupal_get_installed_schema_version('system') < 7000 && !variable_get('update_d7_requirements', FALSE)) {
// Add the cache_path table.
......
......@@ -1002,6 +1002,10 @@ function install_settings_form_submit($form, &$form_state) {
'value' => $form_state['values']['db_prefix'],
'required' => TRUE,
);
$settings['drupal_hash_salt'] = array(
'value' => sha1(drupal_random_bytes(64)),
'required' => TRUE,
);
drupal_rewrite_settings($settings);
// Indicate that the settings file has been verified, and check the database
// for the last completed task, now that we have a valid connection. This
......
......@@ -2029,7 +2029,8 @@ function user_cancel_url($account) {
}
function user_pass_rehash($password, $timestamp, $login) {
return md5($timestamp . $password . $login);
// A single md5() is vulnerable to length-extension attacks, so use it twice.
return md5(drupal_get_hash_salt() . md5($timestamp . $password . $login));
}
/**
......
......@@ -167,6 +167,25 @@
*/
$update_free_access = FALSE;
/**
* Salt for one-time login links and cancel links, form tokens, etc.
*
* This variable will be set to a random value by the installer. All one-time
* login links will be invalidated if the value is changed. Note that this
* variable must have the same value on every web server. If this variable is
* empty, a hash of the serialized database credentials will be used as a
* fallback salt.
*
* For enhanced security, you may set this variable to a value using the
* contents of a file outside your docroot that is never saved together
* with any backups of your Drupal files and database.
*
* Example:
* $drupal_hash_salt = file_get_contents('/home/example/salt.txt');
*
*/
$drupal_hash_salt = '';
/**
* Base URL (optional).
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment