Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Criando aplicações web mais seguras

Nando Vieira
September 23, 2015

Criando aplicações web mais seguras

Manter sua aplicação segura é tão importante quanto o desenvolvimento em si. Infelizmente nem todo desenvolvedor faz a sua parte para garantir que os riscos de ataques foram minimizados. Nessa palestra você verá os problemas mais comuns, entenderá porque é importante manter seu aplicativo atualizado e conhecerá algumas boas práticas para minimizar as chances de ser hackeado.

Palestra apresentada na Web.br 2015.

Nando Vieira

September 23, 2015
Tweet

More Decks by Nando Vieira

Other Decks in Technology

Transcript

  1. 75% DOS ATAQUES ACONTECEM NA WEB A web é um

    ambiente realmente assustador. http://fnando.me/1c6
  2. 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 – Ausência de Controle de Acesso A8 – Cross-Site Request Forgery (CSRF) A9 – Utilização de Componentes com Vulnerabilidades Conhecidas A10 – Redirecionamentos Não Validados OWASP — TOP 10 2013 http://fnando.me/1c9
  3. require 'uri' class ReturnUrl def self.url(default_url, return_url) uri = URI.parse(return_url)

    return default_url if return_url.blank? return default_url unless Config.redirect_allowed_hosts.include?(uri.host) return_url rescue URI::InvalidURIError default_url end end
  4. class SessionsController < ApplicationController def create if Authenticator.call(params[:credential], params[:password], session)

    redirect_to RedirectUrl.url(dashboard_path, params[:return_to]) else render :new end end end
  5. class SessionsController < ApplicationController def create if Authenticator.call(params[:credential], params[:password], session)

    redirect_to RedirectUrl.url(dashboard_path, params[:return_to]) else render :new end end end
  6. Received heartbeat response: 0000: 02 40 00 D8 03 00

    53 43 5B 90 9D 9B 72 0B BC 0C [email protected][...r... 0010: BC 2B 92 A8 48 97 CF BD 39 04 CC 16 0A 85 03 90 .+..H...9....... 00d0: 10 00 11 00 23 00 00 00 0F 00 01 01 2F 33 34 2E ....#......./34. 00e0: 30 2E 31 38 34 37 2E 31 33 37 20 53 61 66 61 72 0.1847.137 Safar 00f0: 69 2F 35 33 37 2E 33 36 0D 0A 52 65 66 65 72 65 i/537.36..Refere 0100: 72 3A 20 68 74 74 70 73 3A 2F 2F 77 77 77 2E 74 r: https://examp 0110: 72 61 79 2E 63 6F 6D 2E 62 72 2F 0D 0A 41 63 63 le.org/......Acc 0120: 65 70 74 2D 45 6E 63 6F 64 69 6E 67 3A 20 67 7A ept-Encoding: gz 0130: 69 70 2C 64 65 66 6C 61 74 65 2C 73 64 63 68 0D ip,deflate,sdch. 0140: 0A 41 63 63 65 70 74 2D 4C 61 6E 67 75 61 67 65 .Accept-Language 0150: 3A 20 70 74 2D 42 52 2C 70 74 3B 71 3D 30 2E 38 : pt-BR,pt;q=0.8 0160: 2C 65 6E 2D 55 53 3B 71 3D 30 2E 36 2C 65 6E 3B ,en-US;q=0.6,en; 0170: 71 3D 30 2E 34 0D 0A 43 6F 6F 6B 69 65 3A 20 5F q=0.4..Cookie: _ 0180: 5F 75 74 6D 61 3D 34 37 35 37 33 32 31 38 2E 31 _utma=47573218.1 0190: 33 31 31 35 32 35 38 34 37 2E 31 34 30 30 30 39 311525847.140009 01a0: 31 35 31 39 2E 31 34 30 30 30 39 36 38 36 35 2E 1519.1400096865. 01b0: 31 34 30 30 31 35 31 35 33 34 2E 33 3B 20 5F 5F 1400151534.3; __ 01c0: 75 74 6D 7A 3D 34 37 35 37 33 32 31 38 2E 31 34 utmz=47573218.14 01d0: 30 30 30 39 31 35 31 39 2E 31 2E 31 2E 75 74 6D 00091519.1.1.utm 01e0: 63 73 72 3D 28 64 69 72 65 63 74 29 7C 75 74 6D csr=(direct)|utm 01f0: 63 63 6E 3D 28 64 69 72 65 63 74 29 7C 75 74 6D ccn=(direct)|utm 0200: 63 6D 64 3D 28 6E 6F 6E 65 29 0D 0A 0D 0A 25 30 cmd=(none)....%0
  7. Received heartbeat response: 0000: 02 40 00 D8 03 00

    53 43 5B 90 9D 9B 72 0B BC 0C [email protected][...r... 0010: BC 2B 92 A8 48 97 CF BD 39 04 CC 16 0A 85 03 90 .+..H...9....... 00d0: 10 00 11 00 23 00 00 00 0F 00 01 01 2F 33 34 2E ....#......./34. 00e0: 30 2E 31 38 34 37 2E 31 33 37 20 53 61 66 61 72 0.1847.137 Safar 00f0: 69 2F 35 33 37 2E 33 36 0D 0A 52 65 66 65 72 65 i/537.36..Refere 0100: 72 3A 20 68 74 74 70 73 3A 2F 2F 77 77 77 2E 74 r: https://examp 0110: 72 61 79 2E 63 6F 6D 2E 62 72 2F 0D 0A 41 63 63 le.org/......Acc 0120: 65 70 74 2D 45 6E 63 6F 64 69 6E 67 3A 20 67 7A ept-Encoding: gz 0130: 69 70 2C 64 65 66 6C 61 74 65 2C 73 64 63 68 0D ip,deflate,sdch. 0140: 0A 41 63 63 65 70 74 2D 4C 61 6E 67 75 61 67 65 .Accept-Language 0150: 3A 20 70 74 2D 42 52 2C 70 74 3B 71 3D 30 2E 38 : pt-BR,pt;q=0.8 0160: 2C 65 6E 2D 55 53 3B 71 3D 30 2E 36 2C 65 6E 3B ,en-US;q=0.6,en; 0170: 71 3D 30 2E 34 0D 0A 43 6F 6F 6B 69 65 3A 20 5F q=0.4..Cookie: _ 0180: 5F 75 74 6D 61 3D 34 37 35 37 33 32 31 38 2E 31 _utma=47573218.1 0190: 33 31 31 35 32 35 38 34 37 2E 31 34 30 30 30 39 311525847.140009 01a0: 31 35 31 39 2E 31 34 30 30 30 39 36 38 36 35 2E 1519.1400096865. 01b0: 31 34 30 30 31 35 31 35 33 34 2E 33 3B 20 5F 5F 1400151534.3; __ 01c0: 75 74 6D 7A 3D 34 37 35 37 33 32 31 38 2E 31 34 utmz=47573218.14 01d0: 30 30 30 39 31 35 31 39 2E 31 2E 31 2E 75 74 6D 00091519.1.1.utm 01e0: 63 73 72 3D 28 64 69 72 65 63 74 29 7C 75 74 6D csr=(direct)|utm 01f0: 63 63 6E 3D 28 64 69 72 65 63 74 29 7C 75 74 6D ccn=(direct)|utm 0200: 63 6D 64 3D 28 6E 6F 6E 65 29 0D 0A 0D 0A 25 30 cmd=(none)....%0
  8. ATUALIZE O SOFTWARE QUE VOCÊ USA Esta deve ser uma

    tarefa constante de seu projeto.
  9. <form action="/transfer" method="get"> <input type="hidden" name="from" value="1234"> <div> <label for="to">Conta

    de destino</label> <select name="to" id="to"></select> </div> <div> <label for="amount">Quantia</label> <input type="text" name="amount" id="amount"> </div> <input type="submit" value="Transferir"> </form>
  10. USE NON-GET PARA AÇÕES QUE MUDAM O ESTADO Nunca utilize

    GET para ações que causam efeito colateral.
  11. <a href="http://example.com" onclick=" var f = document.createElement('script'); f.style.display = 'none';

    document.body.appendChild(f); f.method = 'POST'; f.action = '/transfer?from=1234&to=4567&amount=100000'; f.submit(); "> Link inofensivo </a>
  12. AUTENTICAÇÃO Validar se você é quem você diz ser. AUTORIZAÇÃO

    Validar o que você pode fazer baseado em quem você é.
  13. class AdminPolicy < PermissionPolicy ALLOWED_EMAIL = /\A[^@]+@example\.com\z/ def permit?(user) user

    && user.email.match(ALLOWED_EMAIL) end end AdminPolicy.permit?(current_user)
  14. class AdminController < ActionController::Base protect_from_forgery with: :exception before_action :authorize private

    def authorize return if authorized? reset_session redirect_to login_path end def authorized? AdminPolicy.permit?(current_user) end end
  15. EXCLUA DADOS SENSÍVEIS DE SEUS LOGS Senhas, números de cartão

    de crédito, chaves de API, e tudo mais que for dado sensível.
  16. require 'bcrypt' password_digest = BCrypt::Password.create('your password', cost: 13) #=> $2a$13$uao9THAp2WaLxRyu3ZC7uuD92pPEMFXEukVwv8fZt//O.ugsue23O

    BCrypt::Password.new(password_digest) == 'your password' #=> true BCrypt::Password.new(password_digest) == 'invalid password' #=> false
  17. require 'benchmark' require 'benchmark/ips' require 'bcrypt' require 'digest/sha1' require 'digest/sha2'

    include BCrypt include Digest GC.disable PASSWORD = 'abcdefghij' DIGEST = Password.create(PASSWORD, cost: 13) SHA1_DIGEST = Digest::SHA1.hexdigest(PASSWORD) SHA256_DIGEST = Digest::SHA256.hexdigest(PASSWORD) SHA512_DIGEST = Digest::SHA512.hexdigest(PASSWORD) Benchmark.ips do |x| x.report('sha1') { SHA1.hexdigest(PASSWORD) == SHA1_DIGEST } x.report('sha256') { SHA256.hexdigest(PASSWORD) == SHA256_DIGEST } x.report('sha512') { SHA512.hexdigest(PASSWORD) == SHA512_DIGEST } x.report('bcrypt') { Password.new(DIGEST) == PASSWORD } x.compare! end
  18. Calculating ------------------------------------- sha1 28.511k i/100ms sha256 27.043k i/100ms sha512 24.511k

    i/100ms bcrypt 1.000 i/100ms ------------------------------------------------- sha1 437.174k (±14.5%) i/s - 2.138M sha256 308.032k (±12.2%) i/s - 1.541M sha512 228.471k (±15.0%) i/s - 1.128M bcrypt 1.609 (± 0.0%) i/s - 9.000 in 5.603296s Comparison: sha1: 437174.0 i/s sha256: 308032.1 i/s - 1.42x slower sha512: 228471.5 i/s - 1.91x slower bcrypt: 1.6 i/s - 271735.68x slower
  19. Calculating ------------------------------------- sha1 28.511k i/100ms sha256 27.043k i/100ms sha512 24.511k

    i/100ms bcrypt 1.000 i/100ms ------------------------------------------------- sha1 437.174k (±14.5%) i/s - 2.138M sha256 308.032k (±12.2%) i/s - 1.541M sha512 228.471k (±15.0%) i/s - 1.128M bcrypt 1.609 (± 0.0%) i/s - 9.000 in 5.603296s Comparison: sha1: 437174.0 i/s sha256: 308032.1 i/s - 1.42x slower sha512: 228471.5 i/s - 1.91x slower bcrypt: 1.6 i/s - 271735.68x slower
  20. SALVAR HASHES SEM SALT NÃO AJUDA MUITO Rainbow tables possuem

    muitas senhas e a probabilidade de você encontrar senhas comuns ali é alta.
  21. EM PRODUÇÃO USE O AMBIENTE DE PRODUÇÃO Certifique-se que definiu

    as variáveis de ambiente RAILS_ENV e RACK_ENV.
  22. CONTRATE UM SYS ADMIN COMPETENTE Administrar um servidor corretamente é

    muito mais difícil do apenas fazer sua aplicação executar.
  23. #BREAKING: Twitter $TWTR Q1 Revenue misses estimates, $436M vs. $456.52M

    expected Selerity @selerity https://twitter.com/Selerity/status/593129551221432320
  24. CREATE TABLE proposals ( id uuid primary key not null

    default uuid_generate_v4(), title text not null )
  25. INJEÇÃO DE JAVASCRIPT NO CONTEXTO DA PÁGINA Isto permite roubo

    de cookies, redirecionamento para outros sites, exibição de ads, defacement, executar ações no lugar do usuário.
  26. FAÇA O ESCAPAMENTO DO CONTEÚDO NO JAVASCRIPT Se o dado

    veio do usuário, então não renderize-o como HTML.
  27. USE OUTROS HEADERS DE SEGURANÇA Isso ajuda previnir outros tipos

    de ataque, como defacement através de injeção de iframes.
  28. X-Frame-Options: DENY Bloqueia a renderização de frames, iframes e <object>.

    X-XSS-Protection: 1; mode=block Ativa filtros extras de prevenção contra XSS. X-Content-Type-Options: nosniff Rejeita arquivos que não possuem MIME type correto.
  29. MARQUE COOKIES COMO HTTP ONLY Não deixe cookies que só

    serão usados pelo servidor serem modificados pelo navegador.
  30. NUNCA CONFIE EM DADOS ENVIADOS PELO USUÁRIO Se veio do

    usuário, então o dado é inseguro.
  31. GARANTA QUE A SESSÃO USE SSL Se a página identifica

    usuários logados, deve necessariamente usar SSL.
  32. MARQUE OS COOKIES COMO HTTP ONLY E SEGUROS Isso dificulta

    o roubo de identidades através de falhas como XSS.
  33. Rails.application.config.session_store :cookie_store, { :key => "_example_session", :httponly => true, :secure

    => Config.force_ssl?, :expire_after => 1.hour } Rails.application.configure do config.force_ssl = Config.force_ssl? end config/environments/production.rb config/initializers/session_store.rb
  34. UTILIZE OUTRO TIPO DE STORAGE DE SESSÃO Usar cookies é

    prático, mas pode introduzir falhas de segurança.
  35. config/initializers/session_store.rb Rails.application.config.session_store :redis_session_store, { key: '_myapp-session', secure: Config.force_ssl?, redis: {

    expire_after: 1.hour, key_prefix: 'myapp:session:', url: Config.session_redis_url } } https://github.com/roidrage/redis-session-store
  36. DEFINA A EXPIRAÇÃO DA SESSÃO POR INATIVIDADE Isso pode diminuir

    o engajamento de usuários em sites de redes sociais.
  37. ADICIONE AUTENTICAÇÃO DE DOIS FATORES Dê incentivos para que os

    usuários ativem esse fator extra de autenticação.
  38. NUNCA CONFIE EM DADOS ENVIADOS PELO USUÁRIO Se veio do

    usuário, então o dado é inseguro.
  39. params[:name] = "' OR 1=1) --" Project.where("name = '#{params[:name]}'") #=>

    SELECT "projects".* FROM "projects" WHERE (name = '' OR 1=1) --')
  40. NUNCA CONFIE EM DADOS ENVIADOS PELO USUÁRIO Se veio do

    usuário, então o dado é inseguro.
  41. A WEB É UM LUGAR EXTREMAMENTE HOSTIL 1. Sempre assuma

    que sua aplicação pode sofrer ataques a qualquer instante.
  42. ACOMPANHE SITES DE SEGURANÇA 2. E garanta que o software

    que você é atualizado frequentemente.
  43. A SUA CREDIBILIDADE ESTÁ EM JOGO 3. Não arrisque algo

    que sua empresa demorou para conquistar.