PHP Best Practices for User Authentication and Password Security

PHP best practices for user authentication and password security

OpenID is a method to authenticate users based on their existing accounts on common web services such as Yahoo, Google and Flickr.

Logins to your site are based on a successful login to the remote site.

You do not need to store sensitive user information or use SSL to secure user logins.

A current PHP version of the library can be found here.

PHP best practice on user authentication for a website?

Your SQL statement has an injection vulnerability in it. (This is under the assumption that the "submitted" suffix means the variable hasn't had any filtering done on it.) If a malicious user were to submit 'admin@example.com' AND 1=1;-- as an email address, they could log in with the credentials of "admin@example.com", irrespective of the password. I'd suggest to secure the input to the SQL and/or use stored procedures. I'd also suggest loading only the columns that you absolutely need; it will improve the speed of the query and allow less state to be held in suspension outside of the database.

Additionally, implement salting on the password. If someone were to retrieve the user's data from the database, the passwords would be an easy target for bruteforce and dictionary attacks (like rainbow tables). If you're really paranoid, consider switching from MD5 to SHA or another hashing function.

Make sure of which variables are set in your php.ini file and that they are set to values you expect. Depending on those settings, the array assignment to $_SESSION is also insecure. Some old web applications utilized a PHP 'feature' which made variables in the query string become global variables in the web application, which meant that when it executed $_SESSION['userid'] = $userid;, if a malicious user attached ?userid=1 to their query string, they would become the user with the user ID of 1, which often was the first user (or administrator).

Whats the best way to do user authentication in php?

use Sessions. Store the session id in the cookie, and store the state of the user on the server side (loggedIn, userId, IP).

To clarify what you need to store in the session array:

  • loggedIn: A boolean variable about whether the user is logged in or not. You reuse the same cookie for multiple sessions, so you remember the users username next time they come to your site, etc.
  • userId: The uniqe id of the user in the database. Use this to get more information on the user, like username, email etc. This too can be kept in the session array after the user logs out.
  • IP: To prevent someone from stealing the session id and using it, you store the IP of the user as well. This is optional, as sometimes you want to allow the user to roam (eg, stackoverflow allows me to move about with my laptop without logging me out when the IP changes).
  • lastPing: The timestamp the user was last seen. This can be used instead of the cookie expiration date. If you also store the lifetime of the session, then you can log the user out due to inactivity. This means that the session id cookie can be stored on the users computer for a very long time.

When the user logs out or is logged out due to inactivity, you simply set loggedIn to false. When the user logs in with the right username and password you set loggedIn to true and update the other fields (userId, IP, lifetime). When the user loads a page, you check the lastPing against the current time and the lifetime, and either update lastPing or logout the user.

The session data can either be stored in the filesystem or in a database. If stored in a database, then userId is either a foreign key to the user record, or all the data can be put in the user record.

Hashing

rehashing a value several times is not a good idea, because you reduce the security. Instead use salt, combining a static salt (name of the page for example) and the username of the user, together with the password. A hash that takes a long time isn't better than a fast hash, a hash that results in a large digest is better than a hash that results in a short digest (due to brute force). Using SHA1 should be good enough for a normal site (IE, not a bank or a secret military organization).

What are the best practices for secure login in PHP web application?

It is NOT a good idea to store the password in plain text at any point in time.

1) I do not recommend the PRG model for a login page. The worst thing that could happen is that the person is logged in twice. That's not so bad.

Data stored in $_SESSION can typically not be read by the client. They ARE stored on the server where a malicious employee or hacker might get access to them.

2) After authentication it is ok to check the session to see if someone is logged in. Someone may spoof someone else's session id but the chance of that is minimal as long as you are running SSL. I recommend storing the IP, user agent, and other information you can get easily in the $_SERVER variable and comparing it either on occasion or every time. To reduce the chance that someone has hacked the other person's session id.

Regenerating a session id on login doesn't make a lot of sense to me, although I don't know your particular scenario. My suggestion is to simply regenerate it on log out. Also, you can add a time out feature to the session if you like.

Developing a secure PHP login and authentication strategy

A few random thoughts :

  1. What if I steal the cookie of one of your users (using an XSS attack by injecting some JS code in your website) ? I will then fall in case 2. and thus be able to log in. IMHO, if you want a really secure authentication, do not use "remember me"-type cookies to store user credentials.
  2. If you do store the credentials in a cookie, please don't store the password in clear.
  3. Checking for the HTTP_USER_AGENT is a good first step to prevent session hijacking, but maybe you could combine it with the IP address ? It is far more difficult to be on the same host than your target than to simply use the same browser.

But in any case, thanks for taking the time of thinking about a good authentication scheme. A lot of PHP developers don't.

EDIT: for the record, let me clarify a point here : there are two cookies in this discusion. One being set automatically by PHP to propagate the session ID (sometimes, we see websites putting it in the URL, eg www.example.com/page.php?sessionId=[...]), and the second one created by you in order to store the user credentials and authenticate him when the session is lost. The XSS attack applies to both, ie an attacker could either steal the session cookie and hijack the session (which has a limited lifetime), or steal the credentials cookie and authenticate later.

PHP Secure Session Login - Best Practice

  1. mysql_real_escape_string() does not safeguard you from all forms of SQL Injection, or other types of attack for that matter. You should use a system in which incorperates code to guard against many safeguards individually, an example of such I use on my testing server (not strong enough for production):

    function sanitize($str)
    {
    $str = trim($str);

    if (get_magic_quotes_gpc())
    $str = stripslashes($str);

    return htmlentities(mysql_real_escape_string($str));
    }

Please read the accepted answer for this question to see why any way you filter user input is never full-proof.

--

As far as information about securing user logins, please consider the following tips:

  1. Avoid user input whenever possible, and if impossible; sanitize their input.
  2. Do not use only md5 for securing user passwords. It is easy to decrypt.

    • Consider using a password salt, unique to each individual user.
  3. Keep your own passwords both long, and diverse.

    • Optionally extend these as suggestions to your users' passwords. Example:

      • Must be at least six characters in length.
      • Must consist of a mixed case of characters.
      • Must contain at least one number.
      • (Secure) Must contain at least one symbol.

Rationale and statistics about password strength:

I, (with a nVidia NVS 3100M mobile graphics card), can crack or "brute force" an MD5 or SHA1 hash at a speed of 56,900,000 passwords per second. This means I can complete all passwords of lengths 1 - 6 characters, with a full (a-zA-Z0-9 + symbols) character set; in less than four minutes. Imagine what someone with a decent computer (even a gaming one), or a server could do.

The way to safe against this is to salt your passwords. Depending on how you salt your passwords, the "attacker" would need to try many different means of decrypting before they would be able to guess any of your user's passwords. If your password was not salted, they could brute-force it in the way I have described above.

Read more about PHP Session Security:

PHP Security Guide - Session Security

PHP Session Security (StackOverflow)

Notes on Session Security (SitePoint)

Also Worth Nothing:

You need to decide what your website needs to be secured against. If your website is hosted on a shared server or shared hosting (whether it be a VPN, VPS, or some sort of semi-dedicated solution) you will always be at risk of other malicious users on the system having access to your PHP files, and by extension; your MySQL database. Even on a dedicated server, without proper internal network security you are just as screwed.

Php login - Best practice

Hash the password! never store in plaintext.

And to stop a misconfiguration from revealing your password store the password outside of web root so if PHP was to reveal your code, then the client/attacker could not access the actual hash/file. Here is a simple example using the crypt() function inside a simple user function to check pass.

<?php
function check_pass($password){
$chkpass = file_get_contents(dirname(__FILE__).'/../path_outside/webroot/adminpass.txt');
if(crypt($password, $chkpass) == $chkpass){
return true;
}else{
return false;
}
}

/* The file adminpass.txt contains the hash
$1$MH0.l.1.$aNx9btlqPfGpkAxK4Bdym.
which is mypassword in plaintext */
if (check_pass($_POST['password'])) {
echo "ok!";
}else{
echo "fail!";
}
?>

What should I use for user authentication in PHP?

Check this answer here.

Although the answer is 3 years old, the suggested phpass library is up to date.

Also, +1 to Aron Cederholm. Password security is an extensive subject and you should look first at the related questions already discussed here on StackOverflow so you will be more familiar with the subject and best practices in security.

Although I like frameworks (Symfony, Zend, etc) as they generally implement these good practices, just using them don't make you a good programmer. You have to learn its inner workings. I always salute a programmer dwelving into coding his own secure authentication mechanism (as long as they don't implement it in a live site that really needs strong security), because that's the best way to learn and understand the inners of the subject. Always start from an existing implementation, and THEN use that as an example for creating your own codebase.



Related Topics



Leave a reply



Submit