Page 1 of 2

Security Ideas [sessions/cookies]

Posted: Thu Jun 01, 2006 9:44 am
by jayshields
Hi guys.

I've never really implemented any sort of decent security on an application, and now I've come to do it, I can't think of a good idea to use.

At the moment I have temporary security measures in place while I develop my application.

When a user logs in, it grabs their user id, and sets it in a session var, like so:

Code: Select all

$_SESSION['user_id'] = mysql_result($result, 0, 0);
Now, I can only presume this is being done by a cookie, because nothing is added to the URL, and if I disable cookies, the login system doesn't work after you navigate away from the page. Would it be a good idea to change it so it puts the session ID in the URL?

I am also using a 'Remember Me' system. Now, if someone logs in correctly and has checked the 'Remember Me' box, it sets a cookie like so:

Code: Select all

setcookie('remember', $_SESSION['user_id'], time()+60*60*24*30);
and then when someone enters the website with a remember cookie set:

Code: Select all

$_SESSION['user_id'] = $_COOKIE['remember'];
I assume this is very insecure, as all you would have to do is create your own cookie with the site admin's user ID, and next time you access the website you'll be logged in as him/her.

How should I improve my security, especially for the 'Remember Me' section? Should I store some sort of unique, user specific code in the database and check against it each time the website is accessed? Would that have performance issues? How do you tackle this sort of thing?

Thanks for any input.

Posted: Thu Jun 01, 2006 10:10 am
by Maugrim_The_Reaper
Now, I can only presume this is being done by a cookie, because nothing is added to the URL, and if I disable cookies, the login system doesn't work after you navigate away from the page. Would it be a good idea to change it so it puts the session ID in the URL?
The session id is by default stored in a cookie. Actually it's stored the first time a user visits your domain both in a cookie, and appended to all URLs. The cookie takes over once PHP verifies the client is cookie enabled. That behaviour can be changed by several config vars in php.ini.

It's usually more secure to leave the session id in a cookie - leaving it in a URL can leave some user open to exploitation if they post the links anywhere and someone accesses those links before the original user's session has expired.
I assume this is very insecure, as all you would have to do is create your own cookie with the site admin's user ID, and next time you access the website you'll be logged in as him/her.
It's insecure so long as the rememberme value stored in the cookie can be easily predicted based on commonly available user data. Would be better to generate a truly random hash (see uniqid() in combination with sha1() or md5()), and store this value in both the cookie and the user database. It shouldn't be predictable, so maybe change it every now and again - perhaps with every new remember me function use.
Would that have performance issues?
Many security feature do add overhead. It's something you may want to consider a fixed cost when writing a PHP app. Factor it in when benchmarking performance so you don't overshoot your performance goal when its not yet implemented.

There are a lot of other security measures you can take. Look up using session_regenerate_id(), for example, which create a new session id to prevent anyone potentially gaining new user priveleges if they have managed to get the old session id (i.e. use it when authorisation levels change such as logins, admin panel accesses, etc.). You can also try implementing a client side capacity to salt outgoing passwords so they can't be read in plain text during transmission, or allow IP account binding for users who wish it, or check for changes in the client who started a session (e.g. if the same session is in use and the browser client changes it's possible the valid user has a tag-along who's stolen/hijacked their session).

From reading that paragraph - it's an area to explore that's not too large, and worth knowing...

Re: Security Ideas [sessions/cookies]

Posted: Thu Jun 01, 2006 10:29 am
by Roja
jayshields wrote:When a user logs in, it grabs their user id, and sets it in a session var, like so:

Code: Select all

$_SESSION['user_id'] = mysql_result($result, 0, 0);
Now, I can only presume this is being done by a cookie, because nothing is added to the URL, and if I disable cookies, the login system doesn't work after you navigate away from the page. Would it be a good idea to change it so it puts the session ID in the URL?
People use the term "Cookie" haphazardly, and there are two kinds of cookies - which is important to realize.

There are permanent cookies, which despite their name, don't last forever. They have a finite lifespan, and you have to define it (weeks or months is common). A not insignificant minority of users limit permanent cookies they will accept, and in some cases won't accept any at all.

Sessions, on the other hand, are stored via *session* cookies, or temporary cookies. Most browsers have implemented these cookies to be memory resident, so if your browser crashes or closes, your session cookie is gone. In IE, it does store it to disk, but in a seperate area from the other cookies. In Firefox, I think its memory resident, just like Opera.

So yes, it is being done by a temporary cookie. The vast majority of users - even those with cookie watching or privacy software - usually allow session cookies.

The alternative, as you mention, is passing the session id in the url. The risk with doing so is that it is easy to capture over the wire, and its also passed to other sites when you leave. So for example, if I went from example.com?SID=3987865 to evilhacker.com , the referrer variable will contain that session id. That can be a bad thing, so generally, you should avoid passing it in the url if you can.

(It should be noted that despite these issues, temporary cookies are practically just as easy to capture over the wire - just not by referrer).
jayshields wrote:I am also using a 'Remember Me' system.
How should I improve my security, especially for the 'Remember Me' section? Should I store some sort of unique, user specific code in the database and check against it each time the website is accessed? Would that have performance issues? How do you tackle this sort of thing?

Thanks for any input.
Secure login systems put multiple checks in place to validate that you are you, and that you are allowed to do what you want to do.

Remember me systems remove multiple checks to make things easier for a user.

See the conflict between the two?

There are ways to reduce the impact, but a remember me system, by design, will reduce the security of your login system.

Ways to reduce impact:

1. session_regenerate_id() - each login, change the id, so its valid for a shorter period of time
2. Validate - any changes the user makes should bypass the remember me, and prompt for login again. For example, when changing their email or password.

Hope that helps.

Posted: Thu Jun 01, 2006 11:29 am
by sourcebay
hi guys,
i'm italian and i write english very well, but i try to do it. corrects me if i write wrong.
i usually use this method:

into a file i set a variable to a secret string. when i set the cookies for a user, i create two different cookies.

Code: Select all

// in a different file
$secret_hash = 'this is a secret string';

// when i log the user
var $id_hash = md5($username.$secret_hash);
setcookie('username', $username, (time()+2592000), '/', '',0);
setcookie('id_hash', $id_hash, (time()+2592000), '/', '',0);

// in each page, when i check the user
if($_COOKIE['username'] && $_COOKIE['id_hash']){
   $hash = md5($_COOKIE['username']).$secret_hash;
   if($hash == $_COOKIE['id_hash']){
      // show page code
   }else{
      // display error
   }
}else{
   // display error
}
the same is possible with session vars.
I often use this tecnique, if i wrong corrects me.
Andrew.

Posted: Thu Jun 01, 2006 11:32 am
by sourcebay
ops.. i write
i write english very well
, i had wrong! sorry! i want to write
i don't write english very well..
, sorry!

Posted: Thu Jun 01, 2006 1:23 pm
by jayshields
Thanks Maugrim and Roja, that made good reading.

sourcebay, use the edit function!

Good idea on the revalidation on any changes being made to the user account, I will consider that. I'll also look into regenerating the session ID and storing some encrypted value in the database and cookie and matching them - they all sound like good ideas :)

Thanks again :)

Posted: Thu Jun 01, 2006 3:05 pm
by s.dot
I think (and correct me if I'm wrong) that a remember me option should just be set to remember a username to make logging in easier. I think requiring a password everytime someone visits your site is not too much to ask. The remember me cookie should just be a convenience for the user, most likely set to just a 1 or a 0.

Posted: Thu Jun 01, 2006 6:19 pm
by jayshields
I think you're wrong there :) I've never seen a Remember Me option just remember your username, maybe you are just rejecting the cookies...

eBay, hotmail, phpNuke websites, etc, etc, have remember me functions which auto-log you in.

Posted: Fri Jun 02, 2006 4:06 am
by Maugrim_The_Reaper
I assume he meant a security hash + separate username to identify which user account to check it for...?

Posted: Fri Jun 02, 2006 12:39 pm
by RobertGonzalez
scottayy wrote:I think (and correct me if I'm wrong) that a remember me option should just be set to remember a username to make logging in easier. I think requiring a password everytime someone visits your site is not too much to ask. The remember me cookie should just be a convenience for the user, most likely set to just a 1 or a 0.
'Remember me' and 'Keep me logged in', in my opinion are two different things. Remembering a user is recalling their username when they return, but not logging them. Keeping logged in is a feature that keeps a users session persistent until that user initiates a logout, similar to the way our forums here can keep us logged in.

Posted: Fri Jun 02, 2006 3:49 pm
by Ambush Commander
Remembering a user is recalling their username when they return, but not logging them.
While, strictly speaking, you may be right, most people use remember me and keep me logged in interchangeably. The former more so than the latter.

Posted: Fri Jun 02, 2006 4:28 pm
by RobertGonzalez
I agree. It's just that if you come to my house, I meet, then let you in, it doesn't mean that I will let you in my house next time you come over. I might look through the little peep-hole and say "Oh, It's Ambush Commander", but that doesn't mean I will let you in or that you even want to get it, for that matter. You could be coming over just to see how the door glass looks up close.

I know that it is a silly analogy, but that is just the way I see it. A lot of sites use remember me as a login maintenance feature though.

PS If you do come over, bring cookies. I have a sweet tooth something awful right now. :D

Re: Security Ideas [sessions/cookies]

Posted: Fri Jun 02, 2006 4:40 pm
by Christopher
Roja wrote:People use the term "Cookie" haphazardly, and there are two kinds of cookies - which is important to realize.
This is an excellent point. Perhaps we should start a project thread to write a simple Cookie class that deals with the details of using cookies. I am thinking of a clean abstraction over setcookie()/setrawcookie() for writing and over $_COOKIE for reading. The goal would be to expose an interface that encouraged best practices use of Cookies. It could also provide some basic support using cookies for security. I did a quick Google search and did not find anything I found satisfactory.

Posted: Sun Jun 11, 2006 8:11 am
by daou
I used a checking system where the user, after being validated on login, is given a unique hashed key as a cookie and his ip is saved as a session variable.
This key is also saved as a $_SESSION variable.

Every time a page is loaded, a validation routine is executed.

Code: Select all

if ($_COOKIE['key'] == $_SESSION['key'] && $_SERVER['REMOTE_ADDR'] == $_SESSION['ip_address']) {
  give a new value for key, save it into the cookie and session variable
  load the page
}
else
  end session
Now if someone wants to hijack the session, they will need to get the PHPSESSID, the key cookie, and spoof the ip address of the logged in user.
But once they have this info, they need to use if before the user clicks a link, otherwise the session gets destroyed.
A drawback to this is multiple, fast refreshes by the user (ie clicking a link 5 times/sec). The key cookie might not be updated as quickly as the server key and the session is unintentionally destroyed (or maybe its just a good lesson to the neurotic users who think a clicking marathon will give them broadband :wink: )

Posted: Sun Jun 11, 2006 3:33 pm
by alex.barylski
jayshields wrote:I think you're wrong there :) I've never seen a Remember Me option just remember your username, maybe you are just rejecting the cookies...

eBay, hotmail, phpNuke websites, etc, etc, have remember me functions which auto-log you in.
Thats because places that do use different terminology :)

http://www.rogers.com and http://www.cibc.com are 2 places which don't remember all your details requied to login, but only Username or bankcard number, etc...