CSRF: Avoid security holes in your Drupal forms.
Table of Contents
While everyone is now aware of SQL injections and 99% of Drupal developers now use placeholders in their db queries, some of other important security aspects are often forgotten.
Today I've encountered another example of CSRF (Cross-site request forgery in Wikipedia) in Drupal contributed module.
It's so easy to create a CSRF security hole while creating a module. Here is the short description of the issue.
Some module manipulates the list of custom items, say, user can create lots of 'fruit' items which are shown to user in a Drupal theme_table. It's pretty obvious that website admin needs to have an ability delete each fruit, so what module developer usually does to provide such option? Right, he creates "Delete" link for each fruit and puts it next to each fruit item.
When website admin clicks the link, it leads him to /yourmodule/fruit/343/delete and fruit_delete($id) function in the example module is called. The function certainly is called only after access check in menu access callback, so the code knows that the user deleting the fruit is the fruit owner. After that the user is redirected back to list of fruits, with 'the fruit was deleted successfully' message.
That's so easy - how can we have a security issue here? Yes, we can!
and when viewing the image (well, it doesn't look like image.. it looks like broken image icon with alt text), the admin gets into trouble and deletes his own fruit without even noticing that.
What can be done to avoid that? Use form confirmations and/or form tokens. Token is a special parameter added to request, that gives Drupal an idea that the link was generated by Drupal, for this specific user viewing the website.
Drupal adds token to all forms it generates, so this protection works invisibly for developers.
And that is why we have "Are you sure you want to delete this item?" confirmation forms everywhere in Drupal core and modules.
So, the general idea is: do not allow GET requests to modify your data, and use token protection when generating links/forms manually!
You need to make user to use POST request to website to delete or edit something.
Now, read official d.org docs: http://drupal.org/node/178896 and always use form confirmations (or tokens) in your code!