Guia de vulnerabilidades de segurança em webhooks

Endpoints de webhook são URLs publicamente acessíveis que aceitam requisições HTTP de serviços externos — o que os torna uma superfície de ataque em potencial se não estiverem devidamente protegidos. Os principais riscos de segurança são ataques man-in-the-middle (interceptação de payloads não criptografados), requisições forjadas (atacantes enviando webhooks falsos), replay attacks (reenvio de requisições capturadas), exposição de PII (dados sensíveis em trânsito e em repouso) e controle de acesso insuficiente (configuração de endpoints por pessoas não autorizadas). Mitigar esses riscos exige verificação de assinatura HMAC, uso obrigatório de HTTPS, validação de timestamp, processamento idempotente e controles de acesso adequados.

Para um checklist de segurança conciso, veja o nosso checklist de segurança de webhooks. A seguir, cobrimos cada vulnerabilidade em profundidade.

Existem 3 vetores principais de ataque contra os quais você precisa se proteger, além de considerações adicionais sobre controle de acesso, trilhas de auditoria e tratamento de dados.

Proteja os seus webhooks automaticamente.

A Hookdeck verifica assinaturas de webhooks de mais de 160 provedores — para você focar no processamento, não na autenticação.

Ataque man-in-the-middle

Um ataque man-in-the-middle é uma vulnerabilidade em que um terceiro obtém acesso aos dados do seu webhook capturando e lendo a requisição. É essencial trabalhar apenas com URLs HTTPS (usando SSL) quando há dados sensíveis envolvidos. Alguns provedores, como a Shopify, impõem essa restrição, mas muitas plataformas permitem que você informe URLs não criptografadas. Com HTTPS, o conteúdo da requisição é criptografado e não pode ser lido ou usado por quem interceptar as requisições.

Embora tecnicamente não seja um ataque man-in-the-middle, também é possível informar uma URL que não pertence a você. Cabe a você garantir que a URL informada como URL de webhook aponta para o seu próprio servidor e que esse servidor também é seguro. Algumas plataformas, como a Okta, fazem uma verificação única para validar que você é de fato o dono da URL, e não enviam nenhum webhook até que essa verificação aconteça. Fora isso, audite os logs do seu servidor e as URLs de webhook configuradas para garantir que apontam para o endereço correto.

Requisições forjadas

Uma requisição forjada é uma requisição feita ao seu endpoint de webhook que se passa pela origem original (por exemplo, a Shopify), mas contém dados falsos. É crítico garantir que agentes maliciosos não causem efeitos colaterais nos seus sistemas enviando requisições forjadas aos seus endpoints. Existem várias estratégias para verificar que a requisição não vem de um impostor, sendo a verificação de assinatura a abordagem mais popular e segura.

Verificação de assinatura

Plataformas que assinam os seus webhooks podem ser verificadas comparando um valor presente nos headers (por exemplo, a Shopify inclui um header X-Shopify-Hmac-Sha256) com um HMAC calculado a partir de uma chave secreta e do conteúdo do payload do webhook. Ao gerar um Hash-based message authentication code (HMAC), você precisa usar o conteúdo do payload junto com a chave secreta que a plataforma fornece quando você cria uma assinatura de webhook. Se o header e a sua assinatura calculada coincidirem, você pode ter certeza de que a mensagem foi realmente enviada pelo provedor esperado.

Isso funciona porque só você e a plataforma têm acesso a essa chave secreta e conseguem calcular um hash idêntico. Ao incluir o corpo do payload no hash, você também garante que ele não foi adulterado. Caso esse segredo vaze, substitua-o o quanto antes.

Provedores diferentes usam algoritmos de hashing diferentes (SHA256, SHA128, MD5 etc.), e a sua implementação deve usar o mesmo algoritmo. Muitas plataformas também oferecem SDKs que já incluem a lógica de verificação, poupando você da maior parte do trabalho.

Exemplo de verificação de webhook da Shopify em JavaScript

Para começar a adicionar a verificação de webhook ao servidor, execute o seguinte comando:

$ npm install raw-body

O módulo raw-body que acabamos de instalar ajuda a processar o corpo da requisição recebida de uma forma que pode ser usada para gerar o hash. O módulo body-parser padrão que vem com o Express também poderia ser usado no lugar do pacote raw-body.

Em seguida, importe os pacotes raw-body e crypto no projeto adicionando as seguintes linhas de código:

const getRawBody = require("raw-body");
const crypto = require("crypto");

O módulo crypto será usado para gerar o hash a partir do corpo da requisição e da chave secreta fornecida pela Shopify.

Substitua o handler de requisições app.post criado acima por este:

app.post("/webhook", async (req, res) => {
  //Extract X-Shopify-Hmac-Sha256 Header from the request
  const hmacHeader = req.get("X-Shopify-Hmac-Sha256");

  //Parse the request Body
  const body = await getRawBody(req);
  //Create a hash based on the parsed body
  const hash = crypto
    .createHmac("sha256", secret)
    .update(body, "utf8", "hex")
    .digest("base64");

  // Compare the created hash with the value of the X-Shopify-Hmac-Sha256 Header
  if (hash === hmacHeader) {
    console.log("Notification Requested from Shopify received");
    res.sendStatus(200);
  } else {
    console.log("There is something wrong with this webhook");
    res.sendStatus(403);
  }
});

No código acima, extraímos o header HTTP X-Shopify-Hmac-SHA256 da requisição, criamos um hash com o algoritmo Hmac-SHA256 a partir do corpo da requisição e comparamos os dois hashes.

Importante: use comparação em tempo constante. O exemplo acima usa === por simplicidade, mas em produção você deve usar uma função de comparação em tempo constante, como crypto.timingSafeEqual(), para evitar timing attacks, em que um atacante deduz a assinatura correta byte a byte com base no tempo de resposta:

const isValid = crypto.timingSafeEqual(
  Buffer.from(hash),
  Buffer.from(hmacHeader)
);

Erros comuns na verificação HMAC

  • Usar comparação de strings em vez de comparação em tempo constante. O === padrão vaza informação de tempo que atacantes podem explorar.
  • Fazer o parse do corpo antes da verificação. Se você usar o middleware json() do Express antes da verificação, o corpo é processado e re-serializado — o que pode alterar a formatação e quebrar a assinatura. Sempre verifique contra o corpo bruto.
  • Usar a codificação errada. Alguns provedores enviam assinaturas em Base64, outros em hexadecimal. Garanta que a codificação de saída do seu hash corresponde ao formato do provedor.
  • Armazenar o segredo de forma insegura. Nunca deixe segredos de webhook fixos no código-fonte. Use variáveis de ambiente ou um gerenciador de segredos.

Por fim, crie uma constante chamada secret que guardará o valor do segredo que a Shopify devolveu quando você criou a nova conexão de webhook. É recomendável armazená-lo como variável de ambiente para mantê-lo seguro.

Segredos

Como alternativa, você pode encontrar plataformas com a opção de adicionar headers personalizados às requisições de webhook, ou um header de autenticação básica. Nesse caso, você deve gerar a sua própria chave secreta, defini-la como header e verificá-la do seu lado. Isso é parecido com o funcionamento da maioria das autenticações de API e é considerado seguro quando usado sobre HTTPS. No entanto, não dependa dessa estratégia em HTTP puro, porque qualquer man-in-the-middle poderia roubar o seu segredo e forjar requisições autenticadas.

Whitelisting de IPs

Se a plataforma que publica os webhooks fornece uma lista dos IPs de onde envia as requisições, você pode configurar o endpoint receptor para aceitar apenas requisições desses IPs. Isso costuma ser simples, mas depende da plataforma em que você hospeda a sua aplicação. Embora o whitelisting de IPs seja eficaz, também pode ser trabalhoso, porque você precisa manter a lista atualizada. Se o provedor adicionar um endereço IP e você não atualizar a lista, corre o risco de recusar payloads. Por isso, essa estratégia deve ser um complemento às demais listadas acima. Fazer whitelisting de IPs não é um requisito para se proteger contra requisições forjadas.

Replay attacks

Mesmo com as duas vulnerabilidades anteriores resolvidas, você continua suscetível a replay attacks. Em tese, um agente malicioso poderia interceptar uma requisição criptografada com verificação de assinatura e simplesmente reenviá-la ou fazer requisições idênticas. Ainda que não conseguisse ver nem alterar nenhum dado, ele poderia causar efeitos colaterais indesejados, como criar múltiplos pedidos após um webhook de "Payment Captured". Isso limita as consequências possíveis desse tipo de ataque, mas ainda assim existem soluções práticas para se proteger.

Assinaturas com timestamp

Alguns provedores de webhooks, como a Stripe, incluem um timestamp dentro da assinatura. O timestamp usado no momento da assinatura fica no header e pode ser comparado com uma janela de tempo definida por você. O SDK da Stripe tem uma tolerância padrão de 5 minutos. Esse mesmo timestamp precisa ser anexado à assinatura antes de ela ser hasheada.

Para implementar a validação de timestamp:

  1. Extraia o timestamp do header do webhook
  2. Compare-o com a hora atual do servidor
  3. Rejeite requisições em que a diferença ultrapassa a sua janela de tolerância (normalmente 5 minutos)
  4. Garanta que o relógio do seu servidor está sincronizado via NTP para evitar rejeições indevidas

Observação: a validação de timestamp pode entrar em conflito com os retries de webhooks. Se um provedor reenviar um webhook depois de passada a sua janela de tolerância, a checagem de timestamp vai rejeitar a nova tentativa. Considere isso ao definir a tolerância — ou apoie-se na idempotência como principal proteção contra replay.

Verificação de nonce

Alguns provedores incluem um nonce único (identificador de uso único) em cada entrega de webhook. Ao registrar quais nonces você já processou, é possível rejeitar qualquer requisição que reutilize um nonce já visto. Isso é mais robusto do que a validação de timestamp sozinha, porque captura replays mesmo dentro da janela de tolerância. Em compensação, exige manter um armazenamento dos nonces processados — parecido com o rastreamento de idempotency keys.

Idempotência

Idempotência é um conceito central no trabalho com webhooks: se você já garantiu que os seus endpoints são idempotentes, um replay attack não vai afetá-lo. Ao tornar o endpoint idempotente, você garante que qualquer webhook seja processado apenas uma vez, mesmo que chegue várias vezes. Esse é um caso importante de tratar independentemente de replay attacks, já que a maioria dos provedores (se não todos) opera com uma estratégia de entrega at least once. Assinaturas com timestamp se tornam desnecessárias quando a idempotência está corretamente implementada — a idempotência é a única solução para se proteger contra esses ataques se o seu provedor não oferecer assinaturas com timestamp (e a maioria não oferece).

RBAC e controle de acesso

Segurança de webhooks não se resume a verificar as requisições recebidas — inclui também controlar quem, na sua organização, pode configurar endpoints de webhook e ver os payloads.

  • Restrinja a configuração de endpoints. Apenas pessoas autorizadas devem poder criar, alterar ou excluir endpoints de webhook. Um endpoint mal configurado (apontando para a URL de um atacante) encaminharia todos os seus dados de webhook para um servidor malicioso.
  • Controle a visibilidade dos payloads. Payloads de webhook podem conter dados sensíveis de clientes. Limite quem pode ver payloads brutos nas suas ferramentas de monitoramento e use acesso baseado em papéis para restringir o acesso ao histórico de eventos.
  • Audite mudanças de configuração. Registre todas as alterações na configuração dos webhooks — quem criou ou alterou um endpoint, quando e o que mudou. Isso ajuda na investigação de incidentes e no compliance.

Com a Hookdeck, o acesso do time é controlado por papéis da organização, e todas as mudanças de configuração são registradas no dashboard.

Trilhas de auditoria

Para compliance e resposta a incidentes, mantenha uma trilha de auditoria completa da atividade dos webhooks:

  • Registre cada webhook recebido com timestamp, origem, resultado da verificação de assinatura e desfecho do processamento. Isso é essencial para a análise forense após um incidente de segurança.
  • Acompanhe as tentativas de entrega, incluindo todos os retries, códigos de resposta e tempos. Isso ajuda a distinguir retries legítimos de replay attacks.
  • Retenha os logs pelo período exigido pelo seu compliance. Serviços financeiros, saúde e outros setores regulados podem exigir a retenção dos logs de auditoria de webhooks por períodos específicos.

A Hookdeck mantém automaticamente uma trilha de auditoria completa de todos os eventos de webhook, das tentativas de entrega e dos seus resultados — pesquisável e filtrável no dashboard ou via API.

Tratamento de PII em payloads de webhooks

Payloads de webhooks frequentemente contêm informações pessoalmente identificáveis (PII) — e-mails de clientes, telefones, dados de pagamento, endereços. Tratar esses dados com segurança é uma questão tanto de segurança quanto de compliance.

Dados em trânsito:

  • Use sempre endpoints HTTPS — nunca aceite webhooks sobre HTTP não criptografado quando os payloads contêm PII
  • Avalie se você realmente precisa dos dados completos no payload. Alguns provedores permitem receber notificações leves (apenas o tipo de evento e o ID do recurso) e buscar os dados completos pela API deles — reduzindo a exposição de PII em trânsito

Dados em repouso:

  • Fique atento a onde os payloads são armazenados — o seu sistema de logs, as ferramentas de monitoramento e os serviços de rastreamento de erros podem todos manter cópias
  • Implemente redação de logs para campos sensíveis (números de cartão de crédito, documentos de identificação etc.)
  • Aplique políticas de retenção adequadas aos dados de eventos de webhook

Considerações de compliance:

  • GDPR, HIPAA, PCI-DSS e outras regulamentações podem reger como você trata dados de webhooks que contêm PII
  • Garanta que o seu pipeline de processamento de webhooks atende aos mesmos padrões de compliance do restante do seu tratamento de dados
  • Documente o fluxo de dados dos seus webhooks como parte dos seus registros de tratamento de dados

Para mais sobre como proteger todo o seu pipeline de webhooks, veja o checklist de segurança de webhooks. Para garantir que entregas duplicadas não causem efeitos colaterais relevantes para a segurança, veja como implementar idempotência em webhooks.

Como a Hookdeck ajuda

Fechar todas as vulnerabilidades de segurança listadas neste guia exige mais do que saber que elas existem — significa implementar corretamente verificação de assinatura, proteção contra replay e validação de requisições para cada provedor que você integra, e manter essa implementação em dia conforme os provedores mudam. Um único descompasso significa rejeitar webhooks legítimos ou, pior, aceitar webhooks forjados (e o custo de manutenção cresce a cada novo provedor integrado).

O Event Gateway da Hookdeck cuida da verificação de assinatura de mais de 160 provedores de webhooks desde o primeiro dia. Você seleciona o provedor, informa o segredo de assinatura, e toda requisição recebida é verificada na borda antes de chegar à sua aplicação; requisições não verificadas são rejeitadas automaticamente. Isso significa que os seus handlers podem confiar em todo payload que chega, sem que você mantenha lógica de verificação específica por provedor nem persiga mudanças no esquema de assinatura de cada um. Comece com a Hookdeck e delegue a autenticação de webhooks em minutos.

Conclusão

Webhooks, quando usados corretamente, são muito seguros. Como na maioria das coisas, a responsabilidade recai sobre você para garantir a verificação correta das assinaturas, o uso de HTTPS, a implementação de idempotência e a gestão dos controles de acesso. A Hookdeck resolve boa parte dessas preocupações no nível da infraestrutura — incluindo verificação de assinatura, entrega criptografada, controles de acesso do time e trilhas de auditoria completas — para você focar na lógica da sua aplicação.

FAQs

Quais são os principais riscos de segurança dos webhooks?

Os principais riscos são ataques man-in-the-middle (interceptação de payloads não criptografados), requisições forjadas (atacantes enviando webhooks falsos para o seu endpoint), replay attacks (reenvio de requisições capturadas para provocar processamento duplicado), exposição de PII (dados sensíveis nos payloads) e controle de acesso insuficiente (pessoas não autorizadas configurando endpoints de webhook).

Como eu verifico assinaturas de webhooks?

Use verificação de assinatura HMAC. O provedor inclui nos headers da requisição uma assinatura calculada a partir do payload e de um segredo compartilhado. Você recalcula a assinatura com o mesmo algoritmo e o mesmo segredo e, então, compara usando uma função de comparação em tempo constante para evitar timing attacks. Se coincidirem, a requisição é autêntica e não foi adulterada.

O que é um replay attack em webhooks?

Um replay attack acontece quando um atacante captura uma requisição de webhook válida e assinada e a reenvia para provocar processamento duplicado. Previna isso com validação de timestamp (rejeite requisições com mais de 5 minutos) e processamento idempotente (registre os IDs de webhook já processados para detectar e ignorar duplicatas).

Como proteger dados sensíveis nos payloads de webhooks?

Use sempre endpoints HTTPS, reduza ao mínimo os dados sensíveis incluídos nos payloads (envie IDs em vez de registros completos quando possível), criptografe campos sensíveis no nível da aplicação se necessário e implemente controles de acesso sobre quem pode ver os payloads nas suas ferramentas de monitoramento. Para dados sujeitos a compliance, considere políticas de log que ocultem PII.

Endpoints de webhook devem exigir autenticação?

Endpoints de webhook devem sempre verificar a autenticidade das requisições recebidas, normalmente por meio de verificação de assinatura HMAC. O whitelisting de IPs pode adicionar uma camada extra de segurança, mas não deve ser o único mecanismo de autenticação. Nunca dependa de segurança por obscuridade (URLs secretas) como única proteção.

Como funciona a verificação HMAC em webhooks?

A verificação HMAC (Hash-based Message Authentication Code) funciona calculando um hash do payload do webhook usando uma chave secreta compartilhada e um algoritmo de hashing (normalmente SHA-256). O provedor calcula esse hash no envio e o inclui em um header. Você calcula o mesmo hash ao receber e compara. Se coincidirem, o payload é autêntico e não foi adulterado.