Protect Your Cookies from XSS
One of the more favorite attacks with Cross Site-Scripting (XSS) is to hijack another user's session. This attack is known as session hijacking (shocking!). When it boils down to it, session hijacking is no different than you using a public computer and forgetting to sign-out and another person sending email using your account. In our college computer labs it was a fun way to mess with other people.
Out on the interwebs session hijacking will occur via an XSS exploit. Somehow an attacker is able to inject a piece of malicious JavaScript code onto your site, and that JavaScript contains code to read the user's cookies and dump the information onto another server controlled by the attacker.
So you can impersonate another user. Big deal? Yes, that is a big deal. Here is some fun an attacker can have when they are impersonating another user.
- Send an email to the victim's boss telling the boss to piss off
- Attempt to logon to a bank's website. The bank sends a reset password link via email. The attacker is logged into the victim's email account. The attacker can probably log into the victim's bank account.
- Buy stuff from an online site
- Acquire information about the victim's life so they can pretend to be them in real life.
There are number of ways to prevent a user's session from being hijacked.
- Keep the session timeout low, say 10 or 20 minutes. This is fine for banks, a pain in the ass for other sites.
- Require two-factor authentication. This is becoming more common with social media, banking, and email accounts.
- Encode/Decode all text coming to/from back-end services to ensure XSS is not allowed into your system.
Those are all great solutions, and depending on your needs should be implemented. But those take time and money to implement.
The first step to ensure a user's cookies don't get exposed to JavaScript is to mark them as httponly. This tells the browser the cookie is not allowed to be accessed via JavaScript. This assume's the user is using a modern web browser (Chrome, IE 7+, Firefox, Safari, etc.).
For ASP.NET web sites this feature is enabled by default. It was added as part of the .NET 2.0 release, or as I like to call it, the release that gave .NET generics and made it awesome.
Side Note: a lot of security features have been part of .NET a long time. In this case it has been part of .NET since 2005 (damn!). It really pays to read up on how the .NET framework can help us help ourselves.
If you want to make it specific it is easy to do.
<system.web>
<httpCookies httpOnlyCookies="true" requireSSL="true" />
</system.web>
What this does:
HttpOnly – it will not allow JavaScript to access cookies sent down from the server. By default this is set to true. I'm setting it in this example to be explicit.
RequireSSL – It will only allow cookies sent from the server to be sent via https. RequireSSL is a bit of a misnomer. It is more like RequireSSL or TLS, whichever is enabled on your webserver. Let's say the majority of your traffic is done via https. If you are somehow forced over to the http side the cookies will not come along. Anyone packet sniffing the network could read the cookie via http but not https.
I recommend setting this at the web.config file unless it is absolutely necessary. Requiring all the programmers on your team to remember to set these values each time they need to create a cookie is just asking for trouble. We're human, you'll forget, they'll forget, everyone will forget until a bug comes up.
So there it is, an easy layer of defense to make your site more secure. Keep your JavaScript from accessing the session cookies created by your site with a simple configuration change. By no means is this solution 100% perfect. The idea here is to create another layer of security to make it more difficult for attackers to hijack a session. You don't have to be faster than the bear, you only have to be faster than the person standing next to you.