securing ruby on rails cis 6939 web engineering with ruby on rails university of north florida...

17
Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Upload: laurel-gray

Post on 26-Dec-2015

213 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Securing Ruby on Rails

CIS 6939 Web Engineering with Ruby on RailsUniversity of North FloridaStephen Jones 8 July 2007

Page 2: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

SANS Top-20 Internet Security Attack Targets (2006 Annual Update) Top of the list for the Cross-platform Applications category is:

C1 Web Applications C1.1 Description Applications such as Content Management Systems (CMS), Wikis, Portals, Bulletin Boards,

and discussion forums are being used by small and large organizations. Every week hundreds of vulnerabilities are being reported in these web applications, and are being actively exploited. The number of attempted attacks every day for some of the large web hosting farms range from hundreds of thousands to even millions.

All web frameworks (PHP, .NET, J2EE, Ruby on Rails, ColdFusion, Perl, etc) and all types of web applications are at risk from web application security defects, ranging from insufficient validation through to application logic errors.

Securing Ruby on Rails

Page 3: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

User InputRegular form fields

Hidden form fields

Cookies

URL Parameters

POST data

HTTP headers

AJAX requests

Scoped Queries

Securing Ruby on Rails

Page 4: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

class User < ActiveRecord::Basehas_many :contacts

endclass Contact < ActiveRecord::Base

belongs_to :userend

class ContactsController < ApplicationController before_filter :require_signindef new

@contact = Contact.newenddef create

contact = Contact.new params[:contact]contact.user_id = session[:user_id]contact.saveredirect_to contact_url(contact)

end

Securing Ruby on Rails

def show @contact = Contact.find params[:id]end # accessed in URL path like /contacts/42privatedef require_signin return false unless session[:user_id]end

end

Record IDs used right in the URL?

Page 5: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

class ContactsController < ApplicationController # gives us a @current_user objectbefore_filter :require_signin # safely looks up the contactbefore_filter :find_contact, :except =>

[ :index, :new, :create ]def index

@contacts = @current_user.contacts.find :allenddef new @contact = @current_user.contacts.newenddef create @current_user.contacts.create params[:contact] redirect_to contacts_urlenddef showenddef editend

Securing Ruby on Railsdef update @contact.update_attributes params[:contact] redirect_to contact_urlenddef destroy @contact.destroy redirect_to contacts_urlendprivatedef require_signin @current_user = User.find session[:user_id] redirect_to(home_url) and return false unless@current_userenddef find_contact @contact = @current_user.contacts.find.params[:id]endend

Page 6: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Record IDs in URLs verified? (HTTP authentication) Is the ID guessable? How about a token?

class User < ActiveRecord::Basedef before_create token = Digest::SHA1.hexdigest("#{id}#{rand.to_s}")[0..15] write_attribute 'token', tokenendendclass FeedsController < ApplicationControllerdef show @user = User.find_by_token(params[:id]) or raise ActiveRecord::RecordNotFoundendend

Securing Ruby on Rails

Page 7: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Mass Assignment

contact = current_user.contacts.create params[:contact]contact.update_attributes params[:contact]

class UsersController < ApplicationControllerdef edit @user = current_userenddef update current_user.update_attributes params[:user] redirect_to edit_user_urlendend

edit.rhtml:<% form_for :user, :url => user_url, :html => { :method => :put } do |u| %><p>Login: <%= u.text_field :login %></p><p>Password: <%= u.password_field :password

%></p><p><%= submit_tag "Save Account Settings" %><% end %>

Securing Ruby on Rails

require 'net/http'http = Net::HTTP.new 'localhost', 3000http.post "/users/1", 'user[is_administrator]=1&_method=put',{ 'Content-Type' => 'application/x-www-form-urlencoded' }

class User < ActiveRecord::Base attr_protected :is_administrator has_many :contactsend

class User < ActiveRecord::Base attr_accessible :login, :password has_many :contactsend

Page 8: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Form Validation

Client-side validation with javascript

immediate feedback

The data should still be validated on the server side as well.

Securing Ruby on Rails

Page 9: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

SQL Injectionpassing input directly from user to database

malicious users hijack your queries

Securing Ruby on Rails

# unsafeUser.find(:first, :conditions => "login = '#{params[:login]}' ANDpassword = '#{params[:password]}'")

SELECT * FROM users WHERE (login='alice' and password='secret') LIMIT 1

' or login='bob' and password != ‘

SELECT * FROM users WHERE (login='' andpassword='' or login='bob' and password !=‘ ‘ ) LIMIT 1 #Logs in as any user

Page 10: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

SQL Injection

# safe (pass a hash to :conditions)

User.find(:first, :conditions => { :login => params[:login],

:password => params[:password] })

# safe (shorter form)

User.find(:first, :conditions =>

[ "login = ? AND password = ?", params[:login], params[:password] ])

Securing Ruby on Rails

Page 11: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Session Fixationcross-site cooking

Mitigationuse reset_session in your sign-in and sign-out methods

# signindef create if u = User.find_by_login_and_password(params[:login], params[:password]) reset_session # create a new sess id, to thwart fixation session[:user_id] = u.id redirect_to home_urlelse render :action => 'new'endend

Securing Ruby on Rails

Page 12: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Securing Ruby on Rails

Cross-site Scripting (XSS)

unescaped user data included in HTML output

What’s the problem? Javascript!

http://example.com/search?q=%3Cscript%3Ealert('XSS')%3B%3C%2Fscript%3E

Page 13: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Securing Ruby on Rails

Cross-site Scripting (XSS)#unsafe<%= start_form_tag search_url, :method => :get %><p><%= text_field_tag :q %> <%= submit_tag "Search" %><% end %>

class SearchController < ApplicationController def index @q = params[:q] @posts = Post.find :all, :conditions => ["body like :query", { :query => params[:q]}] endend

<p>Your search for <em><%= @q %></em> returned <%= pluralize @posts.size, "result" %>:</p><% @posts.each do |post| %> <li><%= link_to post.title, post_url(:id => post) %>: <%= exerpt post.body, @q %></li><% end %>

Solution: h helper, also known as html escape.

converts &, ", >, and < into &amp;, &quot; &gt;, and &lt;

<p>Your search for <em><%= h @q %></em><%= link_to h(@user.name), user_url(@user) %>

Page 14: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Securing Ruby on RailsHashing Passwords

MD5 or SHA1require 'digest/sha1'class User < ActiveRecord::Base attr_accessor :password validates_uniqueness_of :login validates_presence_of :password, :if => :password_required? validates_confirmation_of :password, :if => :password_required? before_save :hash_password# Authenticates a user by login/password. Returns the user or nil.def self.authenticate login, password find_by_login_and_hashed_password(login, Digest::SHA1.hexdigest(login+password))endprotecteddef hash_password return if password.blank? self.hashed_password = Digest::SHA1.hexdigest(login+password)enddef password_required? hashed_password.blank? || !password.blank?endend

Page 15: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Securing Ruby on Rails

Silencing Logs

class OrdersController < ApplicationController

filter_parameter_logging :cc_number, :cvv, :cc_date

# ...

end

Page 16: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Securing Ruby on Rails

Advertising

Third party widgets

Page 17: Securing Ruby on Rails CIS 6939 Web Engineering with Ruby on Rails University of North Florida Stephen Jones 8 July 2007

Attributation1. The Ghost In The Browser: Analysis of Web-based Malware

Niels Provos, Dean McNamee, Panayiotis Mavrommatis, Ke Wang and Nagendra Modadugu Google, Inc.

2. Ajax on Rails by Scott Raymond

3. Sans Institute Internet Security Attack Targets http://www.sans.org/top20/

4. Rails Security Mailing List: http://groups.google.com/group/rubyonrails-security

Securing Ruby on Rails