Slide 1

Slide 1 text

@fnando CRIANDO APLICAÇÕES WEB MAIS SEGURAS

Slide 2

Slide 2 text

75% DOS ATAQUES ACONTECEM NA WEB A web é um ambiente realmente assustador. http://fnando.me/1c6

Slide 3

Slide 3 text

USE UM FRAMEWORK WEB ESTABELECIDO Frameworks web possuem diversas configurações de segurança por padrão.

Slide 4

Slide 4 text

BRECHAS DE SEGURANÇA EXISTEM Frameworks podem conter falhas de segurança desconhecidas.

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

NANDO VIEIRA

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

OWASP Open Web Application Security Project https://www.owasp.org

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

INTRODUÇÃO DESTES CONCEITOS Como esses vetores de ataque funcionam e como se previnir.

Slide 12

Slide 12 text

A10 REDIRECIONAMENTOS NÃO VALIDADOS http://fnando.me/1ca

Slide 13

Slide 13 text

/dashboard login?return=/dashboard /dashboard

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

VALIDE OS HOSTS PERMITIDOS Ou simplesmente ignore-os.

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

A9 UTILIZAÇÃO DE COMPONENTES COM VULNERABILIDADES CONHECIDAS http://fnando.me/1cb

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

http://xkcd.com/1354

Slide 23

Slide 23 text

http://xkcd.com/1354

Slide 24

Slide 24 text

http://xkcd.com/1354

Slide 25

Slide 25 text

http://xkcd.com/1354

Slide 26

Slide 26 text

http://xkcd.com/1354

Slide 27

Slide 27 text

http://xkcd.com/1354

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

ATUALIZE TÃO RÁPIDO QUANTO POSSÍVEL Não demore para corrigir falhas que são potencialmente destrutivas.

Slide 31

Slide 31 text

ATUALIZE O SOFTWARE QUE VOCÊ USA Esta deve ser uma tarefa constante de seu projeto.

Slide 32

Slide 32 text

A8 CROSS-SITE REQUEST FORGERY http://fnando.me/1cc

Slide 33

Slide 33 text

Envia formulário Transfere $$$

Slide 34

Slide 34 text

Conta de destino
Quantia

Slide 35

Slide 35 text

Slide 36

Slide 36 text

USE NON-GET PARA AÇÕES QUE MUDAM O ESTADO Nunca utilize GET para ações que causam efeito colateral.

Slide 37

Slide 37 text

Slide 38

Slide 38 text

USE TOKEN DE SEGURANÇA NO FORMULÁRIO Rejeite qualquer alteração que não tiver um token válido.

Slide 39

Slide 39 text

Slide 40

Slide 40 text

Slide 41

Slide 41 text

A7 AUSÊNCIA DE CONTROLE DE ACESSO http://fnando.me/1cd

Slide 42

Slide 42 text

AUTENTICAÇÃO Validar se você é quem você diz ser. AUTORIZAÇÃO Validar o que você pode fazer baseado em quem você é.

Slide 43

Slide 43 text

VALIDE O NÍVEL DE PERMISSÃO Garanta que somente quem permissão pode acessar páginas restritas.

Slide 44

Slide 44 text

class AdminPolicy < PermissionPolicy ALLOWED_EMAIL = /\A[^@]+@example\.com\z/ def permit?(user) user && user.email.match(ALLOWED_EMAIL) end end AdminPolicy.permit?(current_user)

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

A6 EXPOSIÇÃO DE DADOS SENSÍVEIS http://fnando.me/1ce

Slide 47

Slide 47 text

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.

Slide 48

Slide 48 text

Rails.application.config.filter_parameters += [ :password, :api_key, :credit_card_number, :credit_card_cvv ]

Slide 49

Slide 49 text

CRIPTOGRAFE DADOS SENSÍVEIS Garanta que os dados são criptografados no nível da aplicação.

Slide 50

Slide 50 text

USE UM ALGORITMO APROPRIADO PARA SENHAS Não utilize algoritmos de hashing como MD5, SHA1 e semelhantes.

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

SALVAR HASHES SEM SALT NÃO AJUDA MUITO Rainbow tables possuem muitas senhas e a probabilidade de você encontrar senhas comuns ali é alta.

Slide 56

Slide 56 text

A5 CONFIGURAÇÃO INCORRETA DE SEGURANÇA http://fnando.me/1cf

Slide 57

Slide 57 text

EM PRODUÇÃO USE O AMBIENTE DE PRODUÇÃO Certifique-se que definiu as variáveis de ambiente RAILS_ENV e RACK_ENV.

Slide 58

Slide 58 text

PROTEJA PAINÉIS DE ADMINISTRAÇÃO Garanta que todos os painéis exigem autenticação e autorização.

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

CONTRATE UM SYS ADMIN COMPETENTE Administrar um servidor corretamente é muito mais difícil do apenas fazer sua aplicação executar.

Slide 61

Slide 61 text

A4 REFERÊNCIA INSEGURA E DIRETA A OBJETOS http://fnando.me/1cg

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

#BREAKING: Twitter $TWTR Q1 Revenue misses estimates, $436M vs. $456.52M expected Selerity @selerity https://twitter.com/Selerity/status/593129551221432320

Slide 64

Slide 64 text

CREATE TABLE proposals ( id uuid primary key not null default uuid_generate_v4(), title text not null )

Slide 65

Slide 65 text

create_table :proposals, id: :uuid do |t| t.text :title, null: false end

Slide 66

Slide 66 text

VALIDE A PERMISSÃO DE USUÁRIOS Garanta que o usuário pode acessar apenas o que ele deve.

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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.

Slide 72

Slide 72 text

USE TEMPLATE ENGINE COM AUTOESCAPING E evite desabilitar o escapamento de HTML de sua template engine.

Slide 73

Slide 73 text

FAÇA O ESCAPAMENTO DO CONTEÚDO NO JAVASCRIPT Se o dado veio do usuário, então não renderize-o como HTML.

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

USE CONTENT SECURITY POLICY Reduz riscos de XSS ao declarar quais recursos podem ser carregados.

Slide 78

Slide 78 text

http://content-security-policy.com/

Slide 79

Slide 79 text

USE OUTROS HEADERS DE SEGURANÇA Isso ajuda previnir outros tipos de ataque, como defacement através de injeção de iframes.

Slide 80

Slide 80 text

X-Frame-Options: DENY Bloqueia a renderização de frames, iframes e . 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.

Slide 81

Slide 81 text

MARQUE COOKIES COMO HTTP ONLY Não deixe cookies que só serão usados pelo servidor serem modificados pelo navegador.

Slide 82

Slide 82 text

NUNCA CONFIE EM DADOS ENVIADOS PELO USUÁRIO Se veio do usuário, então o dado é inseguro.

Slide 83

Slide 83 text

A2 QUEBRA DE AUTENTICAÇÃO E GERENCIAMENTO DE SESSÃO http://fnando.me/1ci

Slide 84

Slide 84 text

GARANTA QUE A SESSÃO USE SSL Se a página identifica usuários logados, deve necessariamente usar SSL.

Slide 85

Slide 85 text

MARQUE OS COOKIES COMO HTTP ONLY E SEGUROS Isso dificulta o roubo de identidades através de falhas como XSS.

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

No content

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

UTILIZE OUTRO TIPO DE STORAGE DE SESSÃO Usar cookies é prático, mas pode introduzir falhas de segurança.

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

No content

Slide 93

Slide 93 text

DEFINA A EXPIRAÇÃO DA SESSÃO POR INATIVIDADE Isso pode diminuir o engajamento de usuários em sites de redes sociais.

Slide 94

Slide 94 text

No content

Slide 95

Slide 95 text

ADICIONE AUTENTICAÇÃO DE DOIS FATORES Dê incentivos para que os usuários ativem esse fator extra de autenticação.

Slide 96

Slide 96 text

No content

Slide 97

Slide 97 text

https://twofactorauth.org

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

NUNCA CONFIE EM DADOS ENVIADOS PELO USUÁRIO Se veio do usuário, então o dado é inseguro.

Slide 100

Slide 100 text

params[:name] = 'Basecamp' Project.where("name = '#{params[:name]}'") #=> SELECT "projects".* FROM "projects" WHERE (name = 'Basecamp')

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

NUNCA INTERPOLE QUERIES SQL E se realmente decidir fazer isso, faça o escapamento dos parâmetros.

Slide 103

Slide 103 text

params[:name] = ActiveRecord::Base.sanitize("' OR 1=1) --") Project.where("name = #{params[:name]}") #=> SELECT "projects".* FROM "projects" WHERE (name = ''' OR 1=1) --')

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

NUNCA CONFIE EM DADOS ENVIADOS PELO USUÁRIO Se veio do usuário, então o dado é inseguro.

Slide 106

Slide 106 text

AINDA É CEDO, PODE RESUMIR PARA MIM? tl;dw

Slide 107

Slide 107 text

A WEB É UM LUGAR EXTREMAMENTE HOSTIL 1. Sempre assuma que sua aplicação pode sofrer ataques a qualquer instante.

Slide 108

Slide 108 text

ACOMPANHE SITES DE SEGURANÇA 2. E garanta que o software que você é atualizado frequentemente.

Slide 109

Slide 109 text

A SUA CREDIBILIDADE ESTÁ EM JOGO 3. Não arrisque algo que sua empresa demorou para conquistar.

Slide 110

Slide 110 text

@fnando OBRIGADO.