Jump to content

Recommended Posts

Hi,

 

I have a problem with a php script that I put together that uses mysql. Basically, it is a forgot password script that generates a new random password, emails it to a user then encrypts the password and stores it into the database so that the user may log in with it.

 

I set up a page called forgot.php with a form that asks the user to enter his/her email address. It uses the post method to run a few lines of php in a file called doreset.php.

 

When I run the script, nothing seems to happen yet I don't get any error messages. I can't seem to isolate the problem.

 

Here is the code for doreset.php:

<?php
//Start session
session_start();

//Include database connection details
require_once('config.php');

//Array to store validation errors
$errmsg_arr = array();

//Validation error flag
$errflag = false;

//Connect to mysql server
$link = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
if(!$link) {
	die('Failed to connect to server: ' . mysql_error());
}

//Select database
$db = mysql_select_db(DB_DATABASE);
if(!$db) {
	die("Unable to select database");
}

//Function to sanitize values received from the form. Prevents SQL injection
function clean($str) {
	$str = @trim($str);
	if(get_magic_quotes_gpc()) {
		$str = stripslashes($str);
	}
	return mysql_real_escape_string($str);
}

//Sanitize the POST values
$email = clean($_POST['email']);

$valmail = "^([_a-z0-9-]+)(\.[_a-z0-9-]+)*@([a-z0-9-]+)(\.[a-z0-9-]+)*(\.[a-z]{2,4})$";

//Input Validations
if (eregi($valmail, $email))
   	{
	if($email == '') {
		$errmsg_arr[] = 'Email address missing';
		$errflag = true;
	}	
} else {
	$errmsg_arr[] = 'Email address is not valid';
	$errflag = true;
}		
//Check to see if email is linked to an account
if($email != '') {
	$qry = "SELECT * FROM members WHERE email='$email'";
	$result = mysql_query($qry);
	if($result) {
		if(mysql_num_rows($result) < 1) {
			$errmsg_arr[] = 'Email address entered is not linked to an account';
			$errflag = true;
		}
		@mysql_free_result($result);
	}
	else {
		die("Query failed");
	}
}

//If there are input validations, redirect back to the registration form
if($errflag) {
	$_SESSION['ERRMSG_ARR'] = $errmsg_arr;
	session_write_close();
	header("location: forgot.php");
	exit();
}

//Get username linked to email so it can be emailed along with password
$qry = "SELECT username FROM members WHERE email='$email'";
	$username = mysql_query($qry);

function randomPassword ($length = 
{

  // start with a blank password
  $randpw = "";

  // define possible characters
  $charlist = "0123456789bcdfghjkmnpqrstvwxyz"; 
    
  // set up a counter
  $i = 0; 
    
  // add random characters to $randpw until $length is reached
  while ($i < $length) { 

    // pick a random character from the possible ones
    $char = substr($charlist, mt_rand(0, strlen($charlist)-1), 1);
        
    // we don't want this character if it's already in the password
    if (!strstr($randpw, $char)) { 
      $randpw .= $char;
      $i++;
    }

  }

  		// email the random password to the email address the user entered
	mail($email,"Account Login Details","Your username is $username and your new password is $randpw","From: noreply@jammontreal.com");
	// use md5 to encrypt the random password and store it in database
	$encpw = md5($randpw);
	$qry = "UPDATE members SET password ='$encpw' WHERE email ='$email'";
	$result = @mysql_query($qry);
	//Check whether the query was successful or not
	if($result) {
		header("location: sentpw.php");
		exit();
	} else {
		echo "Error. Please Contact Webmaster";
	}
}
?>

 

Can anyone see where I went wrong? (Probably in a few places, I'm not an expert with PHP)

When I run the script, nothing seems to happen yet I don't get any error messages. I can't seem to isolate the problem.

 

What do you mean nothing happens?  In this piece of code you have to do either two things, redirect to sentpw.php or echo, "Error.  Please Contact Webmaster".

 

 if($result) {
         header("location: sentpw.php");
         exit();
      } else {
         echo "Error. Please Contact Webmaster";
      }

 

Please turn on errors like gaza said:

 

ini_set ("display_errors", "1");
error_reporting(E_ALL);

 

I don't really see a problem with your code.  You should echo out your variables and queries to ensure that they have the correct values.  It may be something to do with the mail configuration.  Try emailing something to yourself.

 

 

Blank pages are either caused by parse errors, fatal runtime errors, or code that does not output anything.

 

For a parse error, putting the two lines in your code to set error_reporting to E_ALL and to set display_errors to ON won't help because the code is never executed. When learning php, developing php code, or debugging php code, these two settings should be turned on in php.ini

Before you go too far with this script, you might want to think about security issues regarding emailing users their passwords. In my opinion, you would be better off emailing the user a special link with a query string that is unique to them. This query string could contain the users current encrypted password concatenated with their user ID, and perhaps a salt. When the user follows the link in their email, you would simply evaluate the query string, and allow the user to create their own password. This is more secure for a number of reasons, and the user doesn't have to change their password to something they can remember after you create a new password for them that is hard to remember.

Before you go too far with this script, you might want to think about security issues regarding emailing users their passwords. In my opinion, you would be better off emailing the user a special link with a query string that is unique to them. This query string could contain the users current encrypted password concatenated with their user ID, and perhaps a salt. When the user follows the link in their email, you would simply evaluate the query string, and allow the user to create their own password. This is more secure for a number of reasons, and the user doesn't have to change their password to something they can remember after you create a new password for them that is hard to remember.

 

I had considered this option but decided to go with the random password scenario because I didn't know where to start with the query string method. You're absolutely right that I shouldn't compromise my members' security because I am too lazy to implement the hyperlink/query string method. So, can anybody link to some documentation to help me get started?

Ok I echo'd everything and got some errors:

 

SELECT * FROM members WHERE email='example@domain.com'SELECT username FROM members WHERE email='example@domain.com'

Notice: Undefined variable: encpw in /home/noel695/domains/noeljourneaux.com/public_html/login/doreset.php on line 125

UPDATE members SET password ='' WHERE email ='example@domain.com'

Notice: Undefined variable: randpw in /home/noel695/domains/noeljourneaux.com/public_html/login/doreset.php on line 126

Resource id #5

 

Basically, it's saying $randpw isn't defined and since $encpw depends entirely of $randpw, it also isn't defined. Looking back at the code I pasted originally, can someone show me where I failed to define $randpw?

It seems I had forgotten to define my variable outside of the randomPassword() function. The following was placed before the mail function:

$randpw = randomPassword();

 

I also had to completely overhaul the randomPassword() function because it didn't seem to be working. I used one I found online instead.

So, can anybody link to some documentation to help me get started?

 

I'm working on a script that is sort of specialized to my own login system, but I'll copy and paste the code here, and you can check it out as an example.

 

<?php
/*
This script allows a user to recover their username,
and reset their password if desired. A password
reset link is sent to the user via email, and if
followed, they have an opportunity to reset their 
password. The script is pretty complex, and could
probably use some refining, but it does work well.

        CODE BY R.B.Gottier - www.brianswebdesign.com
*/
require_once("../app_top.inc.php");
if(!isset($get_p) && !isset($post_change_p)){ // If the user has just come to this page, OR the email address has been submitted for username or password recovery
	$fail = 0;
	if (isset($post_submit)){ // If the email address has been submitted
		if ($post_email == FALSE || $post_email == NULL){
			$fail = 1;
		}
		if($fail != 1){ // If validation of the email variable was OK, check the database for the email address to see if there is a match, and return a user_id, hashed password, and firstname if available
		$clean_email = clean_for_query($post_email);
		$a = mysqli_query($db , "SELECT u.user_id,u.password,ua.firstname
								 FROM users AS u,user_accounts AS ua
								 WHERE u.user_id = ua.user_id
								 AND ua.email = '$clean_email' LIMIT 1");
		$numrows = mysqli_num_rows($a);
			if ($numrows == 0){ // If not match
				$fail = 1;
			}else{ // If there was a match then send an email to the user
				$row = mysqli_fetch_assoc($a);
				$password_half = str_split($row['password'] , 16);
				$reassembled_password = $password_half[1] . $password_half[0];
				$reassembled_password .= "{$row['user_id']}";
				$random_hash = md5(date('r', time()));
				$to = $clean_email;
				$subject = 'Your ' . SITE_NAME . ' account';
				$headers = "From: " . SITE_NAME . " <" . ADMIN_EMAIL . ">\r\nReply-To: " . ADMIN_EMAIL . "\r\nReturn-Path: " . ADMIN_EMAIL;
				$headers .= "\r\nContent-Type: multipart/alternative; boundary=\"PHP-alt-".$random_hash."\"";
				$plain_text_content = "Hi {$row['firstname']},\n\n\nCopy and paste the following link into your browser if you can't click on it:\n\n" . this_page() . "?p=$reassembled_password\n\nYou can then reset your password, and gain access to your " . SITE_NAME . " account.\n\nThank you,\n\n" . SITE_NAME;
				$html_content = "Hi {$row['firstname']},<br />Follow the link provided below:<br><a href='" . this_page() . "?p=$reassembled_password'>RESET</a>.<br>You can then reset your password, and gain access to your " . SITE_NAME . " account.<br>Thank you,<br>" . SITE_NAME;
//THIS MUST STAY PARKED OVER ON THE LEFT SIDE OF THE CODE *** DO NOT INDENT THIS TO KEEP THE CODE PRETTY OR IT WILL NOT WORK!
$message = "
--PHP-alt-$random_hash
Content-Type: text/plain; charset=\"iso-8859-1\"
Content-Transfer-Encoding: 7bit

$plain_text_content 

--PHP-alt-$random_hash
Content-Type: text/html; charset=\"iso-8859-1\"
Content-Transfer-Encoding: 7bit

$html_content

--PHP-alt-$random_hash--
";
// END MESSAGE BODY AREA
				// The following line of code is only for development purposes:
				echo $to . "<br>" . $subject . "<br>" . $message . "<br>" . $headers . "<br>";
				// Uncomment the following line in the production environment:
				//mail( $to, $subject, $message, $headers );
				echo "<h2>Email Sent</h2><p>We have emailed you at $clean_email! This email will provide instructions on how to log in to your account.</p><p>If you don't receive this email shortly, check your spam/bulk email folder, or repeat this process.</p>";
				mysqli_free_result($a);
			}
		}
	}
	if (!isset($post_submit) || $fail == 1){ //If the email address has not been submitted, or if the email address was not in the database
		if ($fail == 1){ // If the email address was not in the database
			echo '<h2 class="errorH2">Bad Email Address</h2>
			<div class="errorDiv">
				<p style="padding-bottom:0px;">Your email address was not in our system. Please review the address you tried, try again, or call us directly.</p>
			</div>';
		}
		// Display the form for either a user coming to the page for the first time, or if they didn't provide an email address that was in the database, prefill the email form field (prefill only works if the email address passed filtering)
		echo "<form action='" . this_page() . "' method='POST'>
				<h2>Forgot your login?</h2>
				<p>If your email address is in our database, we will send you information on how to reset your login.</p>
				<label for='email'>What is your email address?<label>
				<input id='email' name='email' type='text' maxlength='50'";
				echo (isset($post_email) && $post_email != '') ? " value='" . htmlentities($post_email) . "'>" : ">";
				echo "
				<input type='submit' name='submit' value='submit' />
			</form>";
	}
}else{ // The user has followed the link in their email OR has submitted a new password
	if(isset($post_new_p) && $post_new_p != NULL && isset($post_change_p) && $post_change_p != '' && $post_new_p == $post_new_p_conf){ // If the user has submitted a new password and the password and password confirmation fields match
		if( strlen( $post_new_p ) > MAX_PASSWORD_LENGTH || strlen( $post_new_p ) < MIN_PASSWORD_LENGTH ){ // If the newly submitted password is more than 12 characters, or less than 7, send the user back to the form to change it
			echo "<h2 class='errorH2'>Password is too long or too short.</h2>
				<div class='errorDiv'>
					<p style='padding-bottom:0px;'>Your password must be between " . MIN_PASSWORD_LENGTH . " and " . MAX_PASSWORD_LENGTH . " characters in length.</p>
					<form action='" . this_page() . "' method='POST'>
						<label for='new_p'>Choose a new password (" . MIN_PASSWORD_LENGTH . " min / " . MAX_PASSWORD_LENGTH . " max)<label>
						<input id='new_p' name='new_p' type='text' />
						<label for='new_p_conf'>Confirm new password<label>
						<input id='new_p_conf' name='new_p_conf' type='text' />
						<input name='username' value='" . htmlentities($post_username) . "' type='hidden' />
						<input name='old_p' value='$get_p' type='hidden' />
						<input type='submit' name='change_p' value='submit' />
					</form>
				</div>";
		}else{ // The password is between MIN_PASSWORD_LENGTH and MAX_PASSWORD_LENGTH characters, and will be processed and updated in the database
			$password_half = str_split($post_old_p , 16);
			$reassembled_password = $password_half[1] . $password_half[0];
			$clean_old_p = clean_for_query($reassembled_password);
			$enc_password = clean_for_query(md5(PASSWORD_SALT . $post_new_p));
			if( strlen( $post_username ) > MAX_USERNAME_LENGTH ){ // At this point, a posted username that has more characters than MAX_USERNAME_LENGTH is an attack, since the value of $post_username comes from a hidden form field.
				die();
			}else{
				$clean_username = clean_for_query($post_username);
			}
			mysqli_query($db , "UPDATE `users` SET password='$enc_password' WHERE username='$clean_username' AND password='$clean_old_p'");
			echo "<h2>Password Reset Confirmation</h2>
					<p>Once again, your username is <b>" . htmlentities($post_username) . "</b>.
					<br />Your new password is <b>" . htmlentities($post_new_p). "</b>.
					<br />Please write them down and proceed to login.</p>
					<p><a href='$thisDomain'>Continue</a></p>";
		}
	}else{ // The user has either followed the link in the email, or the password and password confirmation fields DID NOT match
		if (
			(isset($post_new_p) && isset($post_new_p_conf) && $post_new_p != $post_new_p_conf )
			|| 
			(isset($post_new_p) && $post_new_p == '')
			||
			(isset($post_new_p_conf) && $post_new_p_conf == '')
			)
		{ // If the password and password confirmation fields didn't match, or if they were blank, an error message is shown
			echo "<p style='background-color:yellow;'>Password and confirmed password were not the same, or one or both were blank.</p>";
		}else{ // If the user has followed the link in their email
				echo "<p style='background-color:white;'> </p>";
		}
		$clean_get_p = clean_for_query($get_p);
		$password_half = str_split($clean_get_p , 16);
		$reassembled_password = $password_half[1] . $password_half[0];
		$users_number = clean_for_query($password_half[2]);
		$z = mysqli_query($db , "SELECT u.user_id,u.username,ua.firstname
								 FROM users AS u,user_accounts AS ua
								 WHERE u.user_id = '$users_number' AND ua.user_id = '$users_number'
								 AND password = '$reassembled_password' LIMIT 1");
		$zrows = mysqli_num_rows($z); // Checks to see if anything is in the db.
		if ($zrows != 1){ // If the user could not be determined
			die();
		}else{ // The user was determined by the get variable in the email link
			$row = mysqli_fetch_assoc($z);
			// The form is displayed so the user can reset their password
			echo "<p>Hi {$row['firstname']},<br><br>Your username is <b>{$row['username']}</b>. You will need this, so write it down.</p>
				<form action='" . this_page() . "' method='POST'>
					<label for='new_p'>Choose a new password (" . MIN_PASSWORD_LENGTH . " min / " . MAX_PASSWORD_LENGTH . " max)<label>
					<input id='new_p' name='new_p' type='text' maxlength='50' />
					<label for='new_p_conf'>Confirm new password<label>
					<input id='new_p_conf' name='new_p_conf' type='text' maxlength='50' />
					<input name='username' value='{$row['username']}' type='hidden' />
					<input name='old_p' value='$get_p' type='hidden' />
					<input type='submit' name='change_p' value='submit' />
				</form>";
			mysqli_free_result($z);
		}
	}
}
mysqli_close($db);
?>

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.