Criando APIs seguras

Quem sou eu?

Vinícius Campitelli

Vinícius Campitelli

Agenda

  • Autenticação e autorização
  • Melhores práticas com access tokens
  • Throttling e Rate Limiting
  • Camuflagem de IDs sequenciais
  • Criptografando e assinando requisições e respostas

Autenticação e autorização

Autenticação

É o ato de estabelecer ou confirmar algo (ou alguém) como autêntico (...)
Fonte: Wikipedia

Autenticação

Para autenticar algo ou alguém, precisamos de uma credencial que o identifique.
Ela precisa ser emitida por algo (ou alguém) que o autorizador confie.

“O que você sabe”

Autenticação baseada no conhecimento

Exemplos:
  • Usuário e senha
  • Certificado digital
  • Client ID e Client Secret

“O que você tem”

Autenticação baseada na propriedade

Exemplos:
  • Um token ou cartão físico
  • Um código enviado por SMS ou aplicativo

“O que você é”

Autenticação baseada na característica

Exemplos:
  • Impressão digital
  • Identificação de íris
  • Reconhecimento facial
  • Reconhecimento de voz

Autorização

É garantir que apenas usuários autorizados consumam os recursos protegidos de um sistema computacional
Fonte: Wikipedia

Autorização

Após saber quem é o cliente no processo de Autenticação, preciso agora entender o que ele pode fazer. Quais recursos ele pode consumir? Por quanto tempo?

Como efetuar autenticação e autorização?

Para autenticação, podemos utilizar o OpenID ou implementar nosso próprio sistema (por exemplo, através do banco de dados).

OAuth 2.0 é o protocolo mais conhecido de autorização. Ele, por si só, não contempla processos de autenticação.

Famosa tela de Autorização via OAuth 2

Utilizando o Grant de Authorization Code
(saiba como escolher o Grant Type certo nesse link)

Tela de exemplo do fluxo de Authorization Code do OAuth 2.0 do Google
Referência: Shotgun Debugging
Referências

Melhores práticas com access tokens

O que é um access token?

É um objeto que descreve o contexto de segurança de um processo (...)
Fonte: MSDN

E no mundo de APIs?

O processo de autenticação e autorização pode ser caro computacionalmente (consultas a banco de dados, servidores de autenticação externos, criptografia de senha etc)

E no mundo de APIs?

Ao invés de sempre termos essa carga a cada requisição a nossos servidores, podemos ter um único endpoint de autenticação / autorização que irá realizar essa etapa uma vez e gerar um access token com as informações necessárias para autenticar e autorizar mais rapidamente o cliente nas requisições seguintes

E no mundo de APIs?

Esse token deve possuir um tempo de vida limitado, tanto para diminuir efeitos colaterais caso haja um vazamento quanto porque sua informação pode ficar desatualizada

E no mundo de APIs?

Esse segundo processo pode ser automatizado através de refresh tokens

Eles são utilizados para regerar um access token automaticamente, sem necessitar da intervenção manual do usuário

Como deixar os tokens seguros?

  • Utilizando algoritmos de criptografia seguros e com assinatura;
    • AES-256-GCM, ChaCha20+Poly1305, Ed25519 entre outros
  • Tendo cuidado com implementações de bibliotecas com falhas de segurança;

Como deixar os tokens seguros?

  • Não faça commit de chaves e outros segredos, nem deixe-os hardcoded na aplicação
  • Não guarde informações muito sensíveis (como senhas e outras credenciais)
  • Se precisar armazenar do lado do cliente, utilize cookies seguros (flags httpOnly e secure) ao invés do LocalStorage

Como deixar os tokens seguros?

  • Apenas trafegue tokens no cabeçalho ou corpo da requisição, nunca na URL
  • Não exiba informações do token em seus logs
  • Referências

    Throttling e Rate Limiting

    O que é Throttling?

    É a desaceleração intencional do processamento de uma requisição para prevenir sobrecarga do servidor

    O que é Throttling?

    Imagine um endpoint que consuma grande recursos computacionais (como, por exemplo, o processo de autenticação e autorização descritos anteriormente)

    O que é Throttling?

    Se um agente malicioso identificar esse recurso, ele pode se tornar muito visado para ataques, causando sobrecarga no nosso servidor e podendo gerar paralisação e até queda total do serviço

    O que é Throttling?

    Nesses casos, podemos configurar que o servidor irá aceitar somente x requisições em algum(ns) endpoint(s) por um certo período de tempo

    O que é Throttling?

    Após esse valor x, as requisições entrarão em uma fila para serem processadas alguns instantes depois, assim que as primeiras tiverem sido liberadas

    Mas então o que é Rate Limiting?

    Ao contrário do Throttling, em a requisição será processada com um atraso, Rate Limiting é fazer o servidor se recusar a responder após um certo número de requisições

    Mas então o que é Rate Limiting?

    Nesses casos, devemos emitir um status HTTP 503 Service Unavailable ou 429 Too Many Requests

    Como essas duas práticas se relacionam entre si?

    Geralmente, primeiro aplicamos uma política de Throttling para desacelerar o processamento nas x primeiras requisições, e após um outro número y, iremos simplesmente parar de responder

    Onde e como configurar essas políticas?

    Você deve configurá-las em seu servidor Web (por exemplo, Apache, IIS ou nginx) ou no seu serviço de DNS (por exemplo, o Cloudflare)

    Onde e como configurar essas políticas?

    Tomando como exemplo o nginx, utilizaremos o módulo ngx_http_limit_req_module (que implementa o mais conhecido algoritmo desse tipo de prática, o Leaky Bucket)

    Onde e como configurar essas políticas?

    
                                    limit_req_zone $binary_remote_addr zone=login_zone:10m rate=10r/s;
    
                                    server {
                                        location /login {
                                            limit_req zone=login_zone burst=5;
    
                                            # outras configurações padrões do meu bloco location...
                                        }
                                    }
                                

    Onde e como configurar essas políticas?

    O código anterior irá proteger nosso endpoint /login, permitindo apenas 10 requisições por segundo por IP (ou seja, 1 a cada 100ms)

    Onde e como configurar essas políticas?

    Mas também permitimos um burst, permitindo que 5 requisições extras sejam colocadas na fila de processamento antes de serem enviadas para o upstream

    Onde e como configurar essas políticas?

    Nesse caso, se recebermos de um mesmo IP 10 requisições em um período de 100ms, o que ocorrerá?

    • A 1ª requisição será processada instantaneamente
    • As 2ª, 3ª, 4ª, 5ª e 6ª requisições serão colocadas em uma fila e serão processadas sequencialmente após o término da anterior
    • As 7ª, 8ª, 9ª e 10ª requisições serão negadas
    Referências

    Camuflagem de IDs sequenciais

    O que é um ID sequencial e por que escondê-lo?

    Ao criarmos endpoints no formato /user/1, /user/2, /user/3 etc, estamos fornecendo uma informação muito valiosa sobre a quantidade de registros que possuímos daquela entidade

    O que é um ID sequencial e por que escondê-lo?

    Isso pode ser utilizado tanto por alguém mal intencionado quanto por algum competidor.

    Cuidado com espionagem industrial!

    Como resolver?

    • Crie um segundo campo na tabela com um valor único para aquele registro
      • Esse valor pode ser um GUID, um hash do ID incremental ou um valor aleatório...
    • Então, transforme o recurso /user/IdIncremental em /user/Identificador
    Referências

    Criptografando e assinando requisições e respostas

    Precaução extra

    Para usuários avançados e sistemas críticos, podemos adicionar uma camada extra de proteção: criptografar os dados da requisição e da resposta

    Precaução extra

    Mas, espera aí! Eu já uso HTTPS. Meu dados já estão sendo criptografados usando TLS.

    Precaução extra

    Após o estabelecimento do protocolo, realmente os dados transitados estão criptografados, mas ainda podemos sofrer um ataque de Man in the Middle

    Man in the Middle

    • Existem diversos hops entre o cliente e o servidor. Quem garante que todos os gateways do caminho são seguros?
    • Se você não for o administrador da sua rede local, alguém pode instalar uma Autoridade Certificadora em sua máquina e emitir certificados próprios

    Man in the Middle

    • Nem todos os sites utilizam HSTS
      • Ou seja, pode haver uma conexão HTTP antes do redirecionamento para HTTPS pelo servidor
    • Teoria da conspiração: grandes empresas possuem backdoors para bisbilhotar seu tráfego

    Precaução extra

    Antes de seguir nessa etapa, faça um Threat Modeling e certifique-se que realmente valhe a pena

    Compensa instalar um sistema de segurança de última geração em um depósito que não possui algo de extremo valor dentro?

    Precaução extra

    SIM! Meu sistema é crítico e preciso disso. Ou eu não confio em grandes corporações.

    Precaução extra

    Você pode exigir que toda requisição tenha seu corpo criptografado pelo cliente, utilizando um segredo em que só vocês dois sabem

    Precaução extra

    Por exemplo, você pode utilizar uma terceira informação fora o Client ID e o Client Secret e usá-la como chave assimétrica, ou fornecer um certificado digital para seu cliente

    Precaução extra

    Do lado do servidor, você utiliza essa informação sigilosa para descriptografar o corpo da requisição - se falhar, você emite um erro e para o processamento

    Precaução extra

    Entretanto, esse processo de descriptografia pode ser muito custoso operacionalmente, podendo ser um outro ponto de ataque DoS (lembre-se do que falamos na seção de Throttling e Rate Limiting). Você pode, então, utilizar um processo de assinatura digital além da criptografia.

    Fluxo de criptografia e assinatura

    O cliente...
    • Autentica na sua API fornecendo as credenciais
    • Para cada requisição, assina e criptografa os dados (combinação do corpo da requisição + URL);
      • Utiliza um algoritmo de hash para assinar os dados
      • Criptografa os dados mais a assinatura
      • Envia a requisição somente com os dados criptografados
    • Para cada resposta seguinte, ele deve:
      • Verificar a assinatura
      • Descriptografar o corpo

    Fluxo de criptografia e assinatura

    A cada requisição recebida, o servidor deve...
    • Verificar a assinatura
    • Descriptografar o corpo
    • Ao responder à requisição, deve assinar e criptografar os dados (combinação do corpo da requisição + URL);
      • Utiliza um algoritmo de hash para assinar os dados
      • Criptografa os dados mais a assinatura
      • Envia a requisição somente com os dados criptografados

    Concluindo...

    • Segurança não é trivial
      Segurança não é fácil
      Segurança não é para leigos
    • Nenhum sistema operante é invencível,
      mas você deve dificultar o trabalho de atacantes
    • Saiba equilibrar e avaliar a relação de custo-benefício entre segurança e usabilidade

    Obrigado!

    Slides

    QR Code

    Contato

    GitHub e Twitter