Other ways of protecting cookies - cookies

I've been thinking a lot about this recently, and I wanted to know if anyone has thought of/implemented any intuitive ways of securing cookies from manipulation. I've always used the "sign it with a hash and check against the hash later" approach, but it doesn't strike me as a particularly brilliant way of going about it, and just like all good programmers I want to find a better way of doing it.
As for why cookies specifically, well, I don't use native sessions - I hate to touch the filesystem. Cookies are a really quick way of storing data for later, and even with things such as user authentication I'll chuck the user ID in the cookie, perhaps along with the username/email and a signature, as well as a random hash for good measure.
What clever ways have you used to secure your cookie data?

Uh, you're storing the UserID in the cookie and giving the user access based on that value? You're asking for trouble. Server session based data implementations exist for a good security reason: Store a session identifier in the cookie and access the UserID from the record on the server where the client can't tamper with it.
Cookie security to protect against client tampering is pretty much a lost cause. Given enough time, someone will figure out how to crack it. Don't give clients that opportunity. Cookie security's only purpose is to make sure client's cookies aren't stolen.

Signing the cookie with a HMAC is a perfectly reasonable way to do this. HMAC essentially rolls a secret key known only by your server into the hash, so even someone who knows the algorithm can't generate a HMAC that will be recognized as valid without knowing the key. Just using a plain old hash is trivially bypassable because the attacker can generate valid hashes of their own data, and all the "salt" in the ocean won't fix that.
Even if you used a session ID instead of storing meaningful values, you still would have to be careful that an attacker couldn't predict another valid session ID, and send that to you instead, thus hijacking the other user's session. I believe there was an actual exploit against Hotmail that worked this way.
Encrypting the cookie only helps you if there's something in there you don't want the user to see. Even worse, encryption without an HMAC gives a false sense of security because a cookie that is merely encrypted is still vulnerable to manipulation of the ciphertext to change parts of the plaintext.
So in summary, don't just hash it, use an HMAC!

With hashing you need to be very careful that you have included a salt, otherwise it can be trivial to determine a matching hash.
Thus, to protect against accidents, it's often appropriate to also encrypt the cookie.
-- edit
You may also like to learn about 'HTTPOnly' cookies: http://www.owasp.org/index.php/HTTPOnly

On the Security Now podcast (i forgot which episode), Steve Gibson talks about doing something like this and i think the system he recommended was to make the contents of the cookie a good hash, then make that hash a key in your local database where the value(s) is(are) all of the info that it needs to store.

Related

Passing a serialized object through a URL

I am serializing/pickling an object, encoding it as a compressed string, and passing it as a parameter in the URL for the next page to deserialize. My web app does not have a database; I am doing this because the app gets data from external web services, which are slow.
Is this acceptable practice? Is this a security risk? Is there a way to make this secure?
If you need to share data between views, do it with the session. That's what sessions are made for. Session info is stored in the database by default, but it doesn't have to be, you can also use the filesystem, some caching system (memcache, Redis, etc), or signed-cookies (Django 1.4+ only).
See:
Configuring the Session Engine
How to Use Sessions
Is this a security risk?
If the serialisation you are using is pickle then yes that is definitely a problem, as alluded to on the doc:
Never unpickle data received from an untrusted or unauthenticated source
Use a form of serialisation designed only to hold safe static values (eg JSON).
You can protect a value that you send to the client side from tampering by signing it with a MAC, eg using hmac. You may need to consider adding other properties to the MAC-signed data such as username or timestamp, to prevent signed data blocks being freely interchangeable, if that's a threat to whatever integrity you are trying to achieve.
If you also need to protect the value from being viewed and interpreted by the client side user you would need to use an encryption algorithm (eg AES - not part of stdlib) in addition to the signing.
(I still wouldn't personally trust a MAC-signed and encrypted pickle. Even though it would need the server-side secret to be leaked to make it exploitable, you don't really want an information-leakage vulnerability to escalate to an arbitrary-code-execution vulnerability, which is what pickle represents.)
It is not the best option, since URL parameter fields will show in server logs. You're
probably better of sending data with POST method or better yet, creating a rudimentary database (if you don't have access to anything else, use Sqlite) and just pass the ID to the next screen.

Encrypting using user's password

I want to encrypt a given data using the log-in user's password on a windows machine using WINAPI. I've been looking for a function that uses a token (or something like that) but I couldn't find one.
Does anyone know how to do that?
Thanks! :-)
The Windows Data Protection API sounds like what you need. The CryptProtectData and CryptUnprotectData functions perform encryption using the logon credentials of the current user.
I had written this answer earlier but then reconsidered, since I hadn't heard of the DPAPI before. However, upon some further consideration, I'd like to offer the following opinion. The important preface here is that it all depends on your needs, though. Two conflicting possibilities come to mind:
You want to offer your user complete protection and encryption that the user can trust only she will be able to decrypt, no matter the circumstances.
You're an enterprise IT manager and have all employees on a tight leash. You want them to encrypt business data as part of their workflow so that they cannot see each other's data, but the admins can happily read everyone's data.
If you're in situation (2), then stop reading now and go with DPAPI, which is well suited to that case. If you prefer scenario (1), then read my original answer below.
That's probably not a good idea. Here's why:
The actual password will not be stored on the system (unless you have Windows 3.11 or something like that). Instead, only a hash of the password will be stored, and at login time the password that the user enters is hashed and compared to the stored hash.
So at best you could retrieve the stored hash from the system (if you have admin rights, say). However, if that's the only datum you can go on, then any encryption key you make will be derived from that hash, rather than from the actual password. Thus anyone with access to the system could get to the stored hash, and from there derive the encryption key with relative ease.
In short, don't. Ask the user for a dedicated, fresh password for your data and use it for only that.
use Kerberos (Linux-based authentication server, or other servers using Kerberos) / LDAP framework (Windows server) instead of designing your own login algorithm.
Windows Platform SDK & 3rd-party libraries have connectors with these frameworks.
More information in MSDN about Kerberos: http://msdn.microsoft.com/en-us/library/ff649429.aspx
How to safely store a password
Win32 bcrypt: http://msdn.microsoft.com/en-us/library/aa375421%28v=vs.85%29.aspx

long term cookie

I'm looking for a way for users to be able to connect to my application easily, but rarely. What I want to do is be able to store a cookie with a 1 year life on the user's computer. If they access the website while the cookie is active, they will be automatically logged in.
My proposed solution is this: Upon initial login, create a cookie with the users IP address, last login date, and random number, all hashed together. I will also store their user ID and IP address in cookies as well. These values will also be stored in the database. If after a few months they access the site again, the IP address, ID, and hash match the values in the database, then they are automatically logged in. A new hash is computed. If any of these don't match, then the user will be prompted to log in again.
Are there any obvious security flaws to this design? I am not worried about IP addresses changing, this will be for professors on a university campus.
Thanks in advance,
--Dave
Your question does not make it clear how this system is any different from any other standard long-life cookie. Those are used across the web without significant security problems, so I see no reason you could not also use a cookie in a similar fashion.
Are there any obvious security flaws
to this design?
No.
I would say it's definitely a security risk if someone figures out the system. To be honest, I would rethink that setup, at least the storing it in a database part. Not to mention the fact that cookies very rarely stay on someone's computer for a year anyway, most people clean them far more frequently.
But since you asked, creating it is pretty easy:
$expire = time()+(60*60*24*365);
setcookie("login", "mycookie", $expire, "", "yoursite.com" );
Instead of "mycookie" you could insert that token you were talking about. Hope that helps a little.

In a website with no users, are cookies the only way to prevent people from repeating actions?

I'm creating a website and I don't want to have user/membership.
However, people using the site can do things like vote and flag questionable content. Is the only way to identify and prevent users from doing this repeatedly by using cookies?
I realize a user can just clear their cookies but I can't think of another way.
Suggestions for this scenario?
Well you could map a cookie + ip-adress in a datarecord in your database. To identify the user. So if the ip exists in the database, you simply just add the cookie, but check the cookie first to avoid unessesary database calls.
This is not optimal though, since schools etc might have the same ips on a lot of computers.
You can always just adapt openid!
Marko & Visage are correct,
Just to add though, you might want to store each vote with the timestamp,IP, etc... so at least if someone does try to "game" your site, you'd be able to rollback sets of votes made from the same location or within a very short amount of time (i.e. from a bot)
+1 To all that others have already said. Here's another middle-way idea:
Use cookies as primary means of limiting voting. If a cookie is not found, check the IP address. Allow no more than, say, 1 vote per 5 minutes from the same IP.
Cookies are not enough, as you said it could be cleared/expired.
IP address tracking is also not an option because of DHCP and firewalls.
The only thing that is ~100% sure is users, but then again, one person can register multiple accounts.
I'll go with cookies, as the simplest ant least obtrusive way. If someone really wants to play the system, he will find a way whatever you try to prevent it.
Even with membership a user can register multiple times and vote.
Cookies are one way to handle this but people who know that they can delete cookie can vote again.
You can catch the IP of the voter and restrict based on that. But many people will have same IP.
Sadly there is no other way.
Yes, you are right.
HTTP is stateless, so there is no way of determining if the origin of a request you receive now is the same or different to the origin of a request you received, say, 5 minutes ago.
Cookies are the only way around this. Even server side sessions rely on cookies to maintain session identity across requests (ignoring the security nightmare of passing the sesison ID in the URL, which anyone with malicious intent can sidestep trivially).
There will always be people gaming the system if it suits them. Moreover, if you make it such that you don't need cookies at all you'd be open to very simple attacks.
I think you'll want to consider ways to increase the economic cost of users operating under a cloud of suspicion.
For example, if a user with the same cookie tries to re-submit the vote, that can obviously be stopped easily.
If a user with a different cookie but from the same IP does the same thing, it could be coming from a proxy/firewall so you may want to be cautious and force them to do something extra, like a simple CAPTCHA. Once they've done this, if they behave properly nothing new is required as long as their new cookie stays with them.
This implies that people without cookies can still participate, but they have to re-enter the letter sequence or whatever each time. A hassle, but they're likely used to sites not working without cookies. They'd be able to make an exception if required.
You really won't be able to deal with users sitting over a pool of IPs (real or otherwise) and exploiting new and dynamic attack vectors on your site. In that case, their economic investment will be more than yours and, frankly, you'll lose. At that point, you're just competing to maintain the rules of your system. That's when you should explore requiring signup/email/mobile/SMS confirmation to up the ante.
You can add GET variables and URL parts to serve as cookies - some sites do that to allow logins and/or tracking when cookies are disabled. Generate the part using source IP and user agent string, for example.
site.com/vote?cookie=123456
site.com/vote/cookie123456

comparison of ways to maintain state

There are various ways to maintain user state using in web development.
These are the ones that I can think of right now:
Query String
Cookies
Form Methods (Get and Post)
Viewstate (ASP.NET only I guess)
Session (InProc Web server)
Session (Dedicated web server)
Session (Database)
Local Persistence (Google Gears) (thanks Steve Moyer)
etc.
I know that each method has its own advantages and disadvantages like cookies not being secure and QueryString having a length limit and being plain ugly to look at! ;)
But, when designing a web application I am always confused as to what methods to use for what application or what methods to avoid.
What I would like to know is what method(s) do you generally use and would recommend or more interestingly which of these methods would you like to avoid in certain scenarios and why?
While this is a very complicated question to answer, I have a few quick-bite things I think about when considering implementing state.
Query string state is only useful for the most basic tasks -- e.g., maintaining the position of a user within a wizard, perhaps, or providing a path to redirect the user to after they complete a given task (e.g., logging in). Otherwise, query string state is horribly insecure, difficult to implement, and in order to do it justice, it needs to be tied to some server-side state machine by containing a key to tie the client to the server's maintained state for that client.
Cookie state is more or less the same -- it's just fancier than query string state. But it's still totally maintained on the client side unless the data in the cookie is a key to tie the client to some server-side state machine.
Form method state is again similar -- it's useful for hiding fields that tie a given form to some bit of data on the back end (e.g., "this user is editing record #512, so the form will contain a hidden input with the value 512"). It's not useful for much else, and again, is just another implementation of the same idea behind query string and cookie state.
Session state (any of the ways you describe) are all great, since they're infinitely extensible and can handle anything your chosen programming language can handle. The first caveat is that there needs to be a key in the client's hand to tie that client to its state being stored on the server; this is where most web frameworks provide either a cookie-based or query string-based key back to the client. (Almost every modern one uses cookies, but falls back on query strings if cookies aren't enabled.) The second caveat is that you need to put some though into how you're storing your state... will you put it in a database? Does your web framework handle it entirely for you? Again, most modern web frameworks take the work out of this, and for me to go about implementing my own state machine, I need a very good reason... otherwise, I'm likely to create security holes and functionality breakage that's been hashed out over time in any of the mature frameworks.
So I guess I can't really imagine not wanting to use session-based state for anything but the most trivial reason.
Security is also an issue; values in the query string or form fields can be trivially changed by the user. User authentication should be saved either in an encrypted or tamper-evident cookie or in the server-side session. Keeping track of values passed in a form as a user completes a process, like a site sign-up, well, that can probably be kept in hidden form fields.
The nice (and sometimes dangerous) thing, though, about the query string is that the state can be picked up by anyone who clicks on a link. As mentioned above, this is dangerous if it gives the user some authorization they shouldn't have. It's nice, though, for showing your friends something you found on the site.
With the increasing use of Web 2.0, I think there are two important methods missing from your list:
8 AJAX applications - since the page doesn't reload and there is no page to page navigation, state isn't an issue (but persisting user data must use the asynchronous XML calls).
9 Local persistence - Browser-based applications can persist their user data and state to the local hard drive using libraries such as Google Gears.
As for which one is best, I think they all have their place, but the Query String method is problematic for search engines.
Personally, since almost all of my web development is in PHP, I use PHP's session handlers.
Sessions are the most flexible, in my experience: they're normally faster than db accesses, and the cookies they generate die when the browser closes (by default).
Avoid InProc if you plan to host your website on a cheap-n-cheerful host like webhost4life. I've learnt the hard way that because their systems are over subscribed, they recycle the applications very frequently which causes your session to get lost. Very annoying.
Their suggestion is to use StateServer which is fine except you have to serialise/deserialise the session eash post back. I love objects and my web app is full of them. I'm concerned about performance when switching to StateServer. I need to refactor to only put the stuff I really need in the session.
Wish I'd know that before I started...
Cheers, Rob.
Be careful what state you store client side (query strings, form fields, cookies). Anything security-related should not be stored client-side, except maybe a session identifier if it is reasonably obscured and hard to guess. There are too many websites that have settings like "authenticated=true" and store those in a cookie or query string or hidden form field. It is trivial for a user to bypass something like that. Remember that ANY input coming from a client could have been tampered with and should not be trusted.
Signed Cookies linked to some sort of database store when you need to grab data. There's no reason to be storing data on the client side if you have a connected back-end; you're just looking for trouble if this is a public facing website.
It's not some much a question of what to use & what to avoid, but when to use which. Each has a particular circumstances when it is the best, and a different circumstance when it's the worst.
The deciding factor is generally lifetime of the data. Session state lives longer than form fields, and so on.