Concerning cookies expiration time what is the best practice for a secure application ?
The login system is a SSO that I can't manage, so the ["remember me"][1] option is not possible.
There are 2 solutions
Time expiration, the cookie would expire after a specific amount of time, i.e. 4 hours. But if the user use a shared computer and forgot to log out, another user could access the web application.
Session expiration, the cookie would expire after the web browser is closed (or [even worse][2]. But what if the user never close his session and always keep is computer turned on. The cookie would never expire even if the user doesn't need access to the web application.
Is there not a way to do both at the same time? Base the cookie expiration on the session with a maximum duration of time...
NB : Believing in a security aware user is a sweet dream, thus trust in the user log out is not feasible.
.
[1]: What is an acceptable expiration time for a cookie
[2]: When does a cookie with expiration time 'At end of session' expire?
Since no one else has taken a stab at this question, I'll hopefully get the ball rolling, lol. I'm not sure if this will exactly answer your question, but I'll try my best :).
I think that given the 2 solutions you have presented, along with the dependency of the user behavior, I really don't think there is a good answer in terms of "best practice" (which may also be subjective).
If both solutions were used (that is, a cookie that expires after a specific amount of time [i.e, 4 hours] OR at the end of a session) you would also take on the "con's" of each of those approaches. So, if the user forgets to log out within the expiration period and does not close their session, there is an issue.
So what I am saying is that in any case, the security is based on the user behavior and there will always be these flaws. Using a mix of solutions (defense-in-depth), as you have suggested, is a good line of thinking.
Related
Hello fellow developers
I have obviously under estimated a thing when developing my first complex web site, where user creation and login is required.
It appears that cookies can be edited and modified by the user logged in, by using some developer tools i.e. in Google Chrome. That, I never gave a thought.
So, here is my issue.
When the user is logged in, I store the user name in a cookie.
If username-cookie is not blank, and I can find a user file with that name, the user is logged in, per se. Otherwise, no user is logged in.
When the user logs out, I simply expires the cookie, which works fine.
Now, the problem is, that a user obviously can edit the content of a cookie, outside the web application, or with javascript.
What would be the correct approach here to ensure, that the username cookie is not compromised in any way, other by my web application?
Making them read-only is not possible, I assume. Encrypting the cookie and then decrypting might work, I guess. Then, the cookie would be nonsense to the user, and if modified, result in a logout, as no valid username can be found upon decrypting the edited cookie.
I have stalked Googles cookies, and it appears that there are a lot of xxID cookies, which contains garbage. Does that mean, that encrypting/decrypting is the only way to make it work? I also considered some kind of login-ticket, but that would require a table lookup every time a user interacts with my web page.
Can anyone give me a hint as to what would be the correct approach?
Thanks in advance
Best regards,
Karsten Heitmann
You should look up session management for the language you are using.
The traditional approach is that when a user logs on, your application generates a long, cryptographically random token called the "session id" and sets that into a cookie. It stores data like who is logged in on the server side identified by the random value, so when a logged on user comes back, the browser sends the cookie with the random session id and the application can look up session data on the server side. This way an attacker has no way to guess a valid session id for a logged on user, assuming the session id is cryptographically random and long enough (which more precisely means it has enough entropy). Logging out means deleting the session data on the server side, and also removing the cookie, but that is not the most important part - the session will be invalid anyway.
Note that you should not code this yourself. You did not mention the language and environment you are developing in, but session management is rather tricky business if you want to secure it, and it is already provided by most languages / frameworks.
Just for curiosity, the encryption approach you mention is by the way a valid one. Some frameworks actually do that, but you should not attempt to code that either, because it is very easy to get it wrong, lots of things need to be taken care of to make it secure enough. Unfortunately an answer here is not the right format to go into details I'm afraid.
Btw you mention looking at Google. They use their own single sign-on solution, it is very complex compared to simple session management, so it's probably not the best example for you to look at. Find simple websites, most of those work the traditional way.
I am using node.js + redis for session persistency, however I'm noticing that in nearly every example of redis store or other session persistence, there is a static maxAge or timeout for sessions that you can configure.
It makes sense to me that the session length should be based on the last interaction, and thus allow me to make an update on the timeout. Redis's documentation on its EXPIRE documentation has a section on refreshing the timeoutl
Is refreshing the session timeout bad by design? Should static timeouts always be used?
Edit
My original question was very general since I couldn't find documentation for my specific case and I assumed perhaps it was bad practice! I finally discovered how to do this with Connect + Node after looking at the source code:
Connect listens to the header end event (to know to update the session)
When the event fires, it asks the session store to save the session
Specifically as part of connect-redis, the save method updates the maxAge
In short, I was looking at the wrong place for documentation. Connect#session documents how if maxAge is assigned a new value, session stores (like connect-redis) should honor that.
There is no such thing as bad design, only bad choices.
Static Max Timeout
A good choice where security is of the utmost importance. Using a tight session timeout, especially with authentication, ensures that the end user is the intended user and not someone who dropped in while the principal user was away from his/her pc or device. The major downside to this approach is negative impact to user experience. The last thing you want is the session going stale just before the user was about to checkout or do something important; with a static timeout, this is inevitable and will happen often enough to piss off users.
Reset Timeout Based on Last Visit
It's safe to say most websites use this approach since it offers a good balance between security and user experience. Resetting the session timeout based on last visit eliminates the issue related to static max timeout, and most ecom and banking websites use this approach, so it's certainly an accepted approach.
Not knowing what you're actually building, I'd say going with the reset approach is probably a good choice nonetheless. The examples you mentioned likely omitted resetting the timeout for brevity reasons, not because it's a bad design.
Is it insecure for an app to report how many days are left before current password expires?
For example, if passwords expire every 30 days, if the app told you that your password will expire in 5 days (after you have logged in of course).
Or, is it possible that the app could store a cookie that tells the app to start suggesting a password change 3 days before the password expires?
Would either of these be considered bad practice?
See Bruce Schneier's blog post on Changing Passwords.
The main reason for password expiry is to make compromised passwords expire; telling the user (or the attacker) that it'll expire doesn't change this. What it does do is tell the attacker to compromise something else before the deadline; whether this is a risk depends on whether there are such attackers (I'd expect the first thing to do would be to install a rootkit).
The security benefit is that the user is given some amount of time (e.g. a week) to think of a new password. I can come up with a half-decent password in a minute or two, provided I'm not in a rush to get work done; otherwise I'd just increment a counter on the end. Everyone does this.
My feeling is that the benefit of effectively saying "at some point in the next week, think of a new password" outweighs the potential risks, but 30 days is far too short. There are only a handful of passwords that I actually need to remember (phone, laptop+root, home server+root, work computer+server, password safe); changing any of these is tedious.
There are various ways of ensuring that users don't choose passwords related to old passwords; none of them are particularly good.
I think that if you need to tell the user that the password expires in so many days, you should make a page that appears after the login has been completed.
For example, if you have one page that is your login form, then after that it goes to another script that redirects to the home page on successful login.
Instead of immediately redirecting, you could use <meta http-equiv="refresh" content="5; URL=/"> on the page to give the user five seconds to read the page and show how many days the user has until their password expires.
But make sure the message is only shown after login, otherwise a hacker can read the contents of the login page to find out when their password needs changing.
Ad#m
I don't think it's insecure to tell the user when their password expires - at least I cannot see how it can realistically aid an attacker. It's common practice in any case - as adam mentions, Windows itself does that.
I had an authentication problem in cakephp, when positing credentials from an external site the authentication would work, and then get immediately lost, with the site prompting for login information again.
This guy determined that the cakephp session cookie was changing. His solution was to set security to low.
Seems like in medium or high security Cake makes a double check for
referer... but with low security works fine when clicking auth-
protected links from external sites like hotmail or yahoo
This solution also worked for me, but what I am losing by setting cakephp to 'low' security?
When security is high, a new session ID get generated on every request. It is practically impossible to create a single-sign-on solution between two applications by sharing a session cookie in this case, since Cake will constantly change the session ID without notifying the other application.
When security is medium (or higher), session.referer_check is enabled.
When security is low, you don't have either of the above features, but it is still just as secure as any average PHP website/CMS out there.
The main thing that I know of is the session timeout, as per the app/config/core.php comments, in that your session timeout will be multiplied by a lower number.
The book backs this up,
The level of CakePHP security. The session timeout time defined in 'Session.timeout' is multiplied according to the settings here.
Valid values:
'high' = x 10
'medium' = x 100
'low' = x 300
'high' and 'medium' also enable session.referer_check
CakePHP session IDs are also regenerated between requests if 'Security.level' is set to 'high'.
Ref: http://book.cakephp.org/view/44/CakePHP-Core-Configuration-Variables
So the other thing looks to be the referrer checking.
session.referer_check contains the substring you want to check each HTTP Referer for. If the Referer was sent by the client and the substring was not found, the embedded session id will be marked as invalid. Defaults to the empty string.
So the looks of it, the things you are lose are the ability to accuratly determine who and which sessions you are dealing with.
I ran into a similar problem with losing sessions and many answers pointed to using $this->requestAction() as it will basically curl a request out of the app, so it can look like another session being created with a high security.
The other thing that many google answers threw up was turning off Session.checkAgent in your app/config/core.php as that meant the session would not be checked. This at least prevented me from losing the session information between page requests.
:)
two things happens when setting to 'low'
1)timeout is bigger
2)if session highjacking is easy, then it will be easier! since the session dosent regenerate between requests as when set to 'high'!
and nothing else.
by the way you can change for a specific page the security level or the session timeout or both... so it is not a no-undo-choice
I believe the only ramifications of setting this to low are that the session time is multiplied by 300 rather than 10 or 100 for high and medium respectively and the session refer check that you are having the issue with.
Update:
If you previously had this set to high, you would also loose out on the session id regeneration between requests.
If a user logs into the site, and says 'remember me', we get the unique identifier for the user, encrypt this with RijndaelManaged with a keysize of 256 and place this in a httponly cookie with a set expiration of say.. 120 days, the expiration is refreshed each successful request to the server.
Optionally we generate the initialization vector based upon the user agent and part of the ipv4 address (the last two octets).
Obviously theres no real expiration system built into this, the user could technically use this encrypted key forever (given we don't change the server side key)..
I considered the fact that to allow this feature I need to allow the user to be able to bypass the login and give me their unique id (which is a guid), I figured the guid alone was really hard to guess a real users guid, but would leave the site open to attack by botnots generating guids (I've no idea how realistic it is for them to find a legit guid).. so this is why theres encryption where the server knows the encryption key, and optionally the iv is specific to the browser and ip part.
Should I be considering a different approach where the server issues tickets associated to a user, and these tickets would have a known expiration date so the server stays in control of expiration? should I really care about expiration? remember me is remember me after all?
Looking forward to being humbled ;),
Cheers.
Very similar question.
The solution to your question is in this blog post
"Persistent Login Cookie Best
Practice," describes a relatively
secure approach to implementing the
familiar "Remember Me" option for web
sites. In this article, I propose an
improvement that retains all the
benefits of that approach but also
makes it possible to detect when a
persistent login cookie has been
stolen and used by an attacker.
As Jacco says in the comments: for in depth info about secure authentication read The Definitive Guide To Website Authentication.
Did you consider something like Open Id? As SO uses.
How important is the information that is being remembered? If it's not going to be anything very personal or important, just put a GUID in the cookie.
Including the IP address in the calculation is probably a bad idea, as it would make users using public networks be instantly forgotten.
Using brute force to find GUIDs is ridiculous, as there are 2128 possibilities.