Acabe com o spam no formulário de contato

Acabe com o spam no formulário de contato6 min de leitura

Como adicionar um campo honeypot que bots preenchem e pessoas não

Adicione a qualquer formulário um honeypot que pega bots sem atrapalhar leitores de tela, teclados ou preenchimento automático, com a verificação no servidor para cada stack.

Preet SutharFundador, Ikiform

Adicione um campo de texto extra que você esconde fora da tela, tira da ordem de tabulação e envolve em aria-hidden, com um nome que nenhum navegador preenche automaticamente. Pessoas nunca o preenchem; bots que preenchem todos os campos, sim. No servidor, trate qualquer envio com valor nele como spam e responda exatamente como faria com uma mensagem real.

O que um honeypot tem de diferente

Um honeypot precisa ser duas coisas ao mesmo tempo. Para um bot lendo o HTML, deve parecer um campo normal que vale a pena preencher. Para toda pessoa, não pode existir, e isso inclui quem não usa o formulário do mesmo jeito que você: alguém com leitor de tela, alguém navegando pelo teclado, alguém cujo gerenciador de senhas preenche formulários por ele. A maioria dos bugs de honeypot vem de esquecer uma dessas pessoas, e o sintoma é uma mensagem real arquivada como spam sem alarde.

Como uma pessoa e um bot encontram o mesmo campo honeypotUma pessoa, com qualquer navegador ou tecnologia assistivaUm bot de scriptpreenche oformuláriotela, tecladoou leitor detelaarmadilhaignoradafora da tela,tabindex -1,aria-hiddenautopreenchimentoignoraum nome quenenhumnavegadorreconhecerecebidoarmadilhavazialê o HTMLacha todos oscampospreenchetodosinclusive aarmadilhaenvia nahoraspammesma respostade sucessoComo uma pessoa e um bot encontram o mesmo campo honeypotUma pessoa, com qualquer navegador ou tecnologia assistivaUm bot de scriptpreenche o formuláriotela, teclado ou leitor de telaarmadilha ignoradafora da tela, tabindex -1,aria-hiddenautopreenchimento ignoraum nome que nenhum navegadorreconhecerecebidoarmadilha vazialê o HTMLacha todos os campospreenche todosinclusive a armadilhaenvia na horaspammesma resposta de sucesso
  1. Uma pessoa preenche o formulário com o que costuma usar: tela, teclado ou leitor de tela.
  2. A armadilha está fora da tela, fora da ordem de tabulação e oculta das tecnologias assistivas, então ela nunca chega até lá.
  3. O nome dela é um que navegadores e gerenciadores de senha não preenchem, então ela fica vazia.
  4. O envio chega com a armadilha vazia e é recebido.
  5. Um bot de script lê o HTML e encontra todos os campos, inclusive a armadilha.
  6. Ele preenche todos e envia na hora.
  7. A armadilha tem valor, então o envio é spam. O bot ainda recebe uma resposta de sucesso normal.
Cada proteção da linha de cima fecha um caminho pelo qual uma pessoa real chegaria ao campo. Tire qualquer uma e a linha de cima também pode terminar em spam.

O markup

Coloque a armadilha dentro do formulário, ao lado dos campos reais, como um campo de texto comum. Um campo type="hidden" não funciona: os bots sabem que pessoas não podem editá-lo e o deixam em paz.

contact.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <div class="hp" aria-hidden="true">
    <label for="hp-field">Leave this empty</label>
    <input id="hp-field" name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </div>

  <button>Send</button>
</form>
estilos
<style>
.hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
</style>
  • aria-hidden="true" no contêiner remove o rótulo e o campo da árvore de acessibilidade, então leitores de tela não os anunciam.
  • tabindex="-1" impede que a tecla Tab pare num campo que ninguém vê.
  • O rótulo diz Leave this empty (deixe vazio). Se alguma ferramenta ainda expuser o campo, quem o ler sabe o que fazer.
  • Não adicione required. Um campo obrigatório que as pessoas não veem bloqueia todo envio honesto.

Como escondê-lo

Os bots aprenderam a pular campos obviamente ocultos. Scrapers simples ainda preenchem tudo, mas alguns conferem o atributo hidden ou um display: none inline antes de digitar. Quanto mais longe do próprio campo estiver o que o esconde, mais bots caem.

TécnicaOculto para pessoasBots que ainda pega
Atributo hidden ou display: none inlineSimSó os mais simples. É a primeira coisa que um bot mais esperto confere
Classe fora da tela na sua folha de estiloSimA maioria. O bot precisa carregar e aplicar seu CSS para perceber
opacity: 0 ou tamanho zeroQuase sempre. Algumas lupas e contornos de foco ainda o revelamA maioria, mas é mais arriscado para pessoas
Adicionado por JavaScript após o carregamentoSimBots que rodam scripts. Scrapers de HTML simples nunca o veem, então ele os deixa passar

Use a classe fora da tela da sua folha de estilo. Ela pega mais bots e é a mais segura para pessoas. Se um honeypot parar de funcionar, adicione um segundo com outro nome em vez de um truque de esconder mais esperto.

Escolha um nome que o preenchimento automático ignore

Navegadores e gerenciadores de senha preenchem campos adivinhando pelo name, id, rótulo e valor de autocomplete. autocomplete="off" é só uma dica, e alguns navegadores a ignoram em campos que parecem endereços ou dados de contato. Então quem faz o trabalho de verdade é o nome.

EvitePor quêUse no lugar
email2, phone, name, addressO preenchimento automático os reconhece e os preenche para pessoas reais_gotcha, company_website
honeypot, trap, botAlguns bots pulam campos com nomes óbviosUm nome sem graça e plausível
url, website sozinhosAlgumas ferramentas de preenchimento automático preenchem um campo de site a partir de um perfil salvoUm nome composto como company_website

Confira no servidor

Um honeypot só funciona se o servidor o ler. Uma verificação no navegador é inútil, já que um bot nunca roda seu script. Quando o campo tiver valor, responda exatamente como faria com uma mensagem real e não guarde nem repasse o envio. Uma resposta diferente diz ao bot qual campo o denunciou. Os exemplos abaixo chamam a sua própria saveMessage; troque pelo que guarda ou envia a mensagem por e-mail.

Um formulário HTML simples não tem servidor próprio. Aponte-o para o Ikiform e chame a armadilha de _gotcha, ou renomeie por formulário em Honeypot field. O Ikiform faz a verificação no servidor, e a armadilha nunca é guardada como resposta.

contact.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <div class="hp" aria-hidden="true">
    <label for="hp-field">Leave this empty</label>
    <input id="hp-field" name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </div>

  <button>Send</button>
</form>
Registre em log os envios pegos na armadilha, mesmo que não os guarde. Uma contagem diária mostra se o honeypot ainda faz por merecer, e uma queda repentina a zero significa que os bots aprenderam a pulá-lo.

Como o Ikiform lida com o honeypot

Todo formulário do Ikiform tem por padrão um honeypot chamado _gotcha. Mude-o por formulário em Honeypot field nas configurações do formulário; o nome que você escolher fica reservado e nunca é guardado como resposta. Um honeypot preenchido soma 5 à pontuação de spam, o que já atinge sozinho o limite de 5.

O Ikiform não descarta o envio. Ele o mantém como spam, então se uma pessoa real cair na armadilha, você pode achar a mensagem e restaurá-la. Um envio julgado como spam recebe a mesma resposta de sucesso que um real, então o bot não aprende nada. Ele é guardado com o status spam, não dispara e-mail de notificação nem webhook, não conta no seu uso e é apagado após 30 dias. Toda segunda-feira, um workspace que bloqueou spam recebe um único e-mail de resumo com o total, os formulários mais visados e os principais motivos. A documentação de spam e a de formulários HTML têm a referência.

Confira se funciona

  1. Carregue o formulário com um leitor de tela ligado e percorra-o. A armadilha nunca é anunciada.
  2. Navegue pelo formulário com Tab. O foco vai do último campo real direto para o botão.
  3. Deixe seu navegador e seu gerenciador de senhas preencherem o formulário automaticamente. A armadilha continua vazia.
  4. Envie com o honeypot preenchido, _gotcha=bot. Ele ainda recebe uma resposta de sucesso, mas o envio é guardado como spam e não dispara e-mail nem webhook.
  5. Envie uma mensagem normal. Ela chega como recebida, sem nenhum vestígio do campo armadilha.

Pegadinhas

  • Envios em JSON. Se você monta o corpo à mão em vez de usar FormData, inclua a armadilha, ou seu servidor também a lê como vazia para os bots.
  • Construtores de formulário que renomeiam campos. Alguns construtores colocam prefixo ou renomeiam os campos. Confira o corpo enviado, não o editor, para saber o nome real da armadilha.
  • Cache. Se uma página em cache ainda tiver o nome antigo da armadilha depois que você o renomear, os envios chegam com o nome antigo e passam. Renomeie dos dois lados ao mesmo tempo.
  • Honeypots de checkbox. Uma checkbox oculta também funciona, mas leitores de tela lidam pior com checkboxes soltas do que com campos de texto. Prefira um campo de texto.
  • Uma camada só. Bots que rodam um navegador real e pulam campos invisíveis passam por qualquer honeypot. Combine-o com um limite de taxa e, se precisar, uma verificação humana.

Perguntas

Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.