1

Okay so I have this page which is supposed to allow a user to login with their password which is encrypted in the database with AES. I want to pull the encrypted password out of the DB, decrypt it and compare it to the password the user enters. Here's my code:

<?php
session_start();
$validUser = false;

// see if they want to logout from a current session

$tOption = $_GET['cmd'];

if($tOption=="logout") {
    unset($_SESSION['SAFEUSER']);
}

?>
<html>
<body>
<?php

// are they attempting to log into the menu?

// alternative syntax that uses the submit button's value
// if(   $_POST['Fsubmit'] == "lookupnow" ) {


if(   ($_POST['Femail'] > "") or ($_POST['Fpassword'] > "")  ) {
    // look 'em up in the database to validate credentials

    // establish values for DB credentials
    $hostname = 'localhost';
    $dbname = ''; 
    $username = '';
    $userpass = '';
    $passkey = "sgjbasjgbaslhflshfoashf";

    // get connected to the DB
    try {

      $DBH = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $userpass);

    }
    catch(PDOException $e) {
        echo $e->getMessage();
    }

    $tEmail = $_POST['Femail'];
    $tPassword = $_POST['Fpassword'];

    /*$secureSQL = 'SELECT FirstName, LastName, Phone from Members WHERE Email="' 
            . $tEmail . '" AND Password="' . $tPassword . '"';*/

    $secureSQL = 'SELECT FirstName, LastName, Phone from Members WHERE Email="' 
            . $tEmail . '" AND AES_DECRYPT(Password, $passkey) ="' . $tPassword . '"';

    //echo $secureSQL . "<br>";

    // estalish SQL query  
    $STH = $DBH->query($secureSQL);

    # setting the fetch mode -- this comes into effect when the fetch() function is called
    $STH->setFetchMode(PDO::FETCH_ASSOC);

    while($row = $STH->fetch()) {
        $validUser = true;
        $_SESSION['SAFEUSER'] = true;
    }
    if($validUser==false) {
        echo "<font color='red'>Those credentials were not authenticated.</font><br/><br/>";
    }


}

// are they logged in?

if(!$_SESSION['SAFEUSER']) {
    // if not, make them login
?>
    Please enter your credentials:<br />
    <form method="post" action="mysecuremenu.php">
        Your email address: <input type="text" name="Femail"><br>
        Your password: <input type="password" name="Fpassword"></br>
        <input type="submit" name="Fsubmit" value="lookupnow">
    </form>

<?php   
} else {
    // otherwise, show them the menu
?>
<h2>Please select one of the following:</h2>
<ul>
    <li><a href="MySecureFirstDBForm.php">Enter a new employee</a></li>
    <li><a href="mySecuredbviewall_withdatatable.php">View all employees</a></li>
    <li><a href="mysecuremenu.php?cmd=logout">Logout</a></li>
</ul>

<?php

} // end if(safeuser)

?>
</body>
</html>

I get this error:

Fatal error: Call to a member function setFetchMode() on a non-object on line 58

I feel like it has to have something to do with my SELECT statement because the one I have commented out above it works fine for logging in with non-encrypted passwords. I would appreciate any and all help. Thanks!

  • 2
    Don't use encryption to store passwords - use a hash. Store a hashed version of a password. When you have to check a user password hash the user input and compare it with the stored hash. PHP provides `password_hash()` for this very purpose. Adobe used an encryption method to store passwords and when their site was hacked millions of decrypted passwords found their way to the criminal domain. You have been warned. –  Feb 23 '15 at 22:23
  • If you are storing passwords you should _really_ consider [hashing them](http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords) instead of encrypting/decrypting. If you can't do this under the current setup, you should start looking for ways to port it to a hashing system. As for your error, `$STH` isn't the object you think it is. Make sure you are getting a result from your query (and that your query isn't failing.) – Crackertastic Feb 23 '15 at 22:24
  • Yeah I've been learning about all of this for the past few hours. It definitely seems like hashing is a better option, but unfortunately this was specifically asked to be done with AES. No sensitive information is going to be at risk or anything. – user3579547 Feb 23 '15 at 22:26
  • So when your client has his site hacked and his password is used to drain his bank account that's _'No sensitive information'_ is it? –  Feb 23 '15 at 22:28
  • I agree with you. Take it up with my professor. This is for an assignment. If I could do it differently I would. – user3579547 Feb 23 '15 at 22:30
  • [You're Probably Storing Passwords Incorrectly](http://blog.codinghorror.com/youre-probably-storing-passwords-incorrectly/) on Coding Horror comes to mind. In short: most users use the same password *everywhere*, so anyone building a website where users can log in with a password has a big responsibility to keep those safe. – roeland Feb 23 '15 at 22:36

1 Answers1

1

You have a syntax error in your query, but more on that later. You'd have found it if you'd checked your calls to PDO for errors. PDO doesn't flag errors explicitly unless you ask it to, so you need to check the return value of your call to $DBH->query(...)

$STH = $DBH->query($secureSQL);
if ($STH === false) {
    $errorInfo = $DBH->errorInfo();
    echo $errorInfo[0].':'.$errorInfo[1].' ('.$errorInfo[2].')';
    exit;
}

(You could set PDO to throw an exception when it encounters an error and use a try...catch block to handle it. That's an exercise for the reader)

Now - that syntax error. You're building your query like this:

 $secureSQL = 
    'SELECT FirstName, LastName, Phone from Members WHERE Email="' 
            . $tEmail . '" AND AES_DECRYPT(Password, $passkey) ="' . $tPassword . '"';

You've tried to interpolate the $passkey variable, but that portion of your string is enclosed in single quotes so interpolation doesn't operate. You've concatenated the rest of the parameters, so it's not clear why you've done something different here.

You've also omitted enclosing single quotes around the $passkey so the query would have failed even if the interpolation had worked. Simply swapping your use of single- and double-quotes would have made this easier.

You need this:

 $secureSQL = 
    "SELECT FirstName, LastName, Phone from Members WHERE Email='" 
            . $tEmail . "' AND AES_DECRYPT(Password, '$passkey') ='" . $tPassword . "'";

There's more.

You have added your user input directly into your query string without any form of escaping. This leaves you wide open to SQL injection. Combine that with an encrypted password and you have an open invitation to a hacker to raid your database. At the very least you should use PDO::quote() to escape the variables, but a better approach would be to use prepared statements and avoid the injection risk altogether. (Another exercise for the reader).

And finally (this has been covered in the comments) do not encrypt passwords - hash them PHP provides password_hash() for this purpose in PHP 5.5+, and there is a shim you can use for earlier versions.

If your professor is teaching you to use AES_ENCRYPT() to secure passwords you really should take him to task over it.

  • Thank you so much! I'm still pretty new to all this and I'm learning more every day, and you've helped a lot. I'll definitely look into these things you've mentioned. I've just started learning about SQL injections and it's certainly concerning. And I'm definitely going to be asking my professor about the safety of using AES. If so many people on here think it's not secure, then I don't doubt that it's not. I don't want to learn things the wrong/unsafe way. Again, thanks so much. I'm glad people are willing to help out random college students with their programming. Cheers! – user3579547 Feb 24 '15 at 00:16