Seguridad en aplicaciones Web

Preview:

DESCRIPTION

Diapositivas de la charla sobre seguridad en aplicaciones web.

Citation preview

Seguridad web en aplicaciones Rails

Ernesto Jiménez Caballeroernesto.jimenez@negonation.com

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 => 'usuario@ejemplo.com',   :password => 'xxxx'}# => Usuario creado con los parámetros del formulario

post :create, :user => {   :email => 'usuario@ejemplo.com',    :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 => 'usuario@ejemplo.com',   :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 => 'usuario@ejemplo.com',  :password => 'xxxx',  :admin => true)user.admin # => falseuser.attributes = {  :email => 'nuevo_email@ejemplo.com',  :admin => true }user.admin # => false

user.admin = trueuser.admin # => true

Asignación masivaclass User < ActiveRecord::Base  attr_accessible :email, :passwordend

user = User.new(  :email => 'usuario@ejemplo.com',  :password => 'xxxx',  :admin => true)user.admin # => falseuser.attributes = {  :email => 'nuevo_email@ejemplo.com',  :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">       &lt;script>         /* Javascript malintencionado */       &lt;/script>     </div>

Cross Site Scripting<div class="comentario">  <%=h @comment.body %></div>

post :create, :comment => { :body => "<script>  /* Javascript malintencionado */</script>" }# => <div class="comment">       &lt;script&gt;         /* Javascript malintencionado */       &lt;/script&gt;     </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 => 'cualquiera@spam.es',    :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?

Recommended