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
A hit
- 403