Boas práticas de segurança para webhooks
Gints Dreimanis
6 de julho de 2022
0 minutos de leituraWebhooks são uma das melhores maneiras de transferir informações sobre eventos pontuais de um sistema para outro. Diferentemente de métodos como a consulta periódica via HTTP — em que o cliente solicita informações repetidamente ao servidor —, os webhooks são acionados por eventos.
Isso torna os webhooks simples e eficazes. Um cliente pode se inscrever em um webhook para enviar uma mensagem a um endpoint sempre que um evento específico acontecer.
Mas, como os webhooks geralmente envolvem o envio de mensagens para um endpoint público na internet, podem surgir problemas de segurança. Sem as medidas de proteção adequadas, um invasor pode ler e alterar mensagens ou até mesmo se passar por você. Por isso, precisamos tomar todas as medidas possíveis para alcançar o nível de segurança necessário ao executar um serviço de webhook.
Neste artigo, vamos apresentar as práticas mais eficazes para proteger webhooks e compartilhar dados entre aplicações sem criar uma grande superfície de ataque.
8 boas práticas de segurança para criar webhooks
Ao implementar um webhook, é melhor não depender de uma única prática de segurança. Em vez disso, devemos adotar várias abordagens para manter nosso sistema seguro — mesmo que um invasor consiga superar algumas das nossas medidas de proteção.
No mínimo, devemos usar criptografia para manter privadas as mensagens trocadas com os clientes e autenticação mútua para que o cliente e o servidor tenham certeza de com quem estão se comunicando.
Criptografe os dados enviados por webhooks
Embora não possamos impedir que agentes mal-intencionados interceptem nossas mensagens, podemos impedir que leiam o conteúdo. Uma maneira simples de garantir que toda a comunicação seja segura é usar HTTPS em vez de HTTP.
Usar HTTPS é muito fácil e há poucos ou nenhum motivo para não utilizá-lo. O HTTPS criptografa todos os dados, dificultando muito o acesso de terceiros.
Adicione uma assinatura digital aos webhooks
Agentes mal-intencionados podem interceptar mensagens enviadas pela internet e alterar o conteúdo para benefício próprio. Para evitar mudanças indesejadas, devemos assinar nossas mensagens. Podemos fazer isso usando um código de autenticação de mensagem baseado em hash (HMAC), que combina um algoritmo de hash com um código ou chave secreta compartilhada pelas duas partes.
Os hashes HMAC (ou códigos de embaralhamento) atribuem uma função de hash específica a cada mensagem. Isso permite que quem recebe o webhook verifique a autenticidade e a integridade da mensagem, comparando-a com o hash.
Saiba mais sobre como assinar webhooks neste artigo útil da Twilio.
Autentique as conexões
Os endpoints de webhook costumam ser públicos e acessíveis a qualquer pessoa na internet. Essa disponibilidade cria várias vulnerabilidades para quem recebe webhooks, incluindo ataques de negação de serviço. Para resolver esse problema, quem recebe webhooks deve autenticar a origem das mensagens. É possível autenticar as origens com um nome de usuário e uma senha ou com um token de autenticação.
Além disso, é recomendável autenticar quem recebe a mensagem para garantir que ela chegue ao destino certo.
Adicione carimbos de data e hora à sua mensagem
Podemos incluir o horário de envio nas mensagens para ajudar a evitar ataques de repetição. Esses ataques não leem nem manipulam as mensagens, mas podem capturar uma mensagem legítima e criptografada e reenviá-la em um momento oportuno.
Ao incluir carimbos de data e hora nas mensagens, permitimos que o cliente confirme que a mensagem recebida é atual, e não algo que enviamos algumas semanas atrás. Como as mensagens também são assinadas, o invasor não pode alterar o horário nem guardar a mensagem para realizar um ataque de repetição.
Use fixação de certificados
Se nosso cliente receber uma conexão de um servidor web com um certificado confiável para nossa API, isso não significa que o site (e o certificado) sejam nossos. Um possível invasor pode fazer uma cópia da nossa API e adicionar a ela um certificado confiável. Depois, pode interceptar a mensagem legítima e enviar uma mensagem própria em seu lugar.
Uma maneira de resolver esse problema é usar a fixação de certificados. Se o evento vier sempre do mesmo servidor, o cliente pode fixar o certificado desse servidor no código. Fixar o certificado significa inserir o próprio certificado ou seu hash (impressão digital) diretamente no aplicativo e compará-lo com o certificado apresentado sempre que uma conexão for estabelecida.
No entanto, precisamos ter cuidado com essa técnica, pois ela depende de parâmetros definidos diretamente no código. Se um certificado for alterado ou revogado, talvez o cliente não consiga atualizá-lo a tempo.
Veja um exemplo de fixação de certificados nesta documentação da Mozilla.
Não use webhooks para dados confidenciais
Mesmo quando protegidos, os webhooks não são adequados para dados confidenciais, como senhas ou informações de cartão de crédito. Em geral, eles servem para enviar notificações sobre eventos. Se você estiver incluindo dados confidenciais nas mensagens enviadas por webhooks, reconsidere esse uso.
Registre todas as mensagens enviadas por webhooks
Podemos registrar as mensagens de webhook com uma solução interna ou de terceiros. Os registros ajudam a documentar todas as mensagens enviadas, o que é útil durante auditorias. Além disso, em caso de incidente de segurança, podemos consultar todas as mensagens enviadas e as conexões iniciadas. Monitorar os registros também pode ajudar a identificar comportamentos suspeitos — como tentativas de entrega malsucedidas — antes que ocorra um incidente de segurança.
O registro das mensagens de webhook também ajuda a aumentar a eficiência. Por exemplo, podemos cancelar a inscrição de usuários que não recebem nossas mensagens há muito tempo, mantendo a lista precisa e atualizada. Assista a este vídeo da NearForm para saber mais sobre o registro de mensagens de webhook. E, para conhecer uma boa ferramenta de registro de webhooks, confira este logger para Node.js.
Use um modelo de inscrição com datas de expiração
O ideal é permitir que os usuários definam uma data de expiração para a inscrição. Embora a data de expiração, por si só, não tenha grande impacto, usá-la em conjunto com outras práticas de segurança adiciona uma camada extra de proteção.
Quando combinamos diferentes métodos de criptografia, autenticação e autorização, limitar por quanto tempo um servidor ou cliente mantém privilégios ajuda a criar uma proteção em camadas. Além disso, as datas de expiração reduzem o período que um agente mal-intencionado tem para encontrar uma brecha na segurança (como credenciais roubadas), já que o cliente precisa passar pelo processo de inscrição novamente quando ela expira.
Como estabelecer a segurança de webhooks
Criptografar as mensagens de webhook é a base para permitir que os clientes validem as mensagens. Outras práticas de segurança complementam esse princípio e, quando combinadas, oferecem uma proteção mais completa.
Lembre-se de que o objetivo dos webhooks geralmente é informar os clientes sobre eventos que acontecem no seu sistema. A maioria desses eventos, como novas solicitações de PR no GitHub ou novos seguidores de assinantes, deve ser inofensiva; por isso, os invasores não terão muito interesse em adulterar essa comunicação. Recomendamos evitar o envio de dados altamente confidenciais por webhooks.
Uma abordagem abrangente de segurança começa pela escolha de medidas adequadas ao domínio da sua aplicação e à natureza das informações enviadas. Atualizações sobre eventos futuros, por exemplo, exigem menos medidas de segurança do que mensagens com informações detalhadas sobre clientes específicos. Ao adaptar sua abordagem e estabelecer várias camadas de proteção, você pode ter mais confiança de que seu código e os dados dos clientes estão protegidos contra os diversos tipos de vulnerabilidade que vemos hoje.
