Live free, frag hard.
You are not logged in.
Pages: 1
This thread is here to discuss the password hashing framework phpass and its implementation in FluxBB.
Reference: http://www.openwall.com/phpass/
Useful reading: http://www.openwall.com/articles/PHP-Users-Passwords
FluxBB modification available for download here: http://fluxbb.org/resources/mods/gamezoo-phpass
FluxBB modification README.txt:
##
##
## Mod title: GameZoo PHPass for FluxBB
##
## Mod version: 0.1
## Works on FluxBB: 1.5.*
## Release date: 2014-09-08
## Author: seven (seven@gamezoo.org)
##
## Description: This mod enables PHPass on your FluxBB forum.
## The passwords are updated automatically when the user
## attempts to login.
##
## Affected files: install.php
## login.php
## profile.php
## register.php
## include/functions.php
## include/PasswordHash.php (new file)
##
## Affects DB: Yes
## - altered table: users (password goes from 40 to 60 chars)
##
## Notes: You cannot revert the passwords.
## You have to run one SQL query before proceeding.
## The altered files have been included, but they're
## not guaranteed to be updated to the latest FluxBB.
## The PasswordHash class is taken from:
## http://www.openwall.com/phpass/
##
## DISCLAIMER: Please note that "mods" are not officially supported by
## FluxBB. Installation of this modification is done at your
## own risk. Backup your forum database and any and all
## applicable files before proceeding.
##
##
#
#---------[ 1. RUN SQL STATEMENT ]--------------------------------------------
#
ALTER TABLE users ALTER COLUMN password varchar(60);
#
#---------[ 2. UPLOAD ]-------------------------------------------------------
#
root/include/PasswordHash.php to /include
#
#---------[ 3. OPEN ]---------------------------------------------------------
#
/include/functions.php
#
#---------[ 4. FIND ]---------------------------------------------------------
#
// Check if there's a user matching $user and $password
$result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE '.(is_int($user) ? 'u.id='.intval($user) : 'u.username=\''.$db->escape($user).'\'')) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
$pun_user = $db->fetch_assoc($result);
if (!isset($pun_user['id']) ||
($password_is_hash && $password != $pun_user['password']) ||
(!$password_is_hash && pun_hash($password) != $pun_user['password']))
set_default_user();
else
$pun_user['is_guest'] = false;
#
#---------[ 5. REPLACE ]------------------------------------------------------
#
// Check if there's a user matching $user and $password
$result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE '.(is_int($user) ? 'u.id='.intval($user) : 'u.username=\''.$db->escape($user).'\'')) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
$pun_user = $db->fetch_assoc($result);
if (!isset($pun_user['id']) ||
($password_is_hash && $password != $pun_user['password']) ||
(!$password_is_hash && !phpass_check($password, $pun_user['password'])))
set_default_user();
else
$pun_user['is_guest'] = false;
#
#---------[ 6. FIND ]---------------------------------------------------------
#
//
// Compute a hash of $str
//
function pun_hash($str)
{
return sha1($str);
}
#
#---------[ 7. AFTER, ADD ]---------------------------------------------------
#
//
// Compute PHPass password hashes. pun_hash() is used for many other things.
//
function phpass_hash($password)
{
if (strlen($password) > 72) { die("Password is longer than 72 characters"); }
if(!class_exists("PasswordHash"))
require "PasswordHash.php";
$hasher = new PasswordHash(8, false);
$hash = $hasher->HashPassword($password);
if (strlen($hash) < 20) { die("Password hashing failed"); }
unset($hasher);
return $hash;
}
//
// Check passwords against PHPass stored hashes
// returns true if the password matches with the stored hash
// returns false if the password is too long or doesn't match
//
function phpass_check($password, $storedHash)
{
if (strlen($password) > 72) return false;
if(!class_exists("PasswordHash"))
require "PasswordHash.php";
$hasher = new PasswordHash(8, false);
$check = $hasher->CheckPassword($password, $storedHash);
unset($hasher);
return $check;
}
#
#---------[ 8. OPEN ]---------------------------------------------------------
#
/install.php
#
#---------[ 9. FIND ]---------------------------------------------------------
#
'username' => array(
'datatype' => 'VARCHAR(200)',
'allow_null' => false,
'default' => '\'\''
),
'password' => array(
'datatype' => 'VARCHAR(40)',
'allow_null' => false,
'default' => '\'\''
),
#
#---------[ 10. REPLACE ]-----------------------------------------------------
#
'username' => array(
'datatype' => 'VARCHAR(200)',
'allow_null' => false,
'default' => '\'\''
),
'password' => array(
'datatype' => 'VARCHAR(60)',
'allow_null' => false,
'default' => '\'\''
),
#
#---------[ 11. FIND ]--------------------------------------------------------
#
$db->query('INSERT INTO '.$db_prefix.'users (group_id, username, password, email, language, style, num_posts, last_post, registered, registration_ip, last_visit) VALUES(1, \''.$db->escape($username).'\', \''.pun_hash($password1).'\', \''.$email.'\', \''.$db->escape($default_lang).'\', \''.$db->escape($default_style).'\', 1, '.$now.', '.$now.', \''.$db->escape(get_remote_address()).'\', '.$now.')')
or error('Unable to add administrator user. Please check your configuration and try again', __FILE__, __LINE__, $db->error());
#
#---------[ 12. REPLACE ]-----------------------------------------------------
#
$db->query('INSERT INTO '.$db_prefix.'users (group_id, username, password, email, language, style, num_posts, last_post, registered, registration_ip, last_visit) VALUES(1, \''.$db->escape($username).'\', \''.phpass_hash($password1).'\', \''.$email.'\', \''.$db->escape($default_lang).'\', \''.$db->escape($default_style).'\', 1, '.$now.', '.$now.', \''.$db->escape(get_remote_address()).'\', '.$now.')')
or error('Unable to add administrator user. Please check your configuration and try again', __FILE__, __LINE__, $db->error());
#
#---------[ 13. OPEN ]--------------------------------------------------------
#
/login.php
#
#---------[ 14. FIND ]--------------------------------------------------------
#
$cur_user = $db->fetch_assoc($result);
$authorized = false;
if (!empty($cur_user['password']))
{
$form_password_hash = pun_hash($form_password); // Will result in a SHA-1 hash
// If there is a salt in the database we have upgraded from 1.3-legacy though haven't yet logged in
if (!empty($cur_user['salt']))
{
if (sha1($cur_user['salt'].sha1($form_password)) == $cur_user['password']) // 1.3 used sha1(salt.sha1(pass))
{
$authorized = true;
$db->query('UPDATE '.$db->prefix.'users SET password=\''.$form_password_hash.'\', salt=NULL WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error());
}
}
// If the length isn't 40 then the password isn't using sha1, so it must be md5 from 1.2
else if (strlen($cur_user['password']) != 40)
{
if (md5($form_password) == $cur_user['password'])
{
$authorized = true;
$db->query('UPDATE '.$db->prefix.'users SET password=\''.$form_password_hash.'\' WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error());
}
}
// Otherwise we should have a normal sha1 password
else
$authorized = ($cur_user['password'] == $form_password_hash);
}
if (!$authorized)
message($lang_login['Wrong user/pass'].' <a href="login.php?action=forget">'.$lang_login['Forgotten pass'].'</a>');
// Update the status if this is the first time the user logged in
#
#---------[ 15. REPLACE ]-----------------------------------------------------
#
$cur_user = $db->fetch_assoc($result);
$authorized = false;
if (!empty($cur_user['password']))
{
// Try with PHPass first.
$authorized = phpass_check($form_password, $cur_user['password']);
if(!$authorized)
{
// Old FluxBB passwords that will be updated to PHPass.
// If there is a salt in the database we have upgraded from 1.3-legacy though haven't yet logged in
if (!empty($cur_user['salt']))
{
if (sha1($cur_user['salt'].sha1($form_password)) == $cur_user['password']) // 1.3 used sha1(salt.sha1(pass))
{
$authorized = true;
// Compute the new hash using the provided password
$new_password_hash = phpass_hash($form_password);
// Update password with PHPass
$db->query('UPDATE '.$db->prefix.'users SET password=\''.$new_password_hash.'\', salt=NULL WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error());
}
}
// If the length isn't 40 then the password isn't using sha1, so it must be md5 from FluxBB 1.2
else if (strlen($cur_user['password']) != 40)
{
if (md5($form_password) == $cur_user['password'])
{
$authorized = true;
// Compute the new hash using the provided password
$new_password_hash = phpass_hash($form_password);
// Update password with PHPass
$db->query('UPDATE '.$db->prefix.'users SET password=\''.$new_password_hash.'\' WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error());
}
}
// Otherwise we should have a normal sha1 password (FluxBB 1.5.x)
else if (strlen($cur_user['password'] == 40)
{
$form_password_hash = pun_hash($form_password); // Will result in a SHA-1 hash
if ($cur_user['password'] == $form_password_hash)
{
$authorized = true;
// Compute the new hash using the provided password
$new_password_hash = phpass_hash($form_password);
// Update password with PHPass
$db->query('UPDATE '.$db->prefix.'users SET password=\''.$new_password_hash.'\' WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error());
}
}
// If we end up here, nothing can be done.
}
}
if (!$authorized)
message($lang_login['Wrong user/pass'].' <a href="login.php?action=forget">'.$lang_login['Forgotten pass'].'</a>');
// Update the status if this is the first time the user logged in
#
#---------[ 16. FIND ]--------------------------------------------------------
#
// Remove this user's guest entry from the online list
$db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape(get_remote_address()).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
$expire = ($save_pass == '1') ? time() + 1209600 : time() + $pun_config['o_timeout_visit'];
pun_setcookie($cur_user['id'], $form_password_hash, $expire);
// Reset tracked topics
set_tracked_topics(null);
redirect(pun_htmlspecialchars($_POST['redirect_url']), $lang_login['Login redirect']);
#
#---------[ 17. REPLACE ]-----------------------------------------------------
#
// Remove this user's guest entry from the online list
$db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape(get_remote_address()).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
$expire = ($save_pass == '1') ? time() + 1209600 : time() + $pun_config['o_timeout_visit'];
pun_setcookie($cur_user['id'], $cur_user['password'], $expire);
// Reset tracked topics
set_tracked_topics(null);
redirect(pun_htmlspecialchars($_POST['redirect_url']), $lang_login['Login redirect']);
#
#---------[ 18. FIND ]--------------------------------------------------------
#
// Generate a new password and a new password activation code
$new_password = random_pass(8);
$new_password_key = random_pass(8);
$db->query('UPDATE '.$db->prefix.'users SET activate_string=\''.pun_hash($new_password).'\', activate_key=\''.$new_password_key.'\', last_email_sent = '.time().' WHERE id='.$cur_hit['id']) or error('Unable to update activation data', __FILE__, __LINE__, $db->error());
// Do the user specific replacements to the template
#
#---------[ 19. REPLACE ]-----------------------------------------------------
#
// Generate a new password and a new password activation code
$new_password = random_pass(8);
$new_password_key = random_pass(8);
$db->query('UPDATE '.$db->prefix.'users SET activate_string=\''.phpass_hash($new_password).'\', activate_key=\''.$new_password_key.'\', last_email_sent = '.time().' WHERE id='.$cur_hit['id']) or error('Unable to update activation data', __FILE__, __LINE__, $db->error());
#
#---------[ 20. OPEN ]--------------------------------------------------------
#
/profile.php
#
#---------[ 21. FIND ]--------------------------------------------------------
#
$authorized = false;
if (!empty($cur_user['password']))
{
$old_password_hash = pun_hash($old_password);
if ($cur_user['password'] == $old_password_hash || $pun_user['is_admmod'])
$authorized = true;
}
if (!$authorized)
message($lang_profile['Wrong pass']);
$new_password_hash = pun_hash($new_password1);
#
#---------[ 22. REPLACE ]-----------------------------------------------------
#
$authorized = false;
if (!empty($cur_user['password']))
{
if (phpass_check($old_password, $cur_user['password']) || $pun_user['is_admmod'])
$authorized = true;
}
if (!$authorized)
message($lang_profile['Wrong pass']);
$new_password_hash = phpass_hash($new_password1);
#
#---------[ 23. FIND ]--------------------------------------------------------
#
else if (isset($_POST['form_sent']))
{
if (pun_hash($_POST['req_password']) !== $pun_user['password'])
message($lang_profile['Wrong pass']);
// Make sure they got here from the site
confirm_referrer('profile.php');
#
#---------[ 24. REPLACE ]-----------------------------------------------------
#
else if (isset($_POST['form_sent']))
{
if (!phpass_check($_POST['req_password'], $pun_user['password']))
message($lang_profile['Wrong pass']);
// Make sure they got here from the site
confirm_referrer('profile.php');
#
#---------[ 25. OPEN ]--------------------------------------------------------
#
/register.php
#
#---------[ 26. FIND ]--------------------------------------------------------
#
$password_hash = pun_hash($password1);
#
#---------[ 27. REPLACE ]-----------------------------------------------------
#
$password_hash = phpass_hash($password1);
#
#---------[ 28. SAVE/UPLOAD ]-------------------------------------------------
#
Punirne cento per educarne uno.
Offline
I found a glitch in the SQL statement. MySQL expects:
ALTER TABLE users MODIFY password varchar(60);
Punirne cento per educarne uno.
Offline
Pages: 1