In order to prevent attacks, minimize their impact and remove points of attack, first of all, you have to fully understand the attack methods in order to find the correct countermeasures.
While the power of these commands is quite useful, extreme care should be taken when using them in a Rails based application. Usually, its just a bad idea.
def some_action
path = "#{Rails.root}/public/#{params[:user_path]}"
`ls #{path}`
end
def some_action
str = params[:user_input]
eval(str)
end
params[:user_path] => '; echo '' > ./config/database.yml'
solution => Use 'system' instead of ``=> system("ls", path)
params[:user_path] => "`echo '' > ./config/database.yml`"
solution => Validate input with RegExp, length, use params whitelist, etc...
Although the major issue with Mass Assignment has been fixed by default in base Rails specifically when generating new projects, it still applies to older and upgraded projects so it is important to understand the issue and to ensure that only attributes that are intended to be modifiable are exposed.
What are the potential problems of the code below?
def signup
@user = User.new(params[:user])
end
Use Strong Parameters.
def create
@user = User.create(user_params)
end
def user_params
params.require(:user).permit(:name, :age, ...)
end
Ruby on Rails is often used with an ORM called ActiveRecord. Many use cases protect for SQL Injection out of the box. However, it is possible to write code that allows for SQL Injection.
Why it is dangerous?
User.where("username = '#{params[:username]}' AND encrypted_password = '#{params[:password]}'")
What if we inject this into input?
Vasyl' OR 1=1)--
ActiveRecord =>User.where("username = ? AND encrypted_password = ?", params[:username], params[:password])
or
ActiveRecord =>User.where(username: params[:username], encrypted_password: params[:password])
By default, in Rails 3.0 protection against XSS comes as the default behavior.
Let's look at the code below
<%= raw @product.name %>
<%= @product.name.html_safe %>
<%= content_tag @product.name %>
< script type="text/javascript"> alert("Your hard disk is corrupted."); < /script >
or more private
< script> document.write(document.cookie); < /script >
<%= strip_tags("some<script>alert('hello')</script>") %>
<%= html_escape '< img src=x onerror=prompt(1) >' %>
<%= sanitize '< img src=x onerror=prompt(1) >' %>
<%= sanitize '< img src=x onerror=prompt(1) >', attributes: %w(src onerror) %>
Ruby on Rails has specific, built in support for CSRF tokens. Modern versions of Rails protect against CSRF attacks by default by including a token named authenticity_token within HTML responses. This token is also stored within the user’s session cookie - when a request is received by Rails it checks one against the other. If they do not match, an error is raised. To enable it, or ensure that it is enabled, find the base ApplicationController and look for a directive such as the following
class ApplicationController < ActionController::Base
protect_from_forgery
!! Rails does not provide CSRF protection for any HTTP GET request !!
Example
%a{href: "http://www.google.com/", onclick:"
var f = document.createElement('form');
var input = document.createElement('input');
input.type = 'hidden';
input.name = '_method';
input.value = 'delete';
f.appendChild(input);
f.style.display = 'none';
this.parentNode.appendChild(f);
f.method = 'POST';
f.action = '/products/12';
f.submit();
return false;
"}= 'Go to Google'
Occasionally, a need arises to share resources with another domain. For example, a file-upload function that sends data via an AJAX request to another domain.
The receiving site should whitelist only those domains allowed to make such requests. Whitelist in Rails
gem 'rack-cors', :require => 'rack/cors'
module Sample
class Application < Rails::Application
config.middleware.use Rack::Cors do
allow do
origins 'someserver.example.com'
resource %r{/users/\d+.json},
:headers => ['Origin', 'Accept', 'Content-Type'],
:methods => [:post, :get]
end
end
end
end
Use brakeman, an open source code analysis tool for Rails applications, to identify many potential issues.
Created by Vasyl Lasiak / @vlasiak