O ataque que você vai realmente sofrer

Prévia grátis 5 min de leitura

Leia a ação de login deste repositório:

# app/controllers/auth/sessions_controller.rb
def create
  result = Auth::AuthenticateUserService.call(
    email: params[:email],
    password: params[:password]
  )

  if result.success
    # Read before reset_session clears it.
    pending_link = session[:pending_partner_link]
    reset_session
    session[:user_id] = result.user.id
    ::Auth::CompletePartnerLinkService.call(user: result.user, pending: pending_link)
    redirect_to post_sign_in_path(result.user), notice: t("auth.flash.welcome_back", username: result.user.username)
  else
    @error = result.error
    flash.now[:alert] = @error
    render :new, status: :unprocessable_content
  end
end

Esse é um código cuidadoso. Usa um objeto de serviço, chama reset_session no sucesso (a defesa contra fixação de sessão do curso de OWASP) e devolve um erro genérico. Toda decisão nele está certa.

E nada nele conta. Sozinha, esta ação aceitaria dez mil tentativas por minuto de um endereço. Neste repositório a contagem mora em outro lugar: o Identity::User bloqueia uma conta depois de falhas repetidas, e o Rack::Attack limita logins por IP e por e-mail, como a aula 7 mostra. Este curso é sobre por que essas camadas existem e como escolhê-las.

O que chega

Não é um ataque direcionado. O que chega é automatizado e indiscriminado:

Tráfego O que quer O que te custa
Credential stuffing Senhas reaproveitadas de outros vazamentos Trabalho de bcrypt por tentativa, e contas
Raspadores O seu catálogo, em velocidade Carga de banco, e o seu conteúdo em outro lugar
Scanners de vulnerabilidade /wp-admin, /.env, /.git/config Ruído, e um acerto se algo estiver exposto
Enxurrada de redefinição de senha Nada: ou a reputação do seu e-mail A sua pontuação de remetente, gasta por outra pessoa
Enxurrada de cadastro Contas grátis, para spam Dados lixo e moderação

O credential stuffing merece a ênfase por causa de uma assimetria. Quem ataca não está adivinhando senhas; tem uma lista de pares reais de e-mail e senha de um vazamento alheio e está checando quais funcionam no seu site. Uma política de senha forte não ajuda: a senha é forte, e é também a que a pessoa reaproveitou.

As únicas defesas são limitar tentativas, um segundo fator, e checar contra senhas sabidamente vazadas. Este curso é a primeira.

O que é limitação de taxa

Um contador e um limiar: esta identidade, este número de requisições, nesta janela, e então pare.

flowchart LR
  R["Requisição"] --> D["Identificar: IP? conta? os dois?"]
  D --> C["Contar na janela atual"]
  C --> T{"passou do limite?"}
  T -->|"não"| A["deixa passar"]
  T -->|"sim"| B["429, com Retry-After"]

Três decisões nesse diagrama, e cada uma é uma aula: a identidade é a aula 4, o armazenamento do contador é a aula 5, a resposta é a aula 6.

O que não é

Ser claro sobre isso cedo evita uma categoria de confiança mal colocada:

  • Não é defesa contra ataque distribuído. Dez mil endereços fazendo dez requisições cada derrotam um limite por IP por completo. Limitação de taxa encarece um ataque de uma máquina; uma botnet é outro problema.
  • Não é autorização. Limitar com que frequência alguém chama um endpoint não diz nada sobre se ela deveria poder.
  • Não substitui um segundo fator. Ela desacelera o credential stuffing. A autenticação de múltiplos fatores o torna inútil.
  • Não é de graça. Toda requisição passa a tocar um contador, que é o assunto da aula 5 e é mais caro neste repositório do que você imagina.

As três camadas

A limitação de taxa acontece em três lugares, e eles são complementares e não alternativos:

Camada Exemplo Enxerga Não enxerga
Borda Cloudflare, uma CDN, um WAF de nuvem Volume, antes de te custar qualquer coisa Quem está logado, o que a ação significa
Proxy nginx, kamal-proxy Requisições, por host Conceitos da aplicação
Aplicação rate_limit do Rails, Rack::Attack A conta, a ação, o desfecho Tráfego que ela nunca recebe

A borda é onde volume é mais barato de parar, porque a requisição nem chega aos seus servidores. A aplicação é onde mora o significado: isto é um login que falhou para esta conta é uma frase que só o seu código consegue formar.

Um limite geral de borda de 100 requisições por minuto por IP não impede 20 tentativas de login por minuto, que é bastante para credential stuffing. Essa lacuna é por que este curso é sobre a camada de aplicação, e a aula 6 volta a como as camadas se combinam.

O que este curso cobre

  1. O ataque que você vai sofrer (esta aula).
  2. O rate_limit embutido do Rails.
  3. Fundamentos do Rack::Attack.
  4. Escolhendo o discriminador.
  5. O armazenamento, e o que ele custa.
  6. Respostas, observabilidade e ajuste.
  7. Juntando tudo: protegendo esta aplicação.

Pontos-chave

  • A ação de login deste repositório é bem escrita e não conta nada sozinha; os limites moram num bloqueio de conta e no Rack::Attack.
  • O credential stuffing usa senhas reais de outros vazamentos, então uma política de senha forte não defende contra ele.
  • Limitação de taxa é uma identidade, uma contagem, uma janela e um limiar: três disso são aulas seguintes.
  • Ela não impede ataques distribuídos, não substitui autorização nem um segundo fator.
  • A borda para volume barato; a aplicação é a única camada que sabe o que uma requisição significa.
Aula 1 de 7 · grátis

Continue com a aula 2

O rate_limit embutido do Rails

Mostra o método rate_limit embutido do Rails, suas opções, o uso na redefinição de senha e seus limites.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...