Skip to content

Commit

Permalink
# [#32453] Super user password doesnt update hash and some other issu…
Browse files Browse the repository at this point in the history
…es (Fix #2358)
  • Loading branch information
phproberto committed Oct 29, 2013
1 parent c26eb43 commit c6a2461
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 26 deletions.
3 changes: 3 additions & 0 deletions installation/CHANGELOG
Expand Up @@ -25,6 +25,9 @@ $ -> Language fix or change
- -> Removed
! -> Note

29-Oct-2013 Roberto Segura
# [#32453] Super user password doesn't update hash and some other issues. Thanks Elin Waring

28-Oct-2013 Michael Babker
# [#32375] Regression 3 column blog layout - prototsar. Thanks Thomas Hunziker
# [#32379] Regression: Preformatted images and urls broken in back weblinks and newsfeeds. Thanks Elin Waring
Expand Down
4 changes: 3 additions & 1 deletion installation/model/configuration.php
Expand Up @@ -254,7 +254,9 @@ private function _createRootUser($options)
else
{
$salt = JUserHelper::genRandomPassword(16);
$cryptpass = JUserHelper::getCryptedPassword($options->admin_password, $salt, 'sha256') . ':' . $salt;
//$cryptpass = JUserHelper::getCryptedPassword($options->admin_password, $salt, 'sha256') . ':' . $salt;
$cryptpass = JUserHelper::getCryptedPassword($options->admin_password, $salt, 'sha256');

}

// Take the admin user id
Expand Down
7 changes: 3 additions & 4 deletions libraries/compat/password/lib/password.php
Expand Up @@ -11,7 +11,6 @@

define('PASSWORD_BCRYPT', 1);
define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
define('BCRYPT_HASH_PREFIX', (version_compare(PHP_VERSION, '5.3.7', '<') ? '$2a$' : '$2y$'));

/**
* Hash the password using the specified algorithm
Expand Down Expand Up @@ -50,7 +49,7 @@ function password_hash($password, $algo, array $options = array()) {
$raw_salt_len = 16;
// The length required in the final serialization
$required_salt_len = 22;
$hash_format = sprintf(BCRYPT_HASH_PREFIX . "%02d$", $cost);
$hash_format = sprintf("$2y$%02d$", $cost);
break;
default:
trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
Expand Down Expand Up @@ -158,10 +157,10 @@ function password_get_info($hash) {
'algoName' => 'unknown',
'options' => array(),
);
if (substr($hash, 0, 4) == BCRYPT_HASH_PREFIX && strlen($hash) == 60) {
if (substr($hash, 0, 4) == "$2y$%d$" && strlen($hash) == 60) {
$return['algo'] = PASSWORD_BCRYPT;
$return['algoName'] = 'bcrypt';
list($cost) = sscanf($hash, BCRYPT_HASH_PREFIX . "%d$");
list($cost) = sscanf($hash, "$2y$%d$");
$return['options']['cost'] = $cost;
}
return $return;
Expand Down
25 changes: 25 additions & 0 deletions libraries/compat/password/lib/version_test.php
@@ -0,0 +1,25 @@
<?php
/**
* A Compatibility library with PHP 5.5's simplified password hashing API.
*
* @author Anthony Ferrara <ircmaxell@php.net>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @copyright 2012 The Authors
*/
/**
* Modififations
* Open Source Matters 2013
* CMS version 3.2
*
*/
class version_test
{
public function version_test()
{
$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
$test = crypt("password", $hash);
$pass = $test == $hash;

return $pass;
}
}
16 changes: 4 additions & 12 deletions libraries/joomla/crypt/crypt.php
Expand Up @@ -310,25 +310,17 @@ public static function hasStrongPasswordSupport()
if (is_null($pass))
{
// Check to see whether crypt() is supported.
if (version_compare(PHP_VERSION, '5.3.6', '>'))
if (version_compare(PHP_VERSION, '5.3.7', '>=') === true)
{
// We have safe PHP version.
$pass = true;
}
else
{
// We need to test if we have patched PHP version.
$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
$test = crypt("password", $hash);
$pass = ($test == $hash);

// Test to allow for for Debian backport of bcrypt the 5.3.7 fix.
// See https://github.com/ircmaxell/password_compat/pull/34#issuecomment-26648055
if(crypt('éàèç', '$2a$05$0123456789012345678901$') === crypt('éàèç', '$2x$05$0123456789012345678901$'))
{
// $2a$ is insecure.
$pass = false;
}
jimport('compat.password.lib.version_test');
$test = new version_test;
$pass = $test->version_test();
}

if ($pass && !defined('PASSWORD_DEFAULT'))
Expand Down
16 changes: 12 additions & 4 deletions libraries/joomla/user/helper.php
Expand Up @@ -9,6 +9,9 @@

defined('JPATH_PLATFORM') or die;

// Always make sure that the password hashing API has been defined.
//include_once JPATH_ROOT . '/libraries/compat/password/lib/password.php';

/**
* Authorisation helper class, provides static methods to perform various tasks relevant
* to the Joomla user and authorisation classes
Expand Down Expand Up @@ -342,7 +345,10 @@ public static function getCryptedPassword($plaintext, $salt = '', $encryption =
}

// Get the salt to use.
$salt = self::getSalt($encryption, $salt, $plaintext);
if (empty($salt))
{
$salt = self::getSalt($encryption, $salt, $plaintext);
}

// Encrypt the password.
switch ($encryption)
Expand Down Expand Up @@ -430,21 +436,23 @@ public static function getCryptedPassword($plaintext, $salt = '', $encryption =
return ($show_encrypt) ? '{MD5}' . $encrypted : $encrypted;

case 'sha256':
$encrypted = ($salt) ? hash('sha256', $plaintext . $salt) : hash('sha256', $plaintext);
$encrypted = ($salt) ? hash('sha256', $plaintext . $salt) . ':' . $salt : hash('sha256', $plaintext);

return ($show_encrypt) ? '{SHA256}' . $encrypted : '{SHA256}' . $encrypted;

// 'bcrypt' is the default case starting in CMS 3.2.
case 'bcrypt':
default:
if (JCrypt::hasStrongPasswordSupport())
$useStrongEncryption = JCrypt::hasStrongPasswordSupport();

if ($useStrongEncryption === true)
{
$encrypted = password_hash($plaintext, PASSWORD_BCRYPT);

if (!$encrypted)
{
// Something went wrong fall back to sha256.
return static::getCryptedPassword($plaintext, '', 'sha256', false);
return static::getCryptedPassword($plaintext, '', 'sha256', false);
}

return ($show_encrypt) ? '{BCRYPT}' . $encrypted : $encrypted;
Expand Down
10 changes: 8 additions & 2 deletions libraries/joomla/user/user.php
Expand Up @@ -581,7 +581,7 @@ public function bind(&$array)

$salt = JUserHelper::genRandomPassword(32);
$crypt = JUserHelper::getCryptedPassword($array['password'], $salt, $defaultEncryption);
$array['password'] = $crypt . ':' . $salt;
$array['password'] = $crypt;

// Set the registration timestamp
$this->set('registerDate', JFactory::getDate()->toSql());
Expand Down Expand Up @@ -715,8 +715,14 @@ public function save($updateOnly = false)
// Check if I am a Super Admin
$iAmSuperAdmin = $my->authorise('core.admin');

$iAmRehashingSuperadmin = false;
if (($my->id == 0 && !$isNew) && $this->id == $oldUser->id && $oldUser->authorise('core.admin') && substr($oldUser->password, 0, 4) != '$2y$')
{
$iAmRehashingSuperadmin = true;
}

// We are only worried about edits to this account if I am not a Super Admin.
if ($iAmSuperAdmin != true)
if ($iAmSuperAdmin != true && $iAmRehashingSuperadmin != true)
{
if ($isNew)
{
Expand Down
4 changes: 2 additions & 2 deletions plugins/authentication/joomla/joomla.php
Expand Up @@ -54,7 +54,7 @@ public function onUserAuthenticate($credentials, $options, &$response)

if ($result)
{
if (substr($result->password, 0, 4) == '$2y$' || substr($result->password, 0, 4) == '$2a$')
if (substr($result->password, 0, 4) == '$2y$')
{
// BCrypt passwords are always 60 characters, but it is possible that salt is appended although non standard.
$password60 = substr($result->password, 0, 60);
Expand All @@ -72,7 +72,7 @@ public function onUserAuthenticate($credentials, $options, &$response)
$salt = @$parts[1];
$testcrypt = JUserHelper::getCryptedPassword($credentials['password'], $salt, 'sha256', false);

if ($crypt == $testcrypt)
if ($result->password == $testcrypt)
{
$match = true;
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/system/remember/remember.php
Expand Up @@ -160,7 +160,7 @@ public function onAfterInitialise()
// We have a user with one cookie with a valid series and a corresponding record in the database.
if ($countResults === 1)
{
if (substr($results[0]->token, 0, 4) === '$2y$' || substr($results[0]->token, 0, 4) == '$2a$')
if (substr($results[0]->token, 0, 4) === '$2y$')
{
if (JCrypt::hasStrongPasswordSupport())
{
Expand Down

0 comments on commit c6a2461

Please sign in to comment.