Security Ideas [sessions/cookies]

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Security Ideas [sessions/cookies]

Post 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.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post 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...
Last edited by Maugrim_The_Reaper on Thu Jun 01, 2006 3:45 pm, edited 1 time in total.
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Re: Security Ideas [sessions/cookies]

Post 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.
sourcebay
Forum Newbie
Posts: 5
Joined: Wed May 31, 2006 4:21 am
Location: turin, italy

Post 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.
sourcebay
Forum Newbie
Posts: 5
Joined: Wed May 31, 2006 4:21 am
Location: turin, italy

Post 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!
User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Post 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 :)
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post 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.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Post 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.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

I assume he meant a security hash + separate username to identify which user account to check it for...?
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post 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.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post 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.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post 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
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Security Ideas [sessions/cookies]

Post 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.
(#10850)
daou
Forum Newbie
Posts: 8
Joined: Sat Jun 10, 2006 12:53 pm

Post 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: )
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post 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...
Post Reply