3

I've created a tidy system to salt and hash users passwords, send them a email to prompt reset if they forget them.

I am able to hash the $_POST on the fly and salt it with the users unique salt stored in their row, and match it with the stored hashed password and sign them in. When they reset their password and try to sign back in, the $_POST they enter does not match the stored pw. It is the exact same process.

Any idea why this may be?

Here is the pertinent part of the script:

$query =  "SELECT `encrypted_password`,`salt` FROM `Users` WHERE `Email` = '" . stripslashes(mysql_real_escape_string($_POST['email'])) . "'";
    $request = mysql_query($query,$connection) or die(mysql_error());
    $result = mysql_fetch_array($request);


    $salty_password = sha1($result['salt'] . stripslashes(mysql_real_escape_string($_POST['password'])));

    // SEE HOW THEY COMPARE
    echo "Users real salted pass: " . $result['encrypted_password'] . " / Salty Password to check: " . $salty_password . "<br />";

    $query2 = "SELECT * FROM `Users` WHERE `Email` = '". stripslashes(mysql_real_escape_string($_POST['email'])."' AND `encrypted_password` = '$salty_password'";
    $request2 = mysql_query($query2,$connection) or die(mysql_error());
    $result = mysql_fetch_array($request2);

--edit---

it may help to see how the password is being reset?

$query = "SELECT * FROM `Password_Reset` ORDER BY `id` DESC LIMIT 1";
$request = mysql_query($query,$connection) or die(mysql_error());
$result = mysql_fetch_array($request);

$token = $result['token'];

$alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz1234567890";
$rand = str_shuffle($alpha);
$salt = substr($rand,0,40);
$hashed_password = sha1($salt . stripslashes(mysql_real_escape_string($_POST['Password'])));
$user_email = $result['email'];

    if(isset($_POST['sub_settings'])){


        if(empty($_POST['Password'])) {
            $valid = false;
            $error_msgs[] = 'Whoops! You must enter a password.';
        }

        if($_POST['Password'] != $_POST['passwordConfirm'] || empty($_POST['Password'])) {
            $valid = false;
            $error_msgs[] = "Your password entries didn't match...was there a typo?";
        }

        if($valid) {
            $query = "UPDATE `Users` SET `encrypted_password` = '$hashed_password' WHERE `Email` = '$user_email'";

            mysql_query($query,$connection);
LightningWrist
  • 937
  • 4
  • 20
  • 37
  • 7
    Probably because they are doing injection attacks on your **completely unfiltered queries**. But hey, that's just a guess. – Josh K Feb 08 '11 at 17:49
  • 1
    AND `encrypted_password` = '$salty_password'"; here you have error... should be AND `encrypted_password` = '".$salty_password."'"; on that way how it is now it looks if `encrypted_password` is '$salty_password' string! – FeRtoll Feb 08 '11 at 17:50
  • 1
    Read [this](http://stackoverflow.com/questions/157998/whats-the-difference-between-sha-and-md5-in-php/818572#818572), and then [this](http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html), and then switch to using `bcrypt` instead of hashing algorithms. – eykanal Feb 08 '11 at 17:51
  • @JoshK - as opposed to just pointing out what I am doing wrong, do you have a solution? After all this is why I am posting this here; because I am new at this, trying to learn, and seeking help from experienced people as yourself. – LightningWrist Feb 08 '11 at 17:55
  • and "they" must mean "me" because this is not live yet. – LightningWrist Feb 08 '11 at 17:57
  • 1
    @eykanal: Much more important than what hash he is using is the fact that he needs to Needs To **NEEDS TO** [sanitize his input](http://php.net/manual/en/pdo.prepared-statements.php)... ([See also](http://stackoverflow.com/questions/129677)) – BlueRaja - Danny Pflughoeft Feb 08 '11 at 17:58
  • precautions taken. aka edited – LightningWrist Feb 08 '11 at 18:05
  • 3
    @LightningWrist: How do you expect to learn if nobody tells you what you are doing wrong? Conversely if someone tells you about huge mistakes you're making and you reject that advice, you won't learn. Sanitize your input. In the process you'll fix the bug that @FeRtoll pointed out, and your code will probably work. – btilly Feb 08 '11 at 18:09
  • @LightningWrist: I do not see an edit suggesting that you've taken the precautions indicated. Oversight on your part? – btilly Feb 08 '11 at 18:11
  • I added the mysql_real_escape_string to the user generated inputs – LightningWrist Feb 08 '11 at 18:13
  • 3
    @lightningwrist - sanitizing inputs does not just mean adding `mysql_real_escape`. It means checking that the content of the variables is what you expect it to be; i.e., that the `$_POST['email']` variable doesn't contain a `DROP DATABASE` statement. See [this](http://bobby-tables.com/) for a better explanation. – eykanal Feb 08 '11 at 18:14
  • @eykanal: Forget `bcrypt` and just use a SHA. The people who complain about the time it takes to generate a hash are inconsequential. I can spin up more EC2 instances if it takes longer. – Josh K Feb 08 '11 at 18:20
  • @everyone - I am doing the research now to properly sanitize user input. I will edit and fix once I feel like I have it right.Thanks! – LightningWrist Feb 08 '11 at 18:22
  • Now that a new issue has been detected and measures to fix it are being initiated, does anyone have an answer/idea of problem to my original question? thanks – LightningWrist Feb 08 '11 at 19:19
  • Actually, `mysql_real_escape_string` is sufficient here. But it must be the last thing done to the input before it's inserted into the SQL. `stripslashes` might undo some of the sanitization. – aaz Feb 08 '11 at 19:24

1 Answers1

2

It looks like you generate a random new salt when the password is reset, but don't store it in the database. The password check then uses the previous salt.


Also, it's not necessary to sanitize the password before feeding it into sha1. In fact, using stripslashes and mysql_real_escape_string there might lead to problems because both functions could transform a password differently depending on PHP version and configuration, giving a different hash.

aaz
  • 5,136
  • 22
  • 18
  • 1
    An easy mistake to make. Careful with the escaping too: `stripslashes` is not necessary anywhere while `mysql_real_escape_string` is only needed when constructing SQL queries. – aaz Feb 08 '11 at 20:00