ruby on rails security updated (rails 3) at railswaycon

24
Ruby on Rails Security Updated Heiko Webers, bauland42

Upload: heikowebers

Post on 14-Jul-2015

21.152 views

Category:

Technology


3 download

TRANSCRIPT

Ruby on Rails Security Updated

Heiko Webers, bauland42

Heiko Webers

CEO of bauland42: Secure and innovative web applications, security code audits:http://www.bauland42.de http://www.werkstatt42.de

Ruby on Rails Security Project: Blog and Book at http://www.rorsecurity.info

Cross-Site Scripting in Rails 3

Before: <%= h @project.name %>@project.name #=> <script>h(@project.name) #=> &lt;script&gt;

After: <%= @project.name %>

Unless you want to allow HTML/JS: <%= raw @project.name %>

Cross-Site Scripting in Rails 3

@project.name.html_safe? #=> false h(@project.name).html_safe? #=> true link_to(...).html_safe? #=> true "<br />".html_safe # => "<br />"

4

Cross-Site Scripting in Rails 3

safe + safe = safe safe.concat(safe) = safe (safe << safe) = safe

safe + unsafe = unsafe...

5

Cross-Site Scripting in Rails 3

String interpolation <%= "#{link_to(@product.title, @product)}

#{link_to(@product.title, @product)}" %> Deliberately unsafe

6

Cross-Site Scripting in Rails 3

textilize() and simple_format() do not return safe stringstextilize(‘*bold*‘) #=><strong>bold</strong>

<%= textilize(@product.description) %> NO <%=raw textilize(@product.description)%> OK <%=sanitize textilize(@product.description)

%>

7

Cross-Site Scripting in Rails 3

Know what you‘re doing <%= auto_link(@product.description) %>

# => unsafe, so escaped <%= raw auto_link(@product.description) %>

# => safe, but may contain HTML sanitize() it

8

Cross-Site Scripting in Rails 3

Know what you‘re doing Strings aren't magic:

value = sanitize(@product.description)value.html_safe? #=> truevalue.gsub!(/--product_name--/, @product.title)value.html_safe? #=> true<%= value %>

9

Cross-Site Scripting in Rails 3

Rails helper are becoming stable now There were problems with content_tag(), tag(),

submit_tag(), ... SafeErb plugin doesn‘t work yet/anymore

10

Cross-Site Scripting in Rails 3

xml.instruct!xml.description do xml << "The description: " xml << @product.descriptionend

Use xml.description @product.description to automatically escape

11

Ajax and XSS

No automatic escaping in RJS templates page.replace_html :notice,

"Updated product #{@product.title}"

12

Sanitization

Don‘t write it on your own:value = self.description.gsub("<script>", "")<scr<script>ipt>

sanitize(), strip_tags(), ... use the HTML::Tokenizer

Based on regular expressions Doesn‘t always render valid HTML Last vulnerability in Rails 2.3.5 regarding non-

printable ascii characters13

Sanitization

Use parsers like Nokogiri or Woodstox (JRuby) Gem sanitize: http://github.com/rgrove/sanitize

Sanitize.clean(unsafe_html) Gem Loofah: http://github.com/flavorjones/

loofahLoofah.fragment(unsafe_html).scrub!(:strip)

14

Sql-Injection in Rails 3

No find() anymore, no :conditions hash, ...But: Product.find(params[:id])

User.order('users.id DESC').limit(20).all NO: Product.where("id = #{params[:id]}") Product.where(["id = ?", params[:id]]) Product.where({:id => params[:id]})

15

Sql-Injection in Rails 3

NO: User.order(params[:order]).all raise "SQLi" unless ["id asc", "id desc"].include?

(params[:order]) Escape it yourself:

Product.order(Product.connection.quote(params[:order])).all

16

Other changes in Rails 3

config/initializers/session_store.rbRails.application.config.session_store :cookie_store, :key => "_app_name_session"

config/initializers/cookie_verification_secret.rbRails.application.config.cookie_secret = 'somereallylongrandomkey'

Don‘t keep it in your SCM

17

Other changes in Rails 3

Keep a value in a signed cookie:cookies.signed[:discount] = "12"

filter_parameter_logging deprecated config.filter_parameters << :password

in config/application.rb

18

Respond_with in Rails 3

class ProductsController < ApplicationController respond_to :html, :xml, :json def index respond_with(@products = Product.all) endend

How to define what attributes to render in [email protected]_xml(:only => [:id])

19

Bits and pieces

You can deploy with a SSH key:ssh_options[:keys] = ["/path/to/id_rsa.ppk"]

Secure the admin panel with a client SSL certificate

Remove secrets from your SCM: database.yml, ssh_config.rb

20

Bits and pieces

Check what they‘re downloadingFile.dirname(requested_filename) == expected_directory

/download?file=../config/database.yml validates_format_of :filename,

:with => /^[a-z\.]+$/i hello.txt

<script>alert(1)</script> Use \A and \z

21

Privilege escalation

def update @doc = Doc.find(params[:id]) end

before_filter :load_project before_filter :deny_if_not_full_access before_filter :load_doc

@doc = @project.docs.find(params[:id]) before_filter :deny_if_no_access_to_doc

22

Authorization

def deny_if_no_access_to_doc @doc.may_edit?(current_user) end

def may_edit?(usr) self.creator == usr end

<%= link_to(“Edit“,...) if @doc.may_edit?(current_user) %>

23