Jump to content

session, cookies and the two together for a secure login


ajoo

Recommended Posts

Hi all,

 

In the login systems on the web, I have found that some use sessions and some others use cookies to validate a login. 

 

Normally for login systems with sessions, a hashed login string is created using say the password and HTTP_USER_AGENT is stored in a $_SESSION['logincheck'] variable. 

$login_check = hash('sha512', $password . $user_browser); 

and Before access is provided to the secure login page this SESSION variable is checked against a hashed string created again from values of password retrieved from the database again.

$_SESSION['logincheck']== $login_check 

and if the two are same then the user is allowed to access his secure area. 

 

A similar approach is also provided in some cases where cookies are used. The values stored in cookies are checked against hashed values created with values of variables from the database and if they match access to the user page is granted. 

 

What I wish to ask and know is that would it be a good idea or a bad idea to implement both of these in a login system? What would be the advantages or disadvantages in both cases. 

 

I thought that using both would be a good idea but i am  not sure. I have also not come across any system where both of these have been used simultaneously. 

 

Thanks all !

 

 

 

 

 

 

 

 

  

Link to comment
Share on other sites

Hi,

 

never ever store the password or any password-related data in the session, a cookie or anywhere other than the user table. The password is the user's most sensitive data and must be protected at all cost. The last thing you want is have it flying around in text files on the server or in the user's browser.

 

It even sounds like you store the plaintext password in the database for your calculations. This would be a gross violation of basic security principles.

 

Besides that, I have absolutely no idea what this check is supposed to do. What does this prove? What does it protect against?

 

A login system works like this: Upon registration, the user submits a username and their password. You hash the password with a specialized algorithm like bcrypt (not MD5, SHA or whatever) and store it together with the username. When the user logs in, they again submit their username and password. You verify the password against the stored hash for this username, and if it matches, you store the user ID in the current session. Now the client is connected to this user account for the duration of the session.

 

The session itself is safe as long as nobody other than the user is able to find out the session ID. That of course means the ID needs to be a sufficiently long random number (which depends on your PHP configuration).

Link to comment
Share on other sites

i suggest you take a look at this post i wrote

 

 

No, this is definitely not an option.

 

As I've already said above, you must not store any password-related data in a cookie. Never. I don't know why anybody would think it's a good idea to put passwords in cookies, but this is pretty much the worst thing you can do. Cookies are simple plaintext files which reside in the user's browser for an indefinite amount of time and travel around the Internet on every request.

 

Besides that, your class is very insecure and has several bugs. Your session IDs are simply derived from the server time, which makes it very easy for an attacker to predict them. You don't have any locking mechanism, which means concurrent requests will trample each other. And you fail to prevent the session cookie from being stolen with a JavaScript attack or in transit (you don't set the HttpOnly and Secure flag).

 

I strongly recommend to use  native PHP sessions instead of rolling your own implementation. Custom sessions are only acceptable if you know exactly what you're doing and what you have to take care of.

Link to comment
Share on other sites

Hi Jacques1 and Avi. Thank you both for the reply. 

 

I would like to make some clarifications. No I am not storing the password in a cookie nor am i storing th plain text password anywhere. I am storing a hashed and salted version of the password in the tables.

 

 However I use another hashed and salted string that i am creating from the password, user browser, and a salt ( 128 characters long) as shown below  and store it in a session variable to check, for e.g. when a user moves to another page or if the page is refreshed,and ensure if the user is valid and belongs to this session.  

$login_str = hash('sha512', $submitted_password . $user_browser. $salt);  // hashed string created from submitted password
$_SESSION['logincheck'] = $login_str   // stored in session.

To check on another or refreshed page 


$login_check = hash('sha512', $stored_password . $user_browser. $salt);  // hashed string created from stored password

if($login_check == $_SESSION['$logincheck']); // confirm if the user is the right one.

Yes I use sha512 because I read that that was safe and has been used in some of the secure login systems that I read about on the web. So if that's a mistake, kindly elaborate so that i can take another look at the other encryption routines.

 

Then as i have mentioned I also thought I would use cookies simultaneously with sessions do be doubly sure of the users login. So i used a similar technique to hash another salted string and store that in a cookie on the user's machine for handshaking while browsing between pages or on page refreshes, I check for both these values and if they match, I know its the right user in the session.

 

For this purpose, I pull out the password from the db and recreate a new string to check against the submitted password just as i have done for the sessions above.

 

Now that, like i mentioned, may or may not be a good idea and I am not sure. Hence I am asking the gurus.

Edited by ajoo
Link to comment
Share on other sites

Hi,

 

like I already said above, you cannot even store data which is related to the password in a cookie or the session. This includes hashes of the password. Knowing the hash allows an attacker to start a brute-force search for the password, so this seemingly harmless extra hash may very well reveal the full password in the end. Long story short, don't do it. The only thing you may do with the password is hash it and store the hash in the user table. 

 

SHA-512 is absoutely inappropriate for hashing passwords. Whoever told you to use it doesn't know what they're talking about.

 

None of the general-purpose hash algorithms like MD5, SHA-1 or SHA-2 were ever meant for passwords. They're designed for digital signatures, which is a completely different goal. Calculating signatures should be very fast and work on weak hardware like smartcards, so those algorithms are heavily optimized towards speed and low hardware requirements. This allows an attacker to calculate billions of hashes per second on a stock PC. It's easy to see what that means for passwords: They won't last very long. Searching the entire space of all alphanumerical passwords up to 8 characters takes something from a few minutes to a few days, depending on the algorithm and the hardware.

 

So this is definitely not an option. It doesn't matter which of those algorithms you choose. SHA-2 is just as bad for password hashing as MD5, even though many people run around telling everbody that MD5 is “broken” and that some SHA algorithm with a big number in the name is “strong”. This is an urban legend. It also doesn't help to salt those weak algorithms, because the attacker can easily make up for it with some more dollars or some more time.

 

The only way to protect passwords against the massive computing power of current hardware is to use a specialized password hash algorithm. This algorithm needs three properties:

  • It must be computationally expensive
  • It must have a variable cost factor which can be increased over time
  • It must generate a random salt for every password so that each hash must be attacked individually

Currently, the algorithm of choice is bcrypt. It's strong, time-proven and well-supported by PHP. There are other algorithms, but they all have a drawback.

 

If you already have PHP 5.5, you can take advantage of the new Password Hashing API which makes bcrypt very easy to use. If you don't have PHP 5.5 yet but at least 5.3.7, you can include the password_compat library which offers the same functionalities. PHP versions before 5.3.7 have a defective bcrypt implementation and cannot be used.

 

A short example:

<?php

// bcrypt cannot process more than 72 bytes input, so the user should be warned if the password is too long.
define('PASSWORD_MAX_LENGTH', 72);
// Adjust the cost factor to your hardware; make it as high as your CPU and your users are willing to accept.
define('PASSWORD_HASH_COST', 12);



// Create a new hash.

$test_password = 'a0WHnUH3IDE7Yl2T';

if (strlen($test_password) <= PASSWORD_MAX_LENGTH)
{
    /*
     * The result will consist of exactly 60 ASCII characters and look something like this:
     *
     * $2y$14$6/F6Y7u/jGAUmrUpHZIQ9e1EVLIj0GUtLQdNUEJGthCm4d77bZTUy
     *
     * All information about the hash are included in this string: The "2y" identify the algorithm
     * (in this case bcrypt), the "14" is the cost factor, the next 29 characters after the "$" are the
     * salt, and the remaining 31 characters are the actual hash.
     */
    $password_hash = password_hash($test_password, PASSWORD_BCRYPT, array('cost' => PASSWORD_HASH_COST));

}
else
{
    echo 'Your password is too long. The maximum length is ' . html_escape(PASSWORD_MAX_LENGTH) . ' bytes.';
}



// Verify a password against an existing hash.

$password_to_verify = 'a0WHnUH3IDE7Yl2T';

if (password_verify($password_to_verify, $password_hash))
{
    echo 'The password is correct.';
}
else
{
    echo 'The password is wrong.';
}






function html_escape($raw_input)
{
    return htmlspecialchars($raw_input, ENT_QUOTES, 'UTF-8');
}

Back to your original question:

 

Your check simply makes no sense. Your session contains the user ID, right? And then you look up the password and salt for this user ID?

 

This proves absolutely nothing. You just hash the same user data you hashed a few minutes ago. The only way this check could fail is when the attacker doesn't know the victim's user agent. But this is an absurd assumption. First of all, the UA isn't secret at all. It can easily be found out or simply guessed. And it makes no sense to assume that an attacker who just managed to steal a very strong secret (the session ID) somehow fails to get a much weaker secret (the UA).

 

So this check really doesn't get you anywhere. Instead, you should make sure your session IDs are strong. If you don't know how, simply create a new thread.

 

Link to comment
Share on other sites

Thanks Jacques, 

 

I will create a new thread now as you suggest but i can swear that almost all examples that I saw on the net use sha512. MD5 and the lot that you rejected for hashing passwords. 

 

Thanks for the example on bcrypt. I'll look into it.

Link to comment
Share on other sites

I will create a new thread now as you suggest but i can swear that almost all examples that I saw on the net use sha512.

 

Yes, but that doesn't make it less wrong.

 

It's a well-known fact that a lot of the people who run around writing PHP “tutorials” have absolutely no idea what they're doing. Often times, it's not even their own code. They've just copied and pasted if from somebody who copied and pasted it from somebody who copied and pasted it from somebody. That's why you see the same mistakes being made over and over again and passed from generation to generation.

 

Like I said, this is known problem. But since there are no laws against bad code, there's not much we can do about it. All we can do is give better advice and ask people to choose their sources more carefully.

Link to comment
Share on other sites

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.