Securely implementing session state and 'keep me logged in' feature - security

I would like to improve security on a current application regarding session management and I want the users to be logged in until they explicitly logout.
How does one implement that securely?
Keep session information in database, like sessionid, ip, useragent?
Please provide the requirements, possibly a database layout, do's and don'ts, tips and tricks.
Note:
I know frameworks like asp.NET, rails, codeigniter, etc... already take care of that, but this is not an option. Actually it for a classic asp application. But I think this question does not relate to a specific language.

Read Improved Persistent Login Cookie Best Practice (both the article and comments).

You should know that such a system cannot be secure unless you use https.
It's quite simple:
User logs in.
The server sends the user a cookie with an expire date far in the future.
If you want, you can record the IP of the user.
User requests another page.
The server checks the cookie (possibly the IP stored with the cookie), sees that the user is logged in, and servers the page.
Some security considerations:
As stated above, there is no secure way unless you use https.
If you're using shared hosting, try to find out where your cookies are stored. Often they reside in the /tmp directory, where every user as access to and through that someone could possibly steal your cookies.
Track the IP, if you know that the computer isn't ever going to change it.
Don't store any information in the cookie. Just store a random number there and store the information belonging to it on the server in a database. (Not sensitive information like preferred colour can be stored in the cookie, of course.)

Create a cookie with a ridiculous expiry like 2030 or something. If you need session state, keep a session ID in the cookie (encrypted if security is priority) and map that to a table in a database. IP/UserAgent etc. tend to be meta-data, the cookie is the key to the session.

Related

php5 $_SESSION security

I read sessions and security questions on stackoverflow, and much beyond. I think I know the answer, but I want to confirm it with one concise simple question--security is too important.
Conjecture: My black hat web visitor does not have direct access to his $_SESSION contents.
that is, after my server executes
$_SESSION['myuserprivilege']='user' ;
I can assume that even the most clever blackhat cannot somehow find out even that my code did this, interrogate to what my php program set his server $_SESSION to (both keys and contents), or (much worse) engineer $_SESSION['myuserprivilege'] = 'admin'. only my own server php code can do so.
I still have to be concerned that a blackhat can steal the cookie of a different admin user ( => https and session rotation). but that's a different issue.
correct?
The values of the session are stored in your server, not in the user machine. So, no... No one can see or set that value without access to your server or any security problem in your code. It's like money in a safe, only who have access can get it or if the safe isn't secure enough.
And about cookie stealing, this is called session hijacking. It's common tecnique used to steal a session from another user. You can get more information here.
Basically if a person get the id of the session of a logged admin and the application doesn't have any approach to avoid this kind of situation, this person can have access to that user privileges.
Anyone can set a cookie in your website, but sessions has one thing called "PHP Session ID", so to get some value from a session, this person need to know a valid session id that have privileges to some part of application.
Session routation is not a problem, the chances to get some session from anyone that have this privileges is really, really hard. You also can use more characters in your session to make it more harder, but o don't think it's necessary.
Final answer: No one cannot set a session in our website, just who has access do the code and your server can do it.

Harm of passing session id as url parameter

So I just noticed that one of the internet banks websites is passing session id as url parameter. ( See image below )
I didn't previously see anywhere that ';' in url, in this case it is after 'private;'.
1) What is the use of this ';'?
2) And why internet bank, which needs to be securest place in the internet is passing session id as url parameter?
At first, I thought they are doing it because some of the users disallow use of cookies, but then again, if they allow it, use cookies, if not - url, but I do allow use of cookies, so obviously thats not the case.
3) I guess then they should have some other security measures? What they could be?
4) And what one can possibly do if he knows others valid session id?
As I know, you can quite easily log into others peoples session if you know that id, because its not hard to edit cookies and its much easier to pass that session id as url parameter, especially if you have something like:
session_id($_GET[sessionid]);
Thanks!
1) You should ask whoever designed the application your red box is covering. URL can be anything you want; the convention of key=value&key2=value2 is just that - a convention. In this case, it's Java, and it commonly uses the convention of ;jsessionid=.... for its SID.
2) It's not that big of a deal. Normal users can't copy-paste cookies like they can copy-paste a GET parameter, but power users can do whatever they want (using Mechanize, wget, curl and other non-browser means, or even browser extensions). And if you allow it for some users and disallow for some, it's not really much of a security precaution, is it? Basically, cookie SID will make the attack a bit harder, but it's like putting your front door key under the mat - definitely doesn't keep your door secure. Additionally, cookies are shared between tabs: if a site wants you to be logged in with two accounts at once, you can't do it with cookies.
3) Serverside security, yes. One effective countermeasure is one-time SIDs (each time you visit a page, the server reads the session from the current SID, then starts a new session with a new SID for the next request). A less effective but still good method is to validate other information for consistency (e.g. - still same IP? Still same browser?)
4) Yes, if you know someone's valid SID, and the server does not adequately protect against session fixation, you can "become" that person. This might enable the attacker to, say, pay his bills with your money, for instance.
So, #Amadan correctly covered #1 and #4. But there's a bit more that needs expansion.
Using Session identifiers in a URL can be a major problem. There are a few cases where it's critically bad:
Session Hijacking:
If a user copy-pastes a URL into an email.
In this case, the attacker can simply read the email, and steal the session identifier (thereby resuming the session).
You could partially defend against this by making session lifetimes short, and validating things like IP addresses or User Agents in the session. Note that none of these are foolproof, they just make it "slightly" harder to attack.
If the connection is ever downgraded to HTTP.
If they are not using Http-Strict-Transport-Security (HSTS), then an attacker may be able to successfully downgrade the session to HTTP only (via MITM style attack). If the server isn't setup perfectly, this can cause the URL to leak to the attacker, and hence the session identifier.
Session Fixation Attacks
An attacker can craft a session identifier, and send the user a forged link with that session identifier. The user then logs in to the site, and the session is now tied to their account.
You can mitigate this by strictly rotating session identifiers every time the session changes (log in, log out, privilege upgrade or downgrade, etc). But many servers don't do this, and hence are susceptible to fixation style attacks.
The reason that cookie sessions are seen as more secure is not because they are harder to edit. It's because they are more resistant to fixation attacks (you can't create a URL or link or form or js or anything that sends a fraudulent cookie on behalf of the user).
Why the bank uses a URL parameter? I have two guesses:
Because they want to support those who don't allow cookies.
Which is sigh worthy.
They don't know any better.
Seriously. If it's not in a compliance doc or NIST recommendation, then they likely don't do it. Hell, there are implemented NIST recommendations that are known to be insecure, yet are still followed because it's in writing.
What is the use of this ;?
This is just a query string separator. & isn't the only sub-delim specified in the URL specification (RFC 3986).
And why internet bank, which needs to be securest place in the internet is passing session id as url parameter?
It could be that this session ID is never used, and the actual session identifier user is passed in cookies or in POST data between each navigated page. The only way to verify this is to try copying the URL into another browser to see if your session is resumed, however then again they may be checking things like User Agent - not real security but would dissuade casual attacks. Do not try this on a live system you do not have permission to do so on as it would be illegal. If you want to learn about security download something like Hacme Bank and try on there.
I guess then they should have some other security measures? What they could be?
No doubt they will, otherwise this would be a huge security threat. The URL could be leaked in the referer header if there are any external links on the page. The types of security a bank uses for their website is too large to list here, however they should be meeting certain industry standards such as ISO/IEC 27001 that will cover the types of threat that their site would need to be secure against.
And what one can possibly do if he knows others valid session id? As I know, you can quite easily log into others peoples session if you know that id, because its not hard to edit cookies and its much easier to pass that session id as url parameter, especially if you have something like:
As the ID is displayed on the screen it might be possible to read it (although IDs are generally long). A more realistic attack is Session Fixation. This is where an attacker can set the Session ID of their victim. For example, sending them a link that includes the attacker's Session ID. When the victim follows it and then logs in, as the attacker has the same session, they are logged in too.
Storing the Session information in a cookie or in a URL are both viable methods. A combination may used as
Security session management and (Server) Session management are separate aspects:
The fundamental difference is that cookies are shared between browser windows/tabs, the url not.
If you want your user to be logged on when navigating to the same site in different tab, sharing the security session (=without a new logon procedure) then cookies are a good way.
To differentiate "sessions" per tab and associate distinct server sessions with distinct tabs (Think of the user running two "stateful" transactions in two different tabs in parallel), managing a sessionId on the client which can be different per tab is required. Cookies won't work here.
Putting it in the URL is one way to assure this information is routinely added to requests fired from the page (referrer header). Alternative methods would require specific code to add this information explicitly to each request which is more work.
See How to differ sessions in browser-tabs?

Authentication system - is my one secure?

I want to authenticate my users based entirely on cookies and sql db.
What I do is:
1. Once they login, I generate a random string, create a hash from it, save it in the database along with the user id and his IP.
2. I send the hash to the user as cookie
3. Whenever he wants to access something, I verify if his cookie hash matches the one on the server and also if his IP matches. Of yes, he is valid or else, log him out.
4. (As pointed by Akhil) If he clears his browser cookies or anything does not match the information on the database, I clear all the rows with his username and log him out.
Note: I use a session cookie for storing the random hash, which again is generated using the timestamp, and as long as time doesn't repeat itself(I believe), its random in the corect way.
Is this fine? How can I make it better?
Once they login, I generate a random string
Make sure you use a cryptographically secure method to generate the random string. Do not use mt_rand use something such as openssl_random_pseudo_bytes.
create a hash from it,
Make sure to use a secure hashing algorithm (not MD5, and at least SHA-2).
save it in the database along with the user id and his IP.
One thing to bear in mind is that some internet connections share IP addresses or will sometimes change the client IP address (e.g. AOL or mobile).
I send the hash to the user as cookie 3. Whenever he wants to access something, I verify if his cookie hash matches the one on the server and also if his IP matches. Of yes, he is valid or else, log him out.
It sounds like a good way of doing it and there are no flaws in itself. I would implement a session timeout mechanism. For example, store the date last used in the DB for a sliding expiration and the query will only query records that have not expired. You could have a background process that runs to clear out old, expired records.
Also, use HTTPS and set the Secure and HttpOnly flags on the cookie. This will prevent them being leaked over HTTP, but I would not go as far as disabling HTTP on your system as there are workarounds for an attacker if it is anyway.
I would not be concerned with the cookie being stolen by another user on the same machine. If the cookie can be stolen in this way then the user's machine is probably compromised anyway and you cannot make your system protect data that is outside of your control. You could however renew the token (random string) on a periodic basis giving the user a rolling cookie. You would have to ensure only one user can be logged in at once under the same account though for this to be effective.
Your method only makes sure that the user possess the random string you generated and is using the same external IP address. There exists several way of abusing this system:
if your website doesn't enforce HTTPS then a user connecting using an unsecured public WiFi network could be at risk: if another user of the WiFi network is listening to all the packets being sent on the network, he could intercept your cookie and use it to access the website as your legitimate user. Your server would be unable to differentiate them because they'll both use the same IP address... (There is a Firefox extension available which enable anyone to intercept such login cookie easily: http://en.wikipedia.org/wiki/Firesheep)
This system is also more generally vulnerable to man in the middle attacks (without HTTPS)
If your cookie is stored on the user computer's hard drive it could be reused by another user.
So to answer your question, your system can be deemed as secured provided a few conditions:
you enforce the use of HTTPS on your website (unencrypted HTTP connections should be refused)
your random string is truly random (there exist right and wrong ways of generating random strings in PHP)
your cookie has a short expiry and preferably is set as a session cookie.
You should take a look at the following related question providing details about the proper way of doing what you want to do: How to secure an authentication cookie without SSL
One cannot say this is "bad". But in Web Development, and specifically in its security domain relativity talks. I recommend you to download a CodeIgniter (google it for more info) Session Class (standalone version) and use it. The basic idea is the same as yours, but it is properly more mature since it is developed in such a famous php framework. You can do your DB operations within that class too, since it allows session saving to DB.

store user ID in Session or encrypted cookie for a long time?

in web application like a society networks users log in and do some works for long times like 2 hours or more, now i store some data like user ID (identity number in member table) in session and found users details data by this id .
and when each user log in to site i store this data for that user on session for 2 hours.
for this work i set my session time out on 120minutes and i want to know is this work good?
i mean storing session for 2hours.
in another hand i can store that ID on encrypted cookie on client and i want to know is this way secure and if user/hacker can decrypt my cookie and retrieve user id (this id is my identity table id) can attack to my site and do some thing or not?
In the world of Web, information storage connections in the session variable is wrong path. You do not control the session variable and can be lost at all momments.
I do not know the architecture used, but on an IIS server you can configure the encryption key for the authentication cookie in your Web.config file on your site web
<machineKey validationKey = "AutoGenerate, IsolateApps"
             decryptionKey = "AutoGenerate, IsolateApps"
             validation = "SHA1" decryption = "Auto" />
It is not possible that this information is hack on client side.
This is the better way
The problem with storing identification with a cookie is probably not decrypting the cookie but steeling the cookie as whole. This is common session and permanent cookies.
If you want to not to bother user with new login while the site is still active in browser consider shorter session timeout combined with a javascript keep alive (e.g. page refresh each 10min). Otherwise you have on server lot of sessions no longer needed.
If you want to keep user loged in even if browser window is closed. Consider including a browser identification information in the cookie (e. g. Is browser fingerprinting a viable technique for identifying anonymous users?) with good server encryption.
Don't forget to force https.
Do not store in an encrypted cookie. Store in a signed cookie. It's different, here is the why:
https://spring.io/blog/2014/01/20/exploiting-encrypted-cookies-for-fun-and-profit#modifying-the-decrypted-value
The 'old' alternative of having a session, is a bit less scalable than relying on a signed cookie, but it should be more secure, even if someone like NSA has all kinds of ways to go around signing/encryption. ** ˆˆparanoid statement ˆˆ ** but then again, if they have that, they will most likely also have man in the middle access and all sorts of sessions would be pointless.

What's the accepted techniques for staying logged on to a web site?

Most web sites you can log on to also provide the feature so it remembers you between sessions.
What's the accepted and secure techniques for implementing that ? (What do you put in the cookies and how do you handle it on the server/db?)
This recent 2009 chapter in Spring Security 3.0 discusses Remember-Me type authentication. The general concepts are not specific to Spring Security so you should be able to benefit from it even if you are not using it. The chapter also cites a Barry Jaspan's 2006 blog posting which is an improvement over the techniques described in Charles Miller's 2004 blog posting.
The blog entry basically comes down to:
When the user successfully logs in with Remember Me checked, a login cookie is issued in addition to the standard session management cookie.
The login cookie contains the user's username, a series identifier, and a token. The series and token are unguessable random numbers from a suitably large space. All three are stored together in a database table.
When a non-logged-in user visits the site and presents a login cookie, the username, series, and token are looked up in the database.
If the triplet is present, the user is considered authenticated. The used token is removed from the database. A new token is generated, stored in database with the username and the same series identifier, and a new login cookie containing all three is issued to the user.
If the username and series are present but the token does not match, a theft is assumed. The user receives a strongly worded warning and all of the user's remembered sessions are deleted.
If the username and series are not present, the login cookie is ignored.
Signed cookies that can not be tampered with can be a good idea when you don't require a whole server-side state ... lean mean and efficient.
You still run the risk of cookie theft but you can always sign the cookie using IP address, User-agent and other things to help minimize the threat.
It's just a cookie with a long life value assigned. However it will only work so long as the cookie exists. For example, I have my Firefox set to clear my cookies when I close the browser. So this wouldn't work for me.
Cookies, but the user can decide to delete it.
In the same spirit there is some kind of solution, using Flash. Flash can store informations on the client-side, not a cookie, it's not erased (usually) by the browser. With it, you can remeber which user is asking for pages, but you're stuck using a plugin-using solution, and need to know Flash..
I don't see any other solutions.
Do not try to implement session cookies yourself.
Most web frameworks give you an abstraction over this, leaving you care-free about the many security issues you might be exposing yourself to.
A simple API in pseudo-code in a web framework might look something like this, on login:
authFrwk.loginUser(request.POST.get(username), request.POST.get(password));
This will return a cookie to the client (handled exclusively by the framework).
A securely authorized operation will look something like this:
if (authFrwk.isLoggedOn()) // implicitly checks user session cookie
doSomethingImportant();
else
return notLoggedInMsg();
Basically, a session cookie is given a unique ID on the server-side, which a malacious user cannot generate/guess by himself, and which identifies the client as a logged-on user.

Resources