# in config/initializers/secret_token.rb
MySite::Application.config.secret_token = ENV['SECRET_TOKEN']# in config/application.rb file
config.filter_parameters += [:password, :password_confirm]Symbols are never garbage collected after they are created => denial of service (DOS)
Do a quick search for #to_sym and it’s less popular alias, #intern
E.g. : klass = params[:class].constantize or in a controller object = klass.new(params[:arg])
E.g. : Hey, nice forum!<script>alert("Guess who just got owned?")</script> so watch out where you're using .html_safe or better yet use Rails content_tag(:strong, user.name) for simple stuff.
<%= link_to "Homepage", user.homepage_url %>
# User sets homepage to "javascript:alert('Not again!')"
# => <a href="javascript:alert('Not again!')">Homepage</a># Bad
def emphasize(text)
"<em>#{text}</em>".html_safe
end
# Better
def safe_emphasize(text)
"<em>#{h text}</em>".html_safe
# or
content_tag :em, text
endThere's also the case with:
<%= link_to "Website", user.website %>
# when saving user.website make sure to escape it
# via html_escape or strip_tags.Some really bad code :
@accounts = Account.where("user_id = '#{params[:user_id]}'")Then a simple GET with user_id param set to ' OR 1 --
SELECT * FROM accounts WHERE user_id = '' OR 1 --'Some more bad code :
Order.calculate(:sum, params[:column])Something like salary) FROM users WHERE name = 'Bob'; as the column param and yikes !
Just use strong parameters in Rails 4 or the gem.
-
Don't store user IDs in a session cookie, even if it is signed or encrypted. Instead your session cookie should contain a randomized token that you also store with your user account model. This way you can terminate all sessions from your server and offer a "Sign out on all devices" feature to your users.
-
Only allow authenticated sessions over HTTPS. If possible at all, run your whole site over HTTPS only. If authenticated session cookies ever touch an unsecured connection, you are vulnerable to trivial packet sniffing and replay attacks, no matter which session store you use.
-
Make sure that session cookies are flagged as "secure only", meaning the browser won't send them over an unsecured connection. Remember that when a user enters your domain name into her address bar, the browser will open an unsecured connection by default. Even if your first response is a redirect to HTTPS, an existing session cookie will already have been sent over the plain wire unless the cookie was flagged as "secure only".
-
Make sure that session cookies are flagged as "HTTP only", preventing rogue Javascript embeds from trivially relaying the cookie to an attacker.
-
Innoculate browsers against SSL-stripping by delivering a HSTS security header with a long expiration date. Innoculated browsers will always request your site using HTTPS, even if the user just entered your domain name into her address bar (which would otherwise use an unsecured connection, thus revealing unsecured cookies and enabling SSL-stripping).
-
Make sure that links given out by your application default to the https:// schema to complicate SSL-stripping and not reveal unsecured session cookies. Remember to also fix this in e-mails that contain links into your application.
-
Hash each password with a randomized (per-user) salt to prevent the use of rainbow tables.
-
Choose a hashing algorithm with a work cost that can be increased over time (like bcrypt). Have some process in place to actually do increase the working cost over time. Re-hash passwords whenever a user signs in in order to update their cost.
-
Reconsider embedding remote Javascript, which is running remote code with full privilege inside your views. Prefer delivering Javascript libraries from your own application servers, or from a CDN that you control.
-
Use different session secrets for staging and production servers so sessions obtained on staging have no meaning when replayed against your production systems.
-
When implementing a flag to disable or "freeze" user accounts, don't only check it when signing in. Assume there are existing sessions out there and check the flag before every request. Also have tests in place that users cannot unfreeze their accounts by resetting their passwords or reusing their account activation link.
-
Take a hard look at other ways by which sessions can be gained. Account activation e-mails, password reset forms, help desks, callers claiming false identities are all examples of attacks that can sidestep the most fortified login code.