Skip to content

Instantly share code, notes, and snippets.

@vishaltelangre
Last active December 15, 2015 15:49
Show Gist options
  • Save vishaltelangre/5284933 to your computer and use it in GitHub Desktop.
Save vishaltelangre/5284933 to your computer and use it in GitHub Desktop.
Rails 3 Insecure Defaults (Notes)

Rails 3 Insecure Defaults

By default Rails does not provide CSRF protection for any HTTP GET request
match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
  • Best Practice:
    • Either specify HTTP verbs or use via: :all when adding routes with #match

/^[a-z ]+$/i =~ "Joe User"
# => 0 # Match

/^[a-z ]+$/i =~ " '); -- foo"
# => nil # No match

/^[a-z ]+$/i =~ "a\n '); -- foo"
# => 0 # Match
  • Best Practice:
    • Whenver possible, use \A and \z to anchor regular expressions instead of ^ and $.

Disallow site being rendered in a frame or iframe on sites that it doesn't control.
  • Best Practice:
    • Use the secure_headers RubyGem by Twitter to add an X-Frame-Options header with the value of SAMEORIGIN or DENY.

    • or send this with header:

      X-Frame-Options: SAMEORIGIN
    • Use @rkh's rack-protection instead of secure_headers as provides more protection. +

      One thing secure_headers provides that rack-protection does not is Content Security Policy setup. Among other things, this gives you the ability to let browsers know they are not permitted to run inline javascript on the page. This drastically reduces the vector for script injection for attacks.


WebRick
  • Binding to 127.0.0.1 is a safer default than 0.0.0.0 in all Rails environments.
  • The Fix:
    • Rails already provides a --binding option to change the IP address that the server listens on. The default should be changed from 0.0.0.0 to 127.0.0.1. Developers who need to bind to other interfaces in production can make that change in their deployment configurations.

Versioned Secret Tokens
WebStore::Application.config.secret_token = '4f06a7a…72489780f'
  • Unfortunately, Rails falls flat in dealing with these secret token. The secret_token.rb file ends up checked into version control, and copied to GitHub, CI servers and every developer's laptop.
  • Best Practice:
    • Use a different secret token in each environment. Inject it via an ENV var into the application. As an alternative, symlink the production secret token in during deployment.

Offsite Redirects
class SignupsController < ApplicationController
  def create
    # ...
    if params[:destination].present?
      redirect_to params[:destination]
    else
      redirect_to dashboard_path
    end
  end
end
https://example.com/sessions/new?destination=http://evil.com/
  • Best Practice:
    • When passing a hash to #redirect_to, use the only_path: true option to limit the redirect to the current host:

      ```ruby
      redirect_to params.merge(only_path: true)
      ```
      
    • When passing a string, you can parse it an extract the path:

      ```ruby
      redirect_to URI.parse(params[:destination]).path
      ```
      

Cross Site Scripting (XSS) Via link_to
<%= link_to "Homepage", user.homepage_url %>
user.homepage_url = "javascript:alert('hello')"
<a href="javascript:alert('hello')">Homepage</a>
Rails SQL Injections
YAML Deserialization (remote code execution (RCE) fiasco)
class User < ActiveRecord::Base
serialize :preferences
store :theme, accessors: [ :color, :bgcolor ]
end
  • Best Practice:
    • Use the JSON serialization format instead of YAML for #serialize and #store:

      ```ruby
      class User < ActiveRecord::Base
        serialize :preferences, JSON
        store :theme, accessors: [ :color, :bgcolor ], coder: JSON
      end
      ```
      

Run "rails_best_practices" gem, as picks up a lot of the points mentioned automatically.
Run "cane" gem as a general code quality analyser.
Run "brakeman" to find security holes is software.

Sessions
  • By default, Ruby on Rails uses a Cookie based session store. What that means is that unless you change something, the session will not expire on the server. That means that some default applications may be vulnerable to replay attacks. It also means that sensitive information should never be put in the session.
  • Best Practice:
    • Use a database based session, which thankfully is very easy with Rails:

      Project::Application.config.session_store :active_record_store

Mass Assignment and Strong Parameters
  • Use the strong_parameters gem with Rails 3.x

Sensitive Files
  • Many Ruby on Rails apps are open source and hosted on publicly available source code repositories. Whether that is the case or the code is committed to a corporate source control system, there are certain files that should be either excluded or carefully managed.
      /config/database.yml                 -  May contain production credentials.
      /config/initializers/secret_token.rb -  Contains a secret used to hash session cookie.
      /db/seeds.rb                         -  May contain seed data including bootstrap admin user.
      /db/development.sqlite3              -  May contain real data.
    

REFERENCES:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment