Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Segurança em Aplicações Rails

Segurança em Aplicações Rails

RubyConf Brasil 2016: #rubyconf #rails #security

Diego Rossini Vieira

September 24, 2016
Tweet

Other Decks in Technology

Transcript

  1. OWASP TOP 10 - 2013 A1 Injeção de código A2

    Quebra de autenticação e Gerenciamento de Sessão A3 Cross-Site Scripting (XSS) A4 Referência Insegura e Direta a Objetos A5 Configuração Incorreta de Segurança A6 Exposição de Dados Sensíveis A7 Falta de Função para Controle do Nível de Acesso A8 Cross-Site Request Forgery (CSRF) A9 Utilização de Componentes Vulneráveis Conhecidos A10 Redirecionamentos e Encaminhamentos Inválidos
  2. 1 2 3 4 Atacante cria um site falso com

    o mesmo layout do original O usuário recebe esse site falso e submete o formulário O site falso tem um formulário que aponta para o site original aonde o usuário provavelmente está logado O site original recebe esse formulário e faz uma ação diferente da intenção do usuário
  3. <form action="http://site-original.com.br/users" method=“post"> <div> <label>Email</label> <input type="email" value="[email protected]" name="user[email]"> </div>

    <div> <label>Alterar senha</label> <input type="password" name="user[password_fake]"> <input type="hidden" name="user[password]" value=“senha-do-atacante“ /> </div> <div> <input type="submit" value="Atualizar conta"> </div> </form>
  4. class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising

    an exception. protect_from_forgery with: :exception end
  5. <form action="http://site-original.com.br/users" method=“post"> <input type="hidden" name="authenticity_token" value="5Y4eMio0xwYvt4ANZ=="> <div> <label>Email</label> <input

    type="email" value="[email protected]" name="user[email]"> </div> <div> <label>Alterar senha</label> <input type="password" name="user[password_fake]"> <input type="hidden" name="user[password]" value=“senha-do-atacante“ /> </div> <div> <input type="submit" value="Atualizar conta"> </div> </form>
  6. <h1>Bem vindo ao meu site</h1> <% if params[:message] %> <%=

    params[:message].html_safe %> <% end %>
  7. 1.Sessions 2.CSRF 3.Redirection and Files 4.Intranet and Admin Security 5.User

    Management 6.Injection 7.Unsafe Query Generation 8.Default Headers 9.Environmental Security 10.Additional Resources http://guides.rubyonrails.org/security.html
  8. User.where("email = '#{params[:email]}'") SELECT * FROM users WHERE (email =

    '') or (admin='1') params[:email] = "') or (admin='1"
  9. average calculate count maximum minimum sum delete_all destroy_all exists? find_by

    where from group having joins lock order pluck reorder select update_all API vulnerável do ActiveRecord
  10. Session Fixation: A sessão NUNCA expira! • Dado que você

    tenha um cookie de um usuário, você pode acessar a aplicação para sempre como esse usuário Atenção com Sessions
  11. Sanitize todos os campos de URLs que você salva no

    banco user.homepage_url = "javascript:alert('hello')" link_to "Homepage", user.homepage_url <a href="javascript:alert('hello')">Homepage</a> Atenção com XSS
  12. Adeus proteção se alguém tirar o protect_from_forgery class ApplicationController <

    ActionController::Base # TODO: Não quero usar isso aqui, depois eu dou um jeito # protect_from_forgery with: :exception end Atenção com CSRF
  13. • params • cookies • headers • url path Não

    confie em nenhum dado enviado pelo usuário • upload de arquivos • requisições ajax • elementos do DOM • qualquer coisa!!!!!!!!!
  14. 2016: Como eu poderia ter hackeado todas as contas do

    Facebook Fonte: http://www.anandpraka.sh/2016/03/how-i-could-have-hacked-your-facebook.html
  15. 2016: Como eu poderia ter hackeado todas as contas do

    Facebook Fonte: http://www.anandpraka.sh/2016/03/how-i-could-have-hacked-your-facebook.html
  16. "Access to all of the flight’s departures, arrivals, the reservation

    payment receipt, personal information about passengers (phone numbers, emergency contacts), and the ability to change/cancel the flight."
  17. Referência Insegura e Direta a Objetos Como o usuário já

    estava logado no aplicativo, a API confiava nas requests.
  18. Verifique se a sua API não está expondo mais informações

    que o client que vai consumir ela precisa Exposição de Dados Sensíveis APIs podem expor informações
  19. Exposição de Dados Sensíveis APIs podem expor informações Verifique se

    você se preocupa com a segurança da sua API da mesma forma que você se preocupa com a segurança do seu site
  20. def TryPass(apple_id, password): url = 'https://fmipmobile.icloud.com/fmipservice/device/'+apple_id headers = { 'User-Agent':

    'FindMyiPhone/376 CFNetwork/672.0.8 Darwin/14.0.0' } Fonte: https://github.com/hackappcom/ibrute/blob/master/id_brute.py
  21. def TryPass(apple_id, password): url = 'https://fmipmobile.icloud.com/fmipservice/device/'+apple_id headers = { 'User-Agent':

    'FindMyiPhone/376 CFNetwork/672.0.8 Darwin/14.0.0' } Fonte: https://github.com/hackappcom/ibrute/blob/master/id_brute.py
  22. 401 - Unauthorized = Existe e não tenho acesso! 404

    - Not found = Não existe?! Exposição de Dados Sensíveis Headers podem expor informações
  23. “Senha incorreta” = Acertei o usuário “Usuário ou senha incorretos”

    = Senha ou usuário? Exposição de Dados Sensíveis A linguagem pode expor informações
  24. “E-mail não cadastrado no sistema” = Não tem esse e-mail!

    “Caso exista, enviamos o e-mail” = Tem esse e-mail? Exposição de Dados Sensíveis A linguagem pode expor informações
  25. Exposição de Dados Sensíveis URLs podem expor informações - Credential

    Enumeration www.site.com/user/1 = id do usuário www.site.com/client/3984739874 = cpf do cliente
  26. IDs sequenciais São potencialmente perigosos • Expõem a quantidade de

    registros que existem • Facilidade para ataques usando os próprios endpoints da aplicação
  27. # It will change confirmation, password recovery and other workflows

    # to behave the same regardless if the e-mail provided was right or wrong. # Does not affect registerable. config.paranoid = true Devise
  28. module Devise module Strategies class DatabaseAuthenticatable < Authenticatable def authenticate!

    resource = password.present? && mapping.to.find_for_database_authentication(authentication_hash) hashed = false if validate(resource){ hashed = true; resource.valid_password?(password) } remember_me(resource) resource.after_database_authentication success!(resource) end mapping.to.new.password = password if !hashed && Devise.paranoid fail(:not_found_in_database) unless resource end end end end
  29. PASSWORD = 'abcdefghij' BCRYPT_DIGEST = BCrypt::Password.create(PASSWORD, cost: 13) MD5_DIGEST =

    Digest::MD5.hexdigest(PASSWORD) SHA1_DIGEST = Digest::SHA1.hexdigest(PASSWORD) SHA256_DIGEST = Digest::SHA256.hexdigest(PASSWORD) SHA384_DIGEST = Digest::SHA384.hexdigest(PASSWORD) SHA512_DIGEST = Digest::SHA512.hexdigest(PASSWORD) Benchmark.ips do |x| x.report('md5') { Digest::MD5.hexdigest(PASSWORD) == MD5_DIGEST } x.report('sha1') { Digest::SHA1.hexdigest(PASSWORD) == SHA1_DIGEST } x.report('sha256') { Digest::SHA256.hexdigest(PASSWORD) == SHA256_DIGEST } x.report('sha384') { Digest::SHA384.hexdigest(PASSWORD) == SHA384_DIGEST } x.report('sha512') { Digest::SHA512.hexdigest(PASSWORD) == SHA512_DIGEST } x.report('bcrypt') { BCrypt::Password.create(PASSWORD) == BCRYPT_DIGEST } x.compare! end Fonte: https://speakerdeck.com/fnando/criando-aplicacoes-web-mais-seguras
  30. Warming up -------------------------------------- md5 37.583k i/100ms sha1 37.561k i/100ms sha256

    32.718k i/100ms sha384 30.712k i/100ms sha512 28.692k i/100ms bcrypt 1.000 i/100ms Calculating ------------------------------------- md5 514.530k (± 2.6%) i/s - 2.593M in 5.043394s sha1 521.438k (± 3.0%) i/s - 2.629M in 5.046857s sha256 383.893k (±13.1%) i/s - 1.898M in 5.052521s sha384 305.295k (±13.0%) i/s - 1.505M in 5.024430s sha512 320.019k (± 9.9%) i/s - 1.607M in 5.077244s bcrypt 5.845 (±17.1%) i/s - 29.000 in 5.015230s Comparison ------------------------------------- sha1: 521438.2 i/s md5: 514530.1 i/s - same-ish: difference falls within error sha256: 383893.1 i/s - 1.36x slower sha512: 320019.4 i/s - 1.63x slower sha384: 305294.6 i/s - 1.71x slower bcrypt: 5.8 i/s - 89211.74x slower
  31. Fonte: http://cynosureprime.blogspot.com.br/2015/09/how-we-cracked-millions-of-ashley.html 2015: Como quebramos milhões de senhas do Ashley

    Madison de forma eficiente Fonte: http://arstechnica.com/security/2015/09/once-seen-as-bulletproof-11-million-ashley-madison-passwords-already-cracked/
  32. Fonte: http://cynosureprime.blogspot.com.br/2015/09/how-we-cracked-millions-of-ashley.html 2015: Como quebramos milhões de senhas do Ashley

    Madison de forma eficiente Fonte: http://arstechnica.com/security/2015/09/once-seen-as-bulletproof-11-million-ashley-madison-passwords-already-cracked/
  33. Segurança em dados criptografados Use Salt de forma correta "A

    função primária do Salt é defender contra ataques de dicionário"
  34. Isso gera um salt fixo salt = BCrypt::Engine.generate_salt pass_hash =

    BCrypt::Engine.hash_secret(password,salt) Fonte: http://dustwell.com/how-to-handle-passwords-bcrypt.html
  35. # File 'lib/bcrypt/password.rb', line 43 def create(secret, options = {})

    cost = options[:cost] || BCrypt::Engine.cost raise ArgumentError if cost > 31 Password.new(BCrypt::Engine.hash_secret(secret, BCrypt::Engine.generate_salt(cost))) end Isso gera um salt randômico pass = BCrypt::Password.create(PASSWORD)
  36. “Isso tem a velocidade de 350 bilhões de tentativas de

    senha por segundo" Fonte: http://arstechnica.com/security/2012/12/25-gpu-cluster-cracks-every-standard-windows-password-in-6-hours
  37. “Isso tem a velocidade de 350 bilhões de tentativas de

    senha por segundo" Fonte: http://arstechnica.com/security/2012/12/25-gpu-cluster-cracks-every-standard-windows-password-in-6-hours 350 bilhões
  38. Atualizações de software Atualizar é uma dor? Causas? • Suite

    de testes: ruim? lenta? • Medo do comportamento das dependências?
  39. Atualizações de software GEMS • Chances para diversos problemas de

    segurança • Pense bem antes de adicionar mais uma dependência
  40. Atualizações de software https://github.com/rubysec/bundler-audit GEMS - Considere a gem bundler-audit

    • Verifica versões com vulnerabilidades no Gemfile.lock • Verifica gem sources inseguros
  41. 0 4.5 9 13.5 18 2006 2007 2008 2009 2010

    2011 2012 2013 2014 2015 2016 8 2 12 18 10 12 1 4 2 2 2 Vulnerabilidades Fonte: https://www.cvedetails.com/product/22568/Rubyonrails-Ruby-On-Rails.html?vendor_id=12043 * CVE: Common Vulnerabilities and Exposures * CVEs do Rails
  42. Atualizações de software RAILS - Você deveria conseguir atualizar o

    mais rápido possível quando for um release de segurança
  43. • RabbitMQ, como você trata as mensagens? • Logs diferentes

    do Rails, você filtra dados? • Deveria auditar logs? • StatsD+Grafana para estatísticas de segurança • Brakeman no seu Build • Segurança do teu servidor • Autenticação apenas por SSH (keys) • Libere apenas as portas necessárias • … Outras coisas
  44. OWASP TOP 10 - 2013 A1 Injeção de código A2

    Quebra de autenticação e Gerenciamento de Sessão A3 Cross-Site Scripting (XSS) A4 Referência Insegura e Direta a Objetos A5 Configuração Incorreta de Segurança A6 Exposição de Dados Sensíveis A7 Falta de Função para Controle do Nível de Acesso A8 Cross-Site Request Forgery (CSRF) A9 Utilização de Componentes Vulneráveis Conhecidos A10 Redirecionamentos e Encaminhamentos Inválidos
  45. Responsible Disclosure Rails Fonte: http://rubyonrails.org/security/ • Envie um email para

    a lista de segurança: [email protected] • Contate diretamente o atual coordenador de segurança: Rafael França • Contate diretamente o contato de backup: Jeremy Daer