Day 4: Avoid CSRF attack with ColdFusion 10
Day 4 for my ColdFusion 10 review, since last three days concentrating on all security enhancement. In previous two posts I have covered functions added in ColdFusion10 to avoid XSS attack. Now its time for CSRF (cross site request forgery). As per Wikipedia this is 909th most dangerous software bug ever found. And in normal project we always keep this door open and do not take precaution to restrict it. ColdFusion 10 make it really easy to avoid CSRF attack by adding two functions CSRFGenerateToken and CSRFVerifyToken. First function will generate different token for each session (or each request) which we need to pass with form submit and in action page you need to call CSRFVerifyToken function to make sure request coming through same session and it is not an forgery request. I used to create hash key with combination of session variable and page name which pass with form and in action page comparing same combination with hash key passed in form data.
Normally we think that only public page required more security as it is publicly visible and more chance to be attacked but private page where user need require to login are safe from hacker until someone theft password. If you are thinking so then CSRF attack will change your mind. As an example, Person X visiting one social site regularly and store his personal details, contact list in it. His pages are secure and only accessed with login detail but CSRF doesn't require to login detail to access it as request going to submit by Person X. How? Let's say Person Y (friend of X) invite him read any article on some website which has code for CSRF attack (mostly use image tag) for social website or simply send email with image tag which contain social site URL require to delete any content. As user open his email or website to read article will call delete contact link from his browser where X already logged in and his contact list will be deleted without his knowledge.
Below is example how we can use both coldfusion function to avoid CSRF attack.
<cfsilent> <cfset msg = ""> <cfif isDefined("url.deleteIt")> <!--- Perform delete operation ---> <cfif CSRFVerifyToken(url.token,'randomkeytogeneratetoken')> <cfset msg = "Contact Deleted."> <cfelse> <cfset msg = "CSRF attack"> </cfif> </cfif> </cfsilent> <html> <head></head> <body> <cfoutput><div style="color:##ff0000">#msg#</div> <form name="frmdeletecontact" action=""> Contact: <input type="text" name="contactid" value="10"/><br/> Token: <input type="text" name="token" size="50" value="#CSRFGenerateToken('randomkeytogeneratetoken',true)#"/><br/> <input type="submit" name="deleteIt" value="Delete Contact"> </form> </cfoutput> </body> </html>
You just need to create token using CSRFGenerateToken in form variable which will in hidden field (for testing purpose I have used text field) and once form submitted we need to verify it before processing. CSRFVerifyToken function will return true if token match and false if it forgery request.
CSRFGenerateToken function will take two arguments key and forcenew. Both are optional, key can be use to generate random token based on provided key text and second argument will force to generate new token on every request if passed as true. In case of False it will reuse previous token if already generated for same session. Avoid forcenew as true if you think that user might be using same page in multiple browser tab otherwise it will create new token for every page open and failed other than last open.
So it is easy to avoid attack just you need to decide you want to do that.