Transcript
Page 1: secureRubyonRails.ppt

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

Page 2: secureRubyonRails.ppt

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: secureRubyonRails.ppt

User InputRegular form fieldsHidden form fieldsCookiesURL ParametersPOST dataHTTP headersAJAX requests

Scoped Queries

Securing Ruby on Rails

Page 4: secureRubyonRails.ppt

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 Railsdef 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: secureRubyonRails.ppt

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: secureRubyonRails.ppt

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: secureRubyonRails.ppt

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 Railsrequire '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: secureRubyonRails.ppt

Form ValidationClient-side validation with javascript

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

Securing Ruby on Rails

Page 9: secureRubyonRails.ppt

SQL Injectionpassing input directly from user to databasemalicious 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: secureRubyonRails.ppt

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: secureRubyonRails.ppt

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: secureRubyonRails.ppt

Securing Ruby on Rails

Cross-site Scripting (XSS)unescaped user data included in HTML outputWhat’s the problem? Javascript!

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

Page 13: secureRubyonRails.ppt

Securing Ruby on RailsCross-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: secureRubyonRails.ppt

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: secureRubyonRails.ppt

Securing Ruby on Rails

Silencing Logs

class OrdersController < ApplicationController filter_parameter_logging :cc_number, :cvv, :cc_date # ...end

Page 16: secureRubyonRails.ppt

Securing Ruby on Rails

Advertising

Third party widgets

Page 17: secureRubyonRails.ppt

Attributation1. The Ghost In The Browser: Analysis of Web-based MalwareNiels Provos, Dean McNamee, Panayiotis Mavrommatis, Ke Wang and Nagendra

Modadugu Google, Inc. 2. Ajax on Rails by Scott Raymond3. 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


Top Related