Friday, January 9, 2009

When and How to Use Cookies

(Disclaimer: The methods described below should be viewed as education purposes only! These methods are not certified by me to stop or prevent attacks to your site. Instead, this blog tries to explain some ideas for properly using cookies. In other words, use these methods at your own risk, but don't come looking to sue me if you or your site are compromised).

Cookies, by some, are one of God's greatest inventions for the Internet. To others, cookies represent all that is bad and evil in the world today.

In reality, they are both.

These little files are only as good or bad as you, the developer, use them. With the growing popularity in XSS Attacks and CSRF Attacks, there is no wonder developers are having trouble relating anything good with using cookies, and also why even more users are refusing to accept them.

In this blog entry, I'll explain to you how to make using cookies on your site safer by explaining the following:
When to use cookies, and when not to use cookies
How to properly validate users with cookies
Alternatives to using client-side cookies
References/Further Reading

When to use cookies
Cookies, by many sites in the past and, unfortunately, the present, are mainly used to identify a user who has access to a website. They are intended to be a beneficial file(s) that grants users a more pleasant experience while they are browsing, shopping, or later return to a site, without the need to retype their credentials. However, the same helpful intentions of cookies such as these are continually being turned into unpleasant security vulnerabilities for users and websites alike.

We first start with when not to use cookies.

Cookies should not be used to store sensitive information. To be more blunt, you shouldn't store unencrypted (or plain-text) values for usernames, credit card information, first/last names, addresses, phone/fax/mobile numbers, passwords, email addresses, websites, social security get the drift. Nothing personally related to your user nor anything that will be used to automatically authenticate/login a user should be available in a cookie.

While select few will scream “blasphemy” at such an idea, I assure you it is not I who is blaspheming. It is a common misconception for developers to think cookies are a safe warehouse for information. Such carelessness is leading the current craze of XSS and CSRF attacks among crackers (poorly and misleadingly labeled hackers) to be legit methods to obtain or attack a user/website.

So what should cookies be used for then?

Cookies should be used for simple and harmless storage, and/or by validating that an actual user is submitting a form from within your website (for examples using the form method, please see Preventing CSRF andXSRF Attack link below).

Some Ideas of simple storage:
Keeping track of a shopping cart of an unregistered user (registered users have the luxury of that information being stored in a database).

Remembering which test/quiz/questionnaire/poll a user has already completed.. Of course, I do not mean for use with prize-based poll/questionnaire/etc. These should be limited to registered users and, like before, stored in a database.

Tracking when a user is logged into your site to assist and report “Number of active/Logged In Users” status.

All of these methods are simple, and harmless uses to store cookie data. But like any other data coming from a user to your site, the above must always be validated. You must be as paranoid as possible when dealing with data coming from your client, and validate everything, always. Assuming that no one cares about your website, or that it's unlikely a cracker would ever want to take over your website is exactly why a cracker would choose to take over your site. The majority of crackers do this in order to obtain popularity within their group (or bragging rights if you will), and when one finds out it's possible, the majority of the others will follow in order to gain the same bragging rights. All courtesy of your website's vulnerabilities.

In general remember to just keep it simple, keep it light, and make values you store in a cookie obfuscated as well. If you want to store the ID of an item, name the cookie “session_id_for_user” and the ID the item_id multiplied by some integer and combination of letters/numbers.

Assume you sale Bourbon, and the George T. Stagg has an item_id of 15. The value you should store in the cookie should be b375gts. In other words, b(for bourbon), 375 (which is 15 x 25), and gts (the initials for George T Stagg).

Don't go using my example though. Be creative! Be obtrusive! The harder it is for a cracker to understand just exactly what your cookie values do, the harder it's going to be for them to realize that it's a worthless cookie to begin with.

How to properly validate users with cookies
One of the most popular things a developer wants to do anymore with cookies is allow for a returning user to have a more pleasant experience on their site by not needing to enter as much data to gain access. But since we've already stated that storing information used to authenticate a user is not only dangerous, but shouldn't be used, how should we go about granting users some sort of relief?

The answer, just like above, is an obfuscated encryption key that is used to lookup a user_id in a database, but requires the user to type in their password. Once the encryption key is used and the correct password entered, the current encrypted key is discarded, and a new one is generated.

While this may sound like it contradicts my statements earlier, it is in fact a legitimate method! How can this be? Well, first of all an encrypted hash generated from a combination of the user's browser agent (ie: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv: Gecko/2008121622 Ubuntu/8.04 (hardy) Firefox/3.0.5), a current timestamp (12388445), parts of the person's username and email address (smashed123 becomes maed23 and becomes omilom), all encrypted with SHA or MD5 (although there are numerous rumors about MD5 quickly becoming an insecure encryption). Now you have a nice, simple, and (for now) safe encryption. One that, even if decrypted, would be meaningless/useless to the cracker who attempts to hijack it.

And since we are still requiring the user to type in their password to the site in order to accurately authenticate them further, off-site attacks are even more less likely.

Even after all of this, I still do not use cookies for validating a user's login credentials. Unfortunately, I would rather suffer from losing a lazy user to giving an attacker even 1 iota of an advantage, no matter how good the methods appears.

Alternatives to using client-side cookies
There are of course alternatives to using cookies. Since I am more of a PHP fan, I will use PHP's server-side sessions as an example.

PHP stores sessions 3 ways: via cookies on the client site (which, if used, should be used in conjunction with the session.cookie_httponly setting to help reduce XSS vulnerability), on the filesystem of the server (usually located in /tmp with a hash value), or in the server's memory (not covered or recommended).

Since we're only looking at server-side methods, obviously that leaves server-side-based cookies. While this method is much more secure and reliable, it is still strongly recommended to follow the above guidelines when determining what sort of data to store inside of a session-based cookie.

Resources/Further Reading
Preventing CSRF and XSRF Attacks
The Felten and Zeller Paper (PDF)
Cross-site Scripting Prevention/Awareness

In conclusion, I hope this has been helpful in some way to anyone interested in security. While some of the above almost certainly can be improved on (and I truly hope the development community tries to assist in doing just that), I welcome any and all comments.

Wednesday, January 7, 2009

Facebook - You're killing me smalls!

About 4 months ago, I began making my transition from MySpace over to the Facebook realm. Until recently, I had the utmost respect for Facebook, it's interface, how it works, and all that jazz.

As I said, that is until recently.

That is until I started getting all sorts of emails out of the blue. "What the hell??", I asked myself. Was Facebook selling my account information to a 3rd party? Were they spamming me to make an extra buck?

The answer to all of these questions is "No" - at least not on purpose.

For any tech nerd out there who knows anything at all about Cookies, Sessions, and Security from building a website, you know some pretty common rules when it comes to user information.

1) Don't put any sensitive information in the cookie that you yourself wouldn't want the whole ever-loving world to know about.

2) Don't trust that cookie data. It should be there as a means of "Quick Lookup" ONLY!


Facebook, being the big powerhouse social networking site that they are, should of all people be more than aware of this. They should know that setting a cookie called "login_x" with my username (which is my email address too by the way) in there is a HUGE no-no! Worse yet, it's in plain text to boot!!

Well, maybe I'm over-reacting a little bit. I mean, it is quote/unquote encrypted with url encode!

COME ON GUYS! What the heck gives with this crap?

Given the fact that a LOT more Cookie Sniffing sites are coming out, wouldn't it be pretty obvious that this is yet another great way to have the security on your site compromised, or even worse, a great way for my personal information to get out?! A simple lookup of the email from google, and more than likely you're also going to know that Person's First and Last Name. With that, if the user, say, owns a few domain names? A quick whois on those domains and you now have their address and phone number too! All this information in a matter of seconds if you have written a script to just do the leg work for you, or a couple minutes if you're a teenager with a desire to be a haxx0r.

Now, in case there are any nay sayers out there who think that cookies are part of Satan's toolkit and that only a moron would store them, just hold on a second. Cookies can be good for a number of reasons, like storing a counter, the number of the last post you read, or something else insignificant that would just make your user's experience a tad bit better. Hell, maybe I'll even write a blog on the goods and bads of cookies. Either way, there are ways to use a cookie and there are ways NOT to use a cookie. For a good show in how not to, just use Facebook as an example.

Don't get me wrong, I still love Facebook as an application, and I'll still use it since I've put way too much time into it as it is. However, I for one am going to try and block any and all cookies from this moment on from Facebook.

I mean, MySpace isn't exactly the greatest site on the planet, but hey, at least they aren't storing sensitive information like this in plain text for the world to see...