The Hitchhiker's Guide to Brakeman

def brakeman

Brakeman is an open source static analysis tool which checks Ruby on Rails applications for security vulnerabilities.

 

Rails Specific

Looks for Ruby, Rails and web vulnerabilities

Static

Does not run the application

[my-rails-app] $ gem install brakeman
[my-rails-app] $ brakeman
[my-rails-app] $ brakeman -o output_file

Running a Scan

Warning Types

Mass Assignment

# Instead of this
user = User.new
user.name = params[:user][:name]
user.email = params[:user][:email]

# I can do this
User.new(params[:user])
Parameters: {
  user: {
    name: 'Athur Dent',
    email: 'dent@arthur.com'
  }
}
User.new(params[:user])
Parameters: {
  user: {
    name: 'Athur Dent',
    email: 'dent@arthur.com',
    admin: true
  }
}

How to Solve?

Controller

Strong Parameters (Rails 4+ only)

class UsersController < ApplicationController
  def create
    @user = User.new(user_params)

    # ...
  end


  private

  def user_params
    params.require(:user).permit(:name, :email)
  end
end
Parameters: {
  "user" => {
    "name" => "Arthur Dent",
    "email" => "dent@arthurdent.com",
    "admin"=>"1"
  },
  "commit"=>"Create User"
}
Unpermitted parameter: :admin

Model

attr_accessible (Rails < 4 only)

class User < ActiveRecord::Base
  attr_accessible :name, :email
end
irb(main):001:0> User.new admin: true
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: admin

Cross Site Scripting (XSS)

Rails Escapes Templates by Default

Be VERY careful with html_safe

Marks a string as trusted safe. It will be inserted into HTML with no additional escaping performed. It is your responsibilty to ensure that the string contains no malicious content. It should never be called on user input.

# GOOD
<%= raw glyphicon('search') %>

# VERY BAD
<%= raw user.name %>

SQL Injection

ActiveRecord

Be VERY careful with string interpolation

# BAD, VULNERABLE CODE
User.where("name LIKE '%#{params[:name]}%'")

# GOOD
User.where("name LIKE '%?%'", params[:name])

# BETTER
User.where("name LIKE '%:name%'", name: params[:name])

Learn more about SQL Injection on Rails Apps

rails-sqli.org

File Access

Command Injection

`rm -rf /my/awesome/dir/#{file_path}`

file_path = "../*" #=> PWNED
file_path = "* && my-evil-command" #=> PWNED
command = "rm -rf /my/awesome/dir/my-cool-file.txt"
system command

Remote Code Execution

General Recommendations

NEVER trust user input

Don't limit input possibility by the UI

Don't limit security by Brakeman reports

That's It!

A hit

By Ruan Brandão