This topic is locked
[SOLVED]

 Stop password reuse

11/4/2014 9:16:30 PM
PHPRunner General questions
S
Stucco author

Hi,
Some time ago we discussed password rotation in another thread - http://www.asprunner.com/forums/topic/21878-password-rotation
I have now done some additional functionality to stop password reuse. This will stop the use of a password used within the past 365 days, based on the last used date. This technique is much better than a limit of 3 or 5 passwords before allowing reuse, because it allows the user to change their password as much as they like, but still not be able to cycle through the passwords to get back to their favorite.
Additional thoughts: I am using PHPRunner 7.1 Enterprise Edition and I do have password hashing/encryption enabled. If you do not have it enabled then you can still use this, just remove the md5() function calls.
First- I created a table to store password history, and populated it with existing user data.



CREATE TABLE IF NOT EXISTS `users_password_history` (

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,

`user_id` mediumint(8) unsigned NOT NULL,

`password` varchar(32) NOT NULL,

`first_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

`last_used` timestamp NOT NULL DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `userid_password_idx` (`user_id`,`password`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
INSERT INTO `users_password_history` (user_id, password) SELECT id, password FROM users;


The first_used isn't actually used for anything but I figure it may come in useful someday.
Second- I added the following to the Events - Change password page - Before change password



//Check the history table to ensure we want to allow this change. If any matches are found (return value is > 0) then return false, else return true.

$history_count = DBLookup("SELECT count(id) FROM users_password_history WHERE user_id = " . $_SESSION["user_id"] . " and password = \"" . md5($newpassword) . "\" and datediff(curdate(), last_used) <= 365");

if($history_count != 0) {

$_SESSION["password_reuse"] = "true";

}

return $history_count == 0;


Third- I added the following to the Events - Change password page - After password changed



global $conn;
//Update last_used in the password history table

$password_history_id = DBLookup("SELECT id FROM users_password_history WHERE user_id = " . $_SESSION["user_id"] . " and password = \"" . md5($oldpassword) . "\"");

if($password_history_id) {

$str = "UPDATE users_password_history SET last_used = NOW() WHERE id = " . $password_history_id;

db_query($str,$conn);

}
$str = "INSERT INTO users_password_history (user_id, password) VALUES(" . $_SESSION["user_id"] . ", \"" . md5($newpassword) . "\")";

db_query($str,$conn);


Fourth- I added the following to the Events - Change password page - Before display



//Set the custom message for password change failure due to reuse.

if(isset($_SESSION["password_reuse"])){

$msg .= "You are attempting to reuse a password too soon.<br /><br />";

unset($_SESSION["password_reuse"]);

}

$msg .= "Your new password must:<br />Have not been used in the past 365 days<br />Be at least 8 characters<br />Contain at least 4 unique characters<br />Contain at least 2 digits or symbols<br />Contain letters in both upper and lower case<br />";

$xt->assign("message", $msg);

$xt->assign("message_block",true);


Fifth- I added the following to the Events - admin_users - Add page - After record added



global $conn;
//Add the password history in for newly created users

$str = "INSERT INTO users_password_history (user_id, password) VALUES(" . $values["id"] . ", \"" . $values["password"] . "\")";

db_query($str,$conn);


I updated this based on posts below. Thanks for the help. Good luck!

Sergey Kornilov admin 11/4/2014

In BeforeDisplay event you have access to $xt variable. In "After password changed" event save your message to session variable and then display it in BeforeDisplay event.

S
Stucco author 11/5/2014

Thanks! I updated the original post accordingly.