A few weeks ago my buddy Pete Freitag posted his ideas for improving security for CF10 (link) (or whatever they call the next version of ColdFusion). I thought it would be a good idea to post my own ideas.
It's not that I disagree with any of Pete's ideas, I think they are great, I just thought a few more might be good, and I think some of my priorities might be different.
Listed in no particular order
- Additional / Improved Encoders: Proper XSS protection requires escaping/encoding untrusted output that is rendered in the browser to prevent arbitrary code from running and being used to exploit other user. In the past ColdFusion developers have used the built in functions HTMLEditFormat(), XMLFormat(), URLEncodedFormat(), and JSStringFormat() for these purposes. And while they work in some situations, they were not designed for security purposes and cannot be used to cover all bases.
The ESAPI for JEE Project actually has all of these encoders available and they can be added to your current ColdFusion installations quite easily, but it would be ideal to have them built in.
It might also be nice to have encoder tags. Something like:
Again, this is currently available in the ESAPI project as a JSP tag library and can be used easily within ColdFusion now, but would be nice to have built in.
<cfimport taglib="esapi.tld" prefix="esapi">
- CSRF Protection: This is one that I have thought a lot about, but I struggle with thinking of the best way to implement it. If you don't know what a Cross-Site Request Forgery(CSRF or XSRF) attack is, then check out my posts on it here and here or Pete's post here.
What I am envisioning for CSRF protection is an easy way for developers to create a CSRF token, add it to a persistent scope, include it in a form post, and then verify it when appropriate.
So, for example, when a user is creating a form, it might look something like this:
<form action="index.cfm?event=deletePage" method="POST">
<cftoken scope="session" key="deletePage" />
<input type="hidden" name="pageid" value="#pageid#" />
Then when the page is rendered, that cftoken tag would automatically create a token/nonce, place it into session.tokens.deletePage and create a hidden form field inside of the <form> (with a default name of csrfToken).
Then, on the receiving end, either directly inline in the code, or perhaps in an AOP interceptor, have something like:
<cfset validToken = checkToken(form.csrfToken) />
I'm not sure if it is a good idea or not, I feel like it is, but I would like to see checkToken() have a second parameter for "throw".
<cfset validToken = checkToken(name=form.csrfToken, throw=true) />
If throw was set to "false" then the function would return a boolean. If throw was true, then it would throw an exception if the result was false.
- Additional Session SSL Token: This idea actually comes from Mary Jo Sminkey. We had several conversations about session management some time ago. The reason for this idea is because it is not a straight forward task to have a partially SSL protected site.
Let's look at a scenario to better describe this one. Say you have an ecommerce site that:
- Allows you to browse for merchandise
- Allows you to put merchandise into a cart and then purchase it online
- Allows you to edit your account settings
- Allows you to interact with other customers in a forum
Now in this situation above, you probably only want to perform items numbers 2 and 3 over SSL. Using SSL for the items 1 and 4 would work, but SSL is slower and has more overhead, so on a very active site, you'd probably want to limit the amount of time your users spending on an SSL connection.
Now switching between SSL and Non-SSL is pretty easy (http:// vs. https://). The hard part is dealing with your session token cookie(s).
Briefly, if your user's session token is compromised by a malicious user, their session can be hijacked and the hacker can impersonate the user on your site. To learn more about session hijacking, check out my posts here and here and here and here.
If you browse our hypothetical ecommerce site over a non-SSL connection, your session token is sent over EVERY unencrypted request. So it is being exposed to everyone who knows how to see it (which is more than you would guess). So if one of your users in a Starbucks surfing on their unprotected Wifi and looking at your commerce site, they are exposing their session token on every request while browsing for merchandise. Even a simpleton attacker could pluck that session token out of the air and hang onto it. Once your user decided on their purchase and logged in to complete it, the hacker would then browse to your site after manually creating a session token cookie to match the one he stole from your user. He would then be logged in to your site as your user. Yes, it really is that easy.
There are a few ways to stop this type of attack.
- You could simply place your whole site on SSL, but as we already discussed, this could cause performance problems.
- You could have the secure sections of the site be a separate ColdFusion application with a different session token.
- You could change the user's session token when they switch to SSL. But then you have to worry about transferring all of the user's data from the old session to the new one. You would also need to be able to switch it back if the user decided to Shop >> Login >> Shop some more >> Edit account settings >> Shop some more >> beging checkout >> change mind and shop more >> finally complete checkout. I know that's how I shop.
- When the user logs in and tries to access a secured part of the site (i.e. Checkout, account settings) then you have them re-authenticate. Upon re-authentication, you assign them a second token. This token, just like the session token, will be sent over EVERY request. But this new token will have the SECURE flag set on it, which means it will only be sent over every SSL request. On non-SSL requests, the browser will not send the new token, which means the attacker will never see it in-the-clear. Then on the server, for every request to a secured area you would check THAT token for authorization.
Option #4 above is what I mean when I say "Additional Session SSL Token". If there was some way to implement this type of functionality in ColdFusion, that would, I think, be a big benefit to sites that need to have only certain sections protected by SSL. I don't think the second token would need to be a whole second session scope, it would be more of a pseudo-session id for access control, although having a separate secureSession scope might work too, I'd have to give that some thought.
- Improved Logging: I don't think that many people realize how big a piece of a solid security plan logging is. Logging is a VERY important part of security. And the more logging you can do, the better. For those interested in PCI-DSS, you'll need to know that logging is a HUGE part of achieving that compliance.
We should be logging all sorts of activity that we probably are not. Login attempts, user activity, system changes, user account changes, administrator activity, and more. Logging serves a few purposes.
- Logs, of course, serve as a tool for debugging. Typically that is what we use them for, but many times only during development. Then when we put those apps into production, we minimize the amount of logging we do for performance reasons. It would be nice if we did not need to do that.
- Logging can help you discover where your application is being attacked. Web server logs can help with that, but custom logs can be a much better source of information. With proper logging and log analysis, you can detect attacks that you would not have otherwise known about.
- Logs can be offered as evidence to the authorities that you might call in the event of a breach. They can be used to help an investigation and could even help in the courtroom, if admissible.
Having improved logging, both in performance and features, would go a long way in the next version of ColdFusion, I think. Features like asynchronous logging in <cflog>, custom log locations, and maybe even some alerts for certain keywords or events would be great.
- invalidate() for CF Sessions: One of the AWESOME features of using JEE sessions in ColdFusion is the ability to instantly invalidate an existing session by calling invalidate() on it. This allows the developer to programatically invalidate a session so that it can no longer be used and without having to wait for the session to time out.
It would be nice to have the same ability with ColdFusion sessions.
- Easy session key rotation: There are certain times in our applications when a user should be given a new session instead of continuing the use of an old one (for example, after they move from an un-authenticated state to an authenticated state). Right now, there is not an easy way to do that. It would be nice to have a single function that can "rotate" their session to a new one. Essentially, it would need to:
- Create a new session
- Copy all the data from the old session to the new one
- Invalidate the old session (optionally)
- Invalidate or overwrite the old session cookies
- If old cookies are invalidated, create new session cookies
- Built-In Indirect Object Reference Map: One of the OWASP Top 10 security risks is insecure direct object reference. I have blogged about this risk here.
One way of solving the problem of insecure direct object reference is to use a Object Reference Map. An Object Reference Map is essentially a structure or hashmap that resides in memory, typically in the session scope. A direct reference to an object (i.e. fileid=12 or userid=1) can be mapped to an indirect reference to that object (i.e. a random number or UUID). Then any page that needs to reference that object will use the indirect reference instead of the direct one. On the back-end the system can link the indirect reference to the actual object through the reference map.
Having an object reference map and some utility functions to use with it could make this process much easier.
- Remove Insecure Defaults: I know backward compatibility is important to Adobe and that they don't want an upgrade to break existing installations, but insecure defaults are JUST BAD and they should be changed.
Some of the insecure defaults in ColdFusion are:
- Not having "Use UUID for cftoken " checked
- Not checking Enable Global Script Protection(Even though Global Script Protect offers very little protection, it's better than nothing, improving Global Script Protect as Pete suggested would help this suggestion carry more water.)
- Disable Flash Remoting by default.
- Make it easier to change the name of the Admin user
- Limit DSN default privileges to CRUD (Remove GRANT, REVOKE, etc)
- Other insecure defaults that may exist.
- Add iterations argument to hash(): There has been some discussion over whether or not iterating over password hashes will actually improve security or not. There are not many people with the skills to determine whether or not it really makes a difference(me included). But all of the guidance I have seen from "the experts" indicates that it should be done. What I propose here is to simply add a third, optional argument to the existing hash() function to indicate a number of times the hash should be iterated.
<cfset hashedPass = hash(password & salt, "SHA-256", 3) />
would be the same as doing this:
<cfset hashedPass = hash(hash(hash(password & salt, "SHA-256"), "sha-256"), "sha-256") />
Except that the actual code we would be using might be more like this:
<cfset hashedPass = hash(password & salt, "SHA-256", 75000) />
- Add a security course to the ColdFusion training and education curriculum: Training is an important part of a developers education and the existing security training resources fall short of what developers really need.
I can see that the course designers really tried to include security information in their courses, and I suspect that for the amount of time available in which the course it to be taught, that they could not have added much more. That is why I think a whole separate course should focus just on writing secure applications and on administering a secure server. This could be a 2-3 day course in the training materials and an add-on to the advanced education curriculum.