rails security review checklist
January 27, 2010
I’m reviewing the security of a web app built with Ruby on Rails, so I put together a checklist for a security audit. This isn’t a bank or high security situation, but there were a number of engineers and quite a bit of open source code, so I thought a few checks were in order.
Here’s the list I came up with that I thought other folks might appreciate as a starting point (special thanks to the sfruby list, Mike Gunderloy, and Scott Bronson for feedback):
0) Make sure your Rails and gems are up to date for latest security patches (see rails security mailing list for recent advisory notes)
1) Active Record audit:
A) SQL injection:
(i) whole word search for “find”, “first”, and “all” then visually inspect all instances of ActiveRecord find calls for potential SQL injection vulnerability (also search for “sql” not whole work search to find find_by_sql and “execute” to find cases where raw sql is executed.
(ii) search your models for “named_scope” and check :conditions
B) check for mass assignment Either disable mass assignment as Eric suggests in his article, or audit its use. If doing an audit, check every model to make sure it declares which attributes are settable with attr_accessible. (While attr_protected may technically work, a white list approach is recommended by security experts and the rails security advisory on this topic)
2) Scripting attack: search all eRB files for <%= and ensure that if dynamically generated text was originally entered by the user, it is HTML escaped. Consider rails_xss
3) Secure Access: If some of the site does not have public access, check controllers and ensure that public actions are specifically allowed and that protected access is the default
4) search for “eval” (whole word) and verify that usages are safe
5) search for “forgery” (not whole word), make sure that
config.action_controller.allow_forgery_protection = false
is only disabled in test config
protect_from_forgery should be in the ApplicationController, unless there is a good reason for it not to be
6) check user auth and review that controller actions are limited to expected use
7) passwords: not saved as clear-text in the db, not logged
8) check that private data is not stored in cookies