Easy CSRF Protection on AppEngine

As mentioned in my previous post, this blog runs on AppEngine, and is based on Nick Johnson's Bloggart software. Making a few tweaks to the original application, I noticed that the administration interface does not have CSRF protection. Since I wouldn't be too happy about rogue posts, or people randomly deleting my blog posts, I decided to add that, and came up with a fairly generic, easy library to implement CSRF protection for AppEngine apps, based on this little module that is part of the Google OAuth libraries.

I present to you: xsrfutil.py. It's a very simple library that should be fairly easy to plug into existing AppEngine applications in order to protect them from CSRF attacks. Using it requires two steps:

  • Adding the @xsrfutil.xsrf_protect decorator to the handler functions you'd like to protect,
  • and adding the tokens to your forms.

Here is an example for the first step. Let's assume you have a handler that allows the administrator to delete comments:

class DeleteCommentHandler(basehandler.BaseHandler):   @xsrfutil.xsrf_protect   def post(self, id):     comment = models.Comment.get_by_id(id)     comment.delete()     self.render('admin/deleted.html') app = webapp2.WSGIApplication([     ('/admin/comments/delete/(.*)', DeleteCommentHandler)])

The xsrf_protect ...


I've been wanting to start a blog for some time, mostly for ranting about random stuff, and documenting a couple of security bugs that are pretty well known, but really nowhere described in appropriate detail. Well, finally, here it is - my blog.

I decided to run my own blogging software on AppEngine. Really, don't ask my why - it actually turned out to be quite some work, and the software is not nearly as powerful as something like WordPress or Blogger. Then again, I like flexibility, and being able to add random stuff.

The blog is based on Nick Johnson's Bloggart. But honestly, there's not too much left from the original version. I moved away from the deprecated python runtime, to python27. Also, I changed pretty much the entire way static pages and caching is implemented, because it was a bit too complicated for me. My version might be a tad slower (not much though), but much easier to understand and maintain. If you're interested, the code is on Github.