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

Criando aplicações web mais seguras

Cb5d9e9095cd41b636764a85e57ade4b?s=47 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.

Cb5d9e9095cd41b636764a85e57ade4b?s=128

Nando Vieira

September 23, 2015
Tweet

Transcript

  1. @fnando CRIANDO APLICAÇÕES WEB MAIS SEGURAS

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

    ambiente realmente assustador. http://fnando.me/1c6
  3. USE UM FRAMEWORK WEB ESTABELECIDO Frameworks web possuem diversas configurações

    de segurança por padrão.
  4. BRECHAS DE SEGURANÇA EXISTEM Frameworks podem conter falhas de segurança

    desconhecidas.
  5. DEVS INTRODUZEM FALHAS DE SEGURANÇA Também temos responsabilidade pelo código

    que escrevemos.
  6. NANDO VIEIRA

  7. None
  8. None
  9. OWASP Open Web Application Security Project https://www.owasp.org

  10. 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
  11. INTRODUÇÃO DESTES CONCEITOS Como esses vetores de ataque funcionam e

    como se previnir.
  12. A10 REDIRECIONAMENTOS NÃO VALIDADOS http://fnando.me/1ca

  13. /dashboard login?return=/dashboard /dashboard

  14. None
  15. VALIDE OS HOSTS PERMITIDOS Ou simplesmente ignore-os.

  16. 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
  17. 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
  18. 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
  19. None
  20. A9 UTILIZAÇÃO DE COMPONENTES COM VULNERABILIDADES CONHECIDAS http://fnando.me/1cb

  21. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160

  22. http://xkcd.com/1354

  23. http://xkcd.com/1354

  24. http://xkcd.com/1354

  25. http://xkcd.com/1354

  26. http://xkcd.com/1354

  27. http://xkcd.com/1354

  28. Received heartbeat response: 0000: 02 40 00 D8 03 00

    53 43 5B 90 9D 9B 72 0B BC 0C .@....SC[...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
  29. Received heartbeat response: 0000: 02 40 00 D8 03 00

    53 43 5B 90 9D 9B 72 0B BC 0C .@....SC[...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
  30. ATUALIZE TÃO RÁPIDO QUANTO POSSÍVEL Não demore para corrigir falhas

    que são potencialmente destrutivas.
  31. ATUALIZE O SOFTWARE QUE VOCÊ USA Esta deve ser uma

    tarefa constante de seu projeto.
  32. A8 CROSS-SITE REQUEST FORGERY http://fnando.me/1cc

  33. Envia formulário Transfere $$$

  34. <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>
  35. <img src="http://seusite.com/transfer?to=4567&from=1234&amount=100000" alt="">

  36. USE NON-GET PARA AÇÕES QUE MUDAM O ESTADO Nunca utilize

    GET para ações que causam efeito colateral.
  37. <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>
  38. USE TOKEN DE SEGURANÇA NO FORMULÁRIO Rejeite qualquer alteração que

    não tiver um token válido.
  39. <form action="/transfer" method="post"> <input type="hidden" value="55be2d4a26"> <!-- ... --> <input

    type="submit" value="Transferir"> </form>
  40. <form action="/transfer" method="post"> <input type="hidden" value="55be2d4a26"> <!-- ... --> <input

    type="submit" value="Transferir"> </form>
  41. A7 AUSÊNCIA DE CONTROLE DE ACESSO http://fnando.me/1cd

  42. AUTENTICAÇÃO Validar se você é quem você diz ser. AUTORIZAÇÃO

    Validar o que você pode fazer baseado em quem você é.
  43. VALIDE O NÍVEL DE PERMISSÃO Garanta que somente quem permissão

    pode acessar páginas restritas.
  44. class AdminPolicy < PermissionPolicy ALLOWED_EMAIL = /\A[^@]+@example\.com\z/ def permit?(user) user

    && user.email.match(ALLOWED_EMAIL) end end AdminPolicy.permit?(current_user)
  45. 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
  46. A6 EXPOSIÇÃO DE DADOS SENSÍVEIS http://fnando.me/1ce

  47. 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.
  48. Rails.application.config.filter_parameters += [ :password, :api_key, :credit_card_number, :credit_card_cvv ]

  49. CRIPTOGRAFE DADOS SENSÍVEIS Garanta que os dados são criptografados no

    nível da aplicação.
  50. USE UM ALGORITMO APROPRIADO PARA SENHAS Não utilize algoritmos de

    hashing como MD5, SHA1 e semelhantes.
  51. 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
  52. 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
  53. 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
  54. 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
  55. SALVAR HASHES SEM SALT NÃO AJUDA MUITO Rainbow tables possuem

    muitas senhas e a probabilidade de você encontrar senhas comuns ali é alta.
  56. A5 CONFIGURAÇÃO INCORRETA DE SEGURANÇA http://fnando.me/1cf

  57. EM PRODUÇÃO USE O AMBIENTE DE PRODUÇÃO Certifique-se que definiu

    as variáveis de ambiente RAILS_ENV e RACK_ENV.
  58. PROTEJA PAINÉIS DE ADMINISTRAÇÃO Garanta que todos os painéis exigem

    autenticação e autorização.
  59. None
  60. CONTRATE UM SYS ADMIN COMPETENTE Administrar um servidor corretamente é

    muito mais difícil do apenas fazer sua aplicação executar.
  61. A4 REFERÊNCIA INSEGURA E DIRETA A OBJETOS http://fnando.me/1cg

  62. UTILIZE IDENTIFICADORES NÃO SEQUENCIAIS Identificadores sequenciais são fáceis de modificar.

  63. #BREAKING: Twitter $TWTR Q1 Revenue misses estimates, $436M vs. $456.52M

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

    default uuid_generate_v4(), title text not null )
  65. create_table :proposals, id: :uuid do |t| t.text :title, null: false

    end
  66. VALIDE A PERMISSÃO DE USUÁRIOS Garanta que o usuário pode

    acessar apenas o que ele deve.
  67. class ProposalsController < ApplicationController def edit @proposal = Proposal.find(params[:id]) end

    end
  68. class ProposalsController < ApplicationController def edit @proposal = current_user.proposals.find(params[:id]) end

    end
  69. class ProposalsController < ApplicationController def edit @proposal = current_user.proposals.find(params[:id]) end

    end
  70. A3 CROSS-SITE SCRIPTING http://fnando.me/1ch

  71. 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.
  72. USE TEMPLATE ENGINE COM AUTOESCAPING E evite desabilitar o escapamento

    de HTML de sua template engine.
  73. FAÇA O ESCAPAMENTO DO CONTEÚDO NO JAVASCRIPT Se o dado

    veio do usuário, então não renderize-o como HTML.
  74. $.getJSON("/info", function(profile){ $(".profile").html(profile.bio); }); $.getJSON("/info", function(profile){ $(".profile").text(profile.bio); });

  75. $.getJSON("/info", function(profile){ $(".profile").html(profile.bio); }); $.getJSON("/info", function(profile){ $(".profile").text(profile.bio); });

  76. $.getJSON("/info", function(profile){ $(".profile").html(profile.bio); }); $.getJSON("/info", function(profile){ $(".profile").text(profile.bio); });

  77. USE CONTENT SECURITY POLICY Reduz riscos de XSS ao declarar

    quais recursos podem ser carregados.
  78. http://content-security-policy.com/

  79. USE OUTROS HEADERS DE SEGURANÇA Isso ajuda previnir outros tipos

    de ataque, como defacement através de injeção de iframes.
  80. 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.
  81. MARQUE COOKIES COMO HTTP ONLY Não deixe cookies que só

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

    usuário, então o dado é inseguro.
  83. A2 QUEBRA DE AUTENTICAÇÃO E GERENCIAMENTO DE SESSÃO http://fnando.me/1ci

  84. GARANTA QUE A SESSÃO USE SSL Se a página identifica

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

    o roubo de identidades através de falhas como XSS.
  86. None
  87. None
  88. 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
  89. UTILIZE OUTRO TIPO DE STORAGE DE SESSÃO Usar cookies é

    prático, mas pode introduzir falhas de segurança.
  90. 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
  91. None
  92. None
  93. DEFINA A EXPIRAÇÃO DA SESSÃO POR INATIVIDADE Isso pode diminuir

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

    usuários ativem esse fator extra de autenticação.
  96. None
  97. https://twofactorauth.org

  98. A1 INJEÇÃO DE CÓDIGO http://fnando.me/1cj

  99. NUNCA CONFIE EM DADOS ENVIADOS PELO USUÁRIO Se veio do

    usuário, então o dado é inseguro.
  100. params[:name] = 'Basecamp' Project.where("name = '#{params[:name]}'") #=> SELECT "projects".* FROM

    "projects" WHERE (name = 'Basecamp')
  101. params[:name] = "' OR 1=1) --" Project.where("name = '#{params[:name]}'") #=>

    SELECT "projects".* FROM "projects" WHERE (name = '' OR 1=1) --')
  102. NUNCA INTERPOLE QUERIES SQL E se realmente decidir fazer isso,

    faça o escapamento dos parâmetros.
  103. params[:name] = ActiveRecord::Base.sanitize("' OR 1=1) --") Project.where("name = #{params[:name]}") #=>

    SELECT "projects".* FROM "projects" WHERE (name = ''' OR 1=1) --')
  104. ActiveRecord::Base#average ActiveRecord::Base#count ActiveRecord::Base#maximum ActiveRecord::Base#minimum ActiveRecord::Base#sum ActiveRecord::Base.exists? ActiveRecord::Base.having ActiveRecord::Base.joins ActiveRecord::Base.lock ActiveRecord::Base.order

    ActiveRecord::Base.pluck ActiveRecord::Base.reorder ActiveRecord::Base.select http://rails-sqli.org
  105. NUNCA CONFIE EM DADOS ENVIADOS PELO USUÁRIO Se veio do

    usuário, então o dado é inseguro.
  106. AINDA É CEDO, PODE RESUMIR PARA MIM? tl;dw

  107. A WEB É UM LUGAR EXTREMAMENTE HOSTIL 1. Sempre assuma

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

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

    que sua empresa demorou para conquistar.
  110. @fnando OBRIGADO.