Upload
ernesto-jimenez
View
11.027
Download
6
Embed Size (px)
DESCRIPTION
Diapositivas de la charla sobre seguridad en aplicaciones web.
Citation preview
Seguridad web en aplicaciones Rails
Ernesto Jiménez [email protected]
Sobre esta charla
¿De qué vamos a hablar?
SQL Injections
class User < ActiveRecord::Base def self.authenticate(login, password) return User.find(:first, :conditions => "login = '#{login}' AND crypted_password = '#{encrypt(password)}'") endend
User.authenticate("blabla' OR 'x' = 'x') OR ('x' = 'x", 'lo_que_sea')# => SELECT * FROM users WHERE (login = 'blabla' OR 'x' = 'x') OR ('x' = 'x' AND crypted_password = '4123oijsjdir32josidjr032') LIMIT 1;
User.authenticate("blabla' OR admin = 1) OR ('x' = 'x", 'lo_que_sea')# => SELECT * FROM users WHERE (login = 'blabla' OR admin = 1) OR ('x' = 'x' AND crypted_password = '4123oijsjdir32josidjr032') LIMIT 1;
SQL Injections
SQL Injectionsclass User < ActiveRecord::Base def self.authenticate(login, password) return User.find(:first, :conditions => [ "login = ? AND crypted_password = ?", login, encrypt(password) ]) endend
class User < ActiveRecord::Base def self.authenticate(login, password) return User.find(:first, :conditions => { :login => login, :crypted_password => encrypt(password) }) endend
:conditions => “x = #{x}”deja que Rails escape los parámetros de las consultas
Asignación masiva
Asignación masivaclass UsersController < ApplicationController def create @user = User.create(params[:user]) endend
<% from_for :user, :url => users_path do |f| %> <label>email: <%= f.text_field :email %> </label> <label>password: <%= f.text_field :password %> </label> <%= submit_tag 'Registrarse' %><% end %>
Asignación masivaclass UsersController < ApplicationController def create @user = User.create(params[:user]) endend
Asignación masivaclass UsersController < ApplicationController def create @user = User.create(params[:user]) endend
post :create, :user => { :email => '[email protected]', :password => 'xxxx'}# => Usuario creado con los parámetros del formulario
post :create, :user => { :email => '[email protected]', :password => 'xxxx', :admin => true}# => Escalada de privilegios!
Asignación masivaclass User < ActiveRecord::Base has_many :postsend
class Post < ActiveRecord::Base belongs_to :userend
post :create, :user => { :email => '[email protected]', :password => 'xxxx', :post_ids => [1,2,3]}# => Se proclama autor de los posts 1, 2 y 3!
Asignación masivaclass User < ActiveRecord::Base attr_protected :adminend
user = User.new( :email => '[email protected]', :password => 'xxxx', :admin => true)user.admin # => falseuser.attributes = { :email => '[email protected]', :admin => true }user.admin # => false
user.admin = trueuser.admin # => true
Asignación masivaclass User < ActiveRecord::Base attr_accessible :email, :passwordend
user = User.new( :email => '[email protected]', :password => 'xxxx', :admin => true)user.admin # => falseuser.attributes = { :email => '[email protected]', :admin => true }user.admin # => false
user.admin = trueuser.admin # => true
attr_protectedattr_accessible
no introduzcas vulnerabilidades por olvidos
Cross Site Scripting
Cross Site Scripting<div class="comentario"> <%= @comment.body %></div>
post :create, :comment => { :body => "<script> /* Javascript malintencionado */</script>" }# => <div class="comment"> <script> /* Javascript malintencionado */ </script> </div>
Cross Site Scripting<div class="comentario"> <%= sanitize @comment.body %></div>
post :create, :comment => { :body => "<script> /* Javascript malintencionado */</script>" }# => <div class="comment"> <script> /* Javascript malintencionado */ </script> </div>
Cross Site Scripting<div class="comentario"> <%=h @comment.body %></div>
post :create, :comment => { :body => "<script> /* Javascript malintencionado */</script>" }# => <div class="comment"> <script> /* Javascript malintencionado */ </script> </div>
sanitizeFunciona con listas negras y no lo detecta todo
hbueeeeno, pero... ¿qué pasa si te olvidas uno?
¡¡¡es muy fácil olvidarse una letra!!!
sanitiza antes de guardar
Cross Site Request Forgery
Cross Site Request Forgery<img src=”http://web.com/nuevo_pass?pass=robado” />
Cross Site Request ForgeryNo es un problema en Rails 2.0
Accesos no autorizados
Accesos no autorizadosclass DraftsController < ApplicationController def show @draft = Draft.find(params[:id]) end
def destroy @draft = Draft.destroy(params[:id]) endend
# => Cualquier usuario puede ver y eliminar los borradores
Accesos no autorizadosclass DraftsController < ApplicationController def show @draft = current_user.drafts.find(params[:id]) end
def destroy @draft = current_user.drafts.destroy(params[:id]) endend
# => Solo el autor del borrador puede verlos y borrarlos
Acciones públicas
Acciones públicas# Ejemplo muy chorra :)class UsersController < ApplicationController def invite current_user.invitations.create(params[:email],) send_email end def send_email UserMailer.deliver_email(params[:email], params[:body]) endend
get :send_email, :email => '[email protected]', :body => 'Compra V14GR4! http://www.pastillitaazul.com'# => El código de send_mail se ejecuta aunque luego de error
Acciones públicas# Ejemplo muy chorra :)class UsersController < ApplicationController def invite current_user.invitations.create(params[:email],) send_email end protected def send_email UserMailer.deliver_email(params[:email], params[:body]) endend
algunos consejos
jamás te fíes de lo que recibes en el servidor
ten cuidado con los datos que recibes, pero también con los
que envías
controla las interfaces de tus cotroladores y
modelos
no filtres con listas negras
no tengas miedo de escribir tests que prueben la seguridad
def test_should_avoid_xss_from_search_query get :search, :q => '<script id="injection">alert();</script>' assert_no_tag :script, :attributes => {:id => 'injection' } end
algunas herramientas
FireBug
Cookie Editor
Tamper Data
CURL
WWW::Mechanize
require 'rubygems'require 'mechanize'
agent = WWW::Mechanize.new
page = agent.get 'http://www.gmail.com'form = page.forms.firstform.Email = '***your gmail account***'form.Passwd = '***your password***'page = agent.submit form
page = agent.get page.search("//meta").first.attributes['href'].gsub(/'/,'')page = agent.get page.uri.to_s.sub(/\?.*$/, "?ui=html&zy=n")page.search("//tr[@bgcolor='#ffffff']") do |row| from, subject = *row.search("//b/text()") url = page.uri.to_s.sub(/ui.*$/, row.search("//a").first.attributes["href"]) puts "From: #{from}\nSubject: #{subject}\nLink: #{url}\n\n"
email = agent.get url # ..end
¿Preguntas?