09 New & Safer Password Recovery Question & Secret Answer

Started by Mindless, July 21, 2012, 08:37:28 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Mindless

#1
Credits to Neptune.
Updated for 09.
Xhtml Valid

Basically this mod is handy to reset password without mail involvement.

Code (sql) Select
ALTER TABLE `users` ADD  `passhint` int(10) unsigned NOT NULL, ADD  `hintanswer` varchar(40) NOT NULL default '';

/**
* @file signup.php
* Replace this section
*/

         
Code (php) Select
<tr>
          <td class='rowhead'>{$lang['captcha_pin']}</td>
          <td>
          <input type='text' maxlength='6' name='captcha' id='captcha' onblur='check(); return false;'/>
          </td>
          </tr>


/**
* with this
*/

     
Code (php) Select
      <tr>
          <td class='rowhead'>{$lang['captcha_pin']}</td>
          <td>
            <input type='text' maxlength='6' name='captcha' id='captcha' onblur='check(); return false;'/>
          </td>
      </tr>";
      //==Passhint
     $passhint="";
     $questions = array(
    array("id"=> "1", "question"=> "{$lang['signup_q1']}"),
array("id"=> "2", "question"=> "{$lang['signup_q2']}"),
array("id"=> "3", "question"=> "{$lang['signup_q3']}"),
array("id"=> "4", "question"=> "{$lang['signup_q4']}"),
array("id"=> "5", "question"=> "{$lang['signup_q5']}"),
array("id"=> "6", "question"=> "{$lang['signup_q6']}"));
  foreach($questions as $sph){ 
  $passhint .= "<option value='".$sph['id']."'>".$sph['question']."</option>\n";
  }
  $HTMLOUT .= "<tr><td align='right' class='heading'>{$lang['signup_select']}</td><td align='left'><select name='passhint'>\n$passhint\n</select></td></tr>
  <tr><td align='right' class='heading'>{$lang['signup_enter']}</td><td align='left'><input type='text' size='40'  name='hintanswer' /><br /><font class='small'>{$lang['signup_this_answer']}<br />{$lang['signup_this_answer1']}</font></td></tr>

   
/**
* @file lang/en/lang_signup.php add
*
*/

Code (php) Select
'signup_q1' => 'Mother\'s birthplace',
'signup_q2' => 'Best childhood friend',
'signup_q3' => 'Name of first pet',
'signup_q4' => 'Favorite teacher',
'signup_q5' => 'Favorite historical person',
'signup_q6' => 'Grandfather\'s occupation',
'signup_select' => 'Select Hint Question',
'signup_enter' => 'Enter hint answer',
'signup_this_answer' => 'This answer will be used to reset your password in case you forget it.',
'signup_this_answer1' => 'Make sure its something you wont forget!'
,

            
/**
* @file takesignup.php
* Replace this
*/

   
Code (php) Select
foreach( array('wantusername','wantpassword','passagain','email','captcha') as $x )
    {
      if( !isset($_POST[ $x ]) )
      {
        stderr($lang['takesignup_user_error'], $lang['takesignup_form_data']);
      }
     
      ${$x} = $_POST[ $x ];
    }




/**
* with this
*/

   
Code (php) Select
foreach( array('wantusername','wantpassword','passagain','email','captcha','passhint','hintanswer') as $x )
    {
      if( !isset($_POST[ $x ]) )
      {
        stderr($lang['takesignup_user_error'], $lang['takesignup_form_data']);
      }
     
      ${$x} = $_POST[ $x ];
    }


/**
* change this
*/

Code (php) Select
if (empty($wantusername) || empty($wantpassword) || empty($email))
stderr($lang['takesignup_user_error'], $lang['takesignup_blank']);


/**
* to this
*/

Code (php) Select
if (empty($wantusername) || empty($wantpassword) || empty($email) || empty($passhint) || empty($hintanswer))
stderr($lang['takesignup_user_error'], $lang['takesignup_blank']);


/**
* now, find this
*/

Code (php) Select
$editsecret = (!$arr[0]?"":mksecret());



/**
* below, add
*/

Code (php) Select
$wanthintanswer = md5($hintanswer);



/**
* in the query, after editsecret, add passhint, hintanswer,
* and after $editsecret, add $passhint, $wanthintanswer,
* So, the query should end up looking like this or similiar depending what you have on your own code :
*/

Code (php) Select
$ret = sql_query("INSERT INTO users (username, passhash, secret, editsecret, passhint, hintanswer, email, status, ". (!$arr[0]?"class, ":"") ."added, time_offset, dst_in_use) VALUES (" .
implode(",", array_map("sqlesc", array($wantusername, $wantpasshash, $secret, $editsecret, $passhint, $wanthintanswer, $email, (!$arr[0]?'confirmed':'confirmed')))).
", ". (!$arr[0]?UC_SYSOP.", ":""). "". time() ." , $time_offset, {$dst_in_use['tm_isdst']})");


/**
* @file my.php
* where you want it to show, add
*/

Code (php) Select
$secretqs = "<option value='0'>{$lang['my_none_select']}</option>\n";
  $questions = array(
  array("id"=> "1", "question"=> "{$lang['my_q1']}"),
  array("id"=> "2", "question"=> "{$lang['my_q2']}"),
  array("id"=> "3", "question"=> "{$lang['my_q3']}"),
  array("id"=> "4", "question"=> "{$lang['my_q4']}"),
  array("id"=> "5", "question"=> "{$lang['my_q5']}"),
  array("id"=> "6", "question"=> "{$lang['my_q6']}")
  );
 
  foreach($questions as $sctq){ 
  $secretqs .= "<option value='".$sctq['id']."'" .  ($CURUSER["passhint"] == $sctq['id'] ? " selected='selected'" : "") .  ">".$sctq['question']."</option>\n";
  }
 
  $HTMLOUT .= tr($lang['my_question'], "<select name='changeq'>\n$secretqs\n</select>",1);
  $HTMLOUT .= tr($lang['my_sec_answer'], "<input type='text' name='secretanswer' size='40' />", 1);


/**
* @file lang/en/lang_my.php add
*
*/

Code (php) Select
'my_none_select' => '---- None selected ----',
'my_q1' => 'Mother\'s birthplace',
'my_q2' => 'Best childhood friend',
'my_q3' => 'Name of first pet',
'my_q4' => 'Favorite teacher',
'my_q5' => 'Favorite historical person',
'my_q6' => 'Grandfather\'s occupation',
'my_question' => 'Question',
'my_sec_answer' => 'Secret answer',


/**
* @file takeproedit.php
* replace this
*/

Code (php) Select
if (!mkglobal("email:chpassword:passagain:chmailpass"))
      bark($lang['takeprofedit_no_data']);



/**
* with this
*/

Code (php) Select
if (!mkglobal("email:chpassword:passagain:chmailpass:secretanswer"))
bark($lang['takeprofedit_no_data']);



/**
* above this
*/

Code (php) Select
if ($email != $CURUSER["email"]) {
  if (!validemail($email))
  bark("That doesn't look like a valid email address.");
$r = mysql_query("SELECT id FROM users WHERE email=" . sqlesc($email)) or sqlerr();
  if (mysql_num_rows($r) > 0)
  bark("The e-mail address $email is already in use.");
  $changedemail = 1;
  }




/**
* add
*/

Code (php) Select
if ($secretanswer != '') {
  if (strlen($secretanswer) > 40) bark("Sorry, secret answer is too long (max is 40 chars)");
  if (strlen($secretanswer) < 6) bark("Sorry, secret answer is too sort (min is 6 chars)");
 
  $new_secret_answer = md5($secretanswer);
  $updateset[] = "hintanswer = " . sqlesc($new_secret_answer);
  }




/**
* after this
*/

Code (php) Select
if(isset($_POST["postsperpage"])  && (($postspp = min(100, 0 + $_POST["postsperpage"])) !=  $CURUSER["postsperpage"]))
$updateset[] = "postsperpage = $postspp";




/**
*        add
*/

Code (php) Select
if(isset($_POST["changeq"])  && (($changeq = (int)$_POST["changeq"]) !=  $CURUSER["passhint"]) && is_valid_id($changeq))
  $updateset[] = "passhint = " . sqlesc($changeq);



/**
*  Save and upload resetpw.php to root and add a link to login.php :)
*/


Code (php) Select
<?php
/*
+------------------------------------------------
|   $Date$
|   $Revision$ 09 Final
|   $password hint and answer
|   $Author$ Neptune,Bigjoos
|   $URL$
+------------------------------------------------
*/
require_once "include/bittorrent.php";
//require_once "include/password_functions.php";   //==Uncomment if req.
require_once "include/password_functions.php";
ini_set('session.use_trans_sid''0');
dbconn();
session_start();
$lang array_mergeload_language('global'), load_language('passhint') );

$HTMLOUT '';

global 
$CURUSER;

if (
$CURUSER
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error1']}");

$step = (isset($_GET["step"]) ? (int)$_GET["step"] : (isset($_POST["step"]) ? (int)$_POST["step"] : ''));

if (
$step == '1') {

if (
$_SERVER["REQUEST_METHOD"] == "POST") {

if (!
mkglobal("email:captcha")) 
die();

if(empty(
$captcha) || $_SESSION['captcha_id'] != strtoupper($captcha)){ 
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error2']}"); 
}

if (empty(
$email)) 
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_invalidemail']}");

if (!
validemail($email)) 
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_invalidemail1']}");

$check mysql_query('SELECT id, status, passhint, hintanswer FROM users WHERE email = ' sqlesc($email)) or sqlerr(__FILE__,__LINE__); 
$assoc mysql_fetch_assoc($check) or stderr("{$lang['stderr_errorhead']}""{$lang['stderr_notfound']}"); 

if (empty(
$assoc['passhint']) || empty($assoc['hintanswer'])) 

stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error3']}"); 

if (
$assoc['status'] != 'confirmed'

stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error4']}"); 
}else { 
$HTMLOUT .= "<form method='post' action='".$_SERVER['PHP_SELF']."?step=2'>
<table border='1' cellspacing='0' cellpadding='10'>
<tr>
<td class='rowhead'>
{$lang['main_question']}</td>";

$id[1] = '/1/';
$id[2] = '/2/';
$id[3] = '/3/';
$id[4] = '/4/';
$id[5] = '/5/';
$id[6] = '/6/';
$question[1] = "{$lang['main_question1']}";
$question[2] = "{$lang['main_question2']}";
$question[3] = "{$lang['main_question3']}";
$question[4] = "{$lang['main_question4']}";
$question[5] = "{$lang['main_question5']}";
$question[6] = "{$lang['main_question6']}";
$passhint preg_replace($id$question, (int)$assoc['passhint']);
$HTMLOUT .= "<td><i><b>{$passhint} ?</b></i>
<input type='hidden' name='id' value='"
.(int)$assoc['id']."' /></td></tr>
<tr><td class='rowhead'>
{$lang['main_sec_answer']}</td>
<td><input type='text' size='40' name='answer' /></td></tr><tr><td colspan='2' align='center'><input type='submit' value='
{$lang['main_next']}' class='btn' />
</td></tr></table></form>"
;
print 
stdhead('Reset Lost Password'). $HTMLOUT stdfoot();


}

elseif (
$step == '2') {
if (!
mkglobal('id:answer')) die();

$select mysql_query('SELECT id, username, hintanswer FROM users WHERE id = ' sqlesc($id)) or sqlerr(__FILE____LINE__); 
$fetch mysql_fetch_assoc($select);

if (!
$fetch
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error5']}");

if (empty(
$answer)) 
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error6']}");

if (
$fetch['hintanswer'] != md5($answer)) { 

$ip getip();
$useragent $_SERVER['HTTP_USER_AGENT'];

$msg "".htmlspecialchars($fetch['username']).", on ".get_datetime(), ''1,) . ", {$lang['main_message']}"."\n\n{$lang['main_message1']} " $ip " (". @gethostbyaddr($ip) . ")""\n {$lang['main_message2']} ".$useragent."\n\n {$lang['main_message3']}\n {$lang['main_message4']}\n";
$subject ="Failed password reset";
mysql_query('INSERT INTO messages (receiver, msg, subject, added) VALUES (' .
      sqlesc((int)$fetch['id']) . ', ' sqlesc($msg) . ', ' sqlesc($subject) . ', ' sqlesc(time()) . ')') or sqlerr(__FILE____LINE__);

stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error7']}"); 
}else { 
$HTMLOUT .= "<form method='post' action='?step=3'>
<table border='1' cellspacing='0' cellpadding='10'>
<tr><td class='rowhead'>
{$lang['main_new_pass']}</td>
<td><input type='password' size='40' name='newpass' /></td></tr>
<tr><td class='rowhead'>
{$lang['main_new_pass_confirm']}</td><td><input type='password' size='40' name='newpassagain' /></td></tr>
<tr><td colspan='2' align='center'><input type='submit' value='
{$lang['main_changeit']}' class='btn' />
<input type='hidden' name='id' value='"
.(int)$fetch['id']."' /></td></tr></table></form>";
print 
stdhead('Reset Lost Password'). $HTMLOUT stdfoot(); 



elseif (
$step == '3') {
if (!
mkglobal('id:newpass:newpassagain')) die();

$select mysql_query('SELECT id, editsecret FROM users WHERE id = ' sqlesc($id)) or sqlerr(__FILE____LINE__); 
$fetch mysql_fetch_assoc($select) or stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error8']}");

if (empty(
$newpass)) 
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error9']}"); 
if (
$newpass != $newpassagain
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error10']}"); 
if (
strlen($newpass) < 6
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error11']}"); 
if (
strlen($newpass) > 40
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error12']}");

$secret mksecret();
$newpassword =  make_passhash$secretmd5($newpass) ) ;

mysql_query('UPDATE users SET secret = ' sqlesc($secret) . ', editsecret = "", passhash=' sqlesc($newpassword) . ' WHERE id = ' sqlesc($id) . ' AND editsecret = ' sqlesc($fetch["editsecret"]));

if (!
mysql_affected_rows()) 
stderr("{$lang['stderr_errorhead']}""{$lang['stderr_error13']}");
else 
stderr("{$lang['stderr_successhead']}","{$lang['stderr_error14']} <a href='{$TBDEV['baseurl']}/login.php' class='altlink'><b>{$lang['stderr_error15']}</b></a> {$lang['stderr_error16']}"FALSE); 
}else {

if (isset(
$_SESSION['captcha_time']))
    (
time() - $_SESSION['captcha_time'] < 10) ? exit($lang['captcha_spam']) : NULL;

$HTMLOUT .= "<script type='text/javascript' src='./scripts/captcha.js'></script>
<p>
{$lang['main_body']}</p>
<br />
<form method='post' action='"
.$_SERVER['PHP_SELF']."?step=1'>
<table border='1' cellspacing='0' cellpadding='10'>
<tr>
<td class='rowhead'>
{$lang['main_email_add']}</td><td><input type='text' size='40' name='email' /></td></tr>
<tr><td class='rowhead'>
{$lang['main_captcha']}</td>
<td><div id='captchaimage'><a href='"
.$_SERVER['PHP_SELF']."' onclick='refreshimg(); return false;'><img class='cimage' src='./captcha/GD_Security_image.php?".time()."' border='0' alt='Click to refresh image' title='Click to refresh image' /></a></div></td></tr>
<tr><td class='rowhead'>
{$lang['main_pin']}</td><td>
<input type='text' maxlength='6' name='captcha' id='captcha' onblur='check(); return false;' /></td></tr>
<tr><td colspan='2' align='center'><input type='submit' value='
{$lang['main_recover']}' style='height: 25px' /></td></tr></table>
</form>"
;
print 
stdhead('Reset Lost Password'). $HTMLOUT stdfoot();
}
?>


/**
*  Save and upload lang_passhint.php to lang/en :)
*/

Code (php) Select
<?php

$lang 
= array(

#stderr
'stderr_errorhead' => "Error",
'stderr_error1' => "What the hell are you trying to do? You are already logged in!",
'stderr_error2' => "The characters you type must match the characters in the picture. Please try again.",
'stderr_error3' => "You cannot reset your password because you have not yet definied your question/secret answer!",
'stderr_error4' => "You cannot reset your password because your account has not been confirmed!",
'stderr_error5' => "This user wasnt found in the database!",
'stderr_error6' => "You must type your secret answer!",
'stderr_error7' => "Your secret answer must match the question you provided for your account. Please try again.",
'stderr_error8' => "This user was not found in the database!",
'stderr_error9' => "You must type your new password!",
'stderr_error10' => "The passwords didn't match! Please try again.",
'stderr_error11' => "Sorry, password is too short (min is 6 chars)",
'stderr_error12' => "Sorry, password is too long (max is 40 chars)",
'stderr_error13' => "Unable to update user data. Please contact an administrator about this error.",
'stderr_successhead' => "Success",
'stderr_error14' => "Your password has been updated! Click",
'stderr_error15' => "Here",
'stderr_error16' => "to log in with your new password!",
'stderr_notfound' => "This email address was not found in the database.",
'stderr_invalidemail' => "You must enter your email address!",
'stderr_invalidemail1' => "That doesn't look like a valid email address!",
#captcha
'captcha_spam' => "NO SPAM! Wait 10 seconds and then refresh page",
#main
'main_question' => "Question",
'main_question1' => "Mother's birthplace",
'main_question2' => "Best childhood friend",
'main_question3' => "Name of first pet",
'main_question4' => "Favorite teacher",
'main_question5' => "Favorite historical person",
'main_question6' => "Grandfather's occupation",
'main_sec_answer' => "Secret Answer",
'main_next' => "Next",
'main_new_pass' => "New password",
'main_new_pass_confirm' => "Confirm password",
'main_message' => "somebody (probably you), tried to set a new password for this account by question & secret answer method but failed!",
'main_message1' => "Their IP Address was:",
'main_message2' => "Their user agent was:",
'main_message3' => "If this wasn't you please report this event to a member of staff!",
'main_message4' => "Thank you.",
'main_changeit' => "Change it!",
'main_body' => "Before you can reset your password, you need to type your email address and verify the captcha image !",
'main_email_add' => "E-Mail Address",
'main_captcha' => "Captcha",
'main_pin' => "Pin",
'main_recover' => "Recover");
?>