CSRF, what does it mean, and what is the best way to prevent it?
I am writing this, because at this time it seems that twitter is vulnerable to the simplest of CSRF attacks. If you know what a CSRF is and how to avoid it on your code, you will probably not learn anything new, but you may have valuable input.
CSRF simply put stands for "Cross site request forgery". What that means is that some other website told your browser to do a request that would cause an undesirable action at the attacked website.
For example, consider the image tag:
<img src="http://twitter.com/newtweet?text=hello+world" alt="you've been hacked!" >
While I don't use twitter, and I don't know the exact variables needed to send a CSRF, this is basically all a CSRF needs. If you happen to be logged into twitter, this code would cause your browser to try to retrieve an image at "http://twitter.com/newtweet?text=hello+world" including all the browser cookies that would tell twitter that you are logged in, as well as post the 'hello world' to your twitter feed.
CSRF is simple to execute, but also relatively simple to prevent too. To avoid the worm type of CSRF right now, just forcing the user's id to be passed in as well, and to match the userid in the browser cookie would prevent all the current worm problems.
However If I didn't like you, and sent you an email sending you to a webpage that had the following image tag, I would still get you to post the 'hello world' message:
<img src="http://twitter.com/newtweet?text=hello+world&twit_id=1337" alt="you've been hacked!" >
The best way to prevent CSRF is to include a 'nonce'. A nonce is just a simple random number id that your server remembers and requires before a post is allowed.
CPAN is not much help at this time, I only found one module for CGI::Application that mentioned CSRF. http://search.cpan.org/~holly/CGI-Application-Plugin-ProtectCSRF-1.01/ . There were several others that mentioned nonces, but none appeared to be something that could be simply plugged into a web application.
How you remember a nonce between drawing the webpage and receiving the submission is left as an exercise for the reader at this time, but depending on your application, storing a nonce in the database attached to the user's record (one per user) would work, but would of course increase the writes to your database. One way to minimize writing load on your server is only to update the nonce each time the user posts new data to the application.This way you only update the nonce when already writing to the database, and can reject the submission if the nonce doesn't properly come back to the webserver via the form submission.