Formulários acessíveis à prova de spam

visualizações Publicado em: 07/04/2007

Crédito: essa matéria é uma tradução e foi escrita por Jared Smith
URL do original: http://webaim.org/blog/2007/03/07/spam_free_accessible_forms/>
Título original: Spam-free accessible forms
Traduzido com autorização do autor

Os métodos de prevenção com propósito de evitar spambots em formulários na Web é uma questão que tem sido exaustivamente discutida. Muitas soluções têm sido propostas e a maioria delas interfere diretamente em questões de usabilidade e a acessibilidade na página. A utilização de CAPTCHA é um caso clássico onde acessibilidade é diretamente impactada.

Ao longo deste último ano eu compilei algumas técnicas básicas de bloqueio de spam em formulários. Eu também implementei na prática algumas delas e constatei que houve uma considerável redução de 99% das submissões por spambots em meus formulários enquanto o impacto sobre a usabilidade e a acessibilidade foi nenhum ou muito pouco. Quase todas as técnicas experimentadas utilizam scripts rodando no servidor, e no meu caso usei PHP, conforme mostro a seguir, mas você pode usar qualquer linguagem de script rodando no servidor.

Hipótese 1: Estas técnicas de prevenção de spam podem ser ineficientes quando usadas em grandes corporações para as quais os spammers tenham sido direcionados especificamente aos seus formulários. As técnicas são eficientes para formulários de contato padrão, áreas de comentários ou registro de dados para os quais os spammers não estão programados para tentar burlar os mecanismos de prevenção.

Hipótese 2: A princípio estas técnicas bloqueiam bots e programas spam de submissão automática de formulários. Elas podem também filtrar conteúdos. Contudo não impedem que uma ação humana direta poste um spam no seu site.

As técnicas são:

  • Detecção de inserção de conteúdos típicos de spam em campos do formulário;
  • Detecção de conteúdos em campos ocultos do formulário;
  • Validação dos dados submetidos pelo formulário;
  • Procura por conteúdo repetido em múltiplos campos do formulário;
  • Geração de conteúdo dinâmico, submissão em determinado ou pelo mesmo usuário;
  • Criação de um formulário de múltiplos estágios ou uma página de verificação;
  • Certificar de que o formulário está sendo postado do seu servidor.

Detecção de inserção de conteúdos típicos de spam em campos do formulário

Está é a técnica que tem se mostrado mais efetiva na prevenção de spam. A finalidade da maioria dos spam bots é a de postar URL’s com o objetivo de aumentar o tráfego ou o page rank de um site ou com a finalidade de usar seu formulário para envio de spam não só para você como para outros (procedimento conhecido como 'hijack ' do formulário). A detecção de conteúdo típico de spam e de 'injections ' no header do e-mail normalmente é efetiva para bloquear os spambots.

A seguir mostro o código PHP que quando colocado na página de processamento do formulário (a página para a qual o formulário é enviado quando submetido) procura em todos os campos do formulário pela existência das formas mais comuns de 'injections ' em headers e outros códigos maliciosos que possam usar seu processador de email para envio de cópias carbono ou ocultas para terceiros. O código detecta ainda conteúdos e strings tipo “[url]” que são usadas tipicamente por spammers. Se for detectada qualquer uma das condições citadas a variável $spam é setada para true no código mostrado.

if (preg_match( "/bcc:|cc:|multipart|\[url|Content-Type:/i", implode($_POST))) {
$spam=true;  
}

Você pode ainda detectar links e URLs nos campos de formulário. O código a seguir seta a variável $spam para true se mais do que 3 instâncias de “<a” ou “http:” aparecer em qualquer campo do formulário.

if (preg_match_all("/<a|http:/i", implode($_POST), $out) > 3) {      
$spam=true;  
}

Estes códigos bloqueiam a maioria dos spambots cuja finalidade seja a de postar links ou 'hijack ' seu script de email. Além disto, alguns filtros básicos para palavras típicas de spam podem ser usados.

$spamwords = "/(aqui|lista|de|palavras|típicas|de|spam)/i";  
if (preg_match($spamwords, implode($_POST))) {      
$spam=true;  
}

Você pode se valer de um serviço externo de detecção de conteúdos típicos de spam para povoar seu script. O meu favorito é o Akismet. Akismet é normalmente usado como filtro de spam para comentários em blogs (ele bloqueou aproximadamente 14,000 comentários de spam neste blog nos últimos 9 meses!), mas ele pode ser usado com sucesso em quase todo formulário Web.

Detecção de conteúdos em campos ocultos do formulário

A maioria dos spambots identifica o seu formulário, determina o nome dos elementos que o compõem bem como a URL de processamento. De posse destes dados, um software modifica os elementos do formulário preenchendo-o com conteúdos e valores e em seguida submete-o à URL devida. Tipicamente o bot preenche cada um dos elementos do formulário com algum conteúdo, como forma de aumentar as chances de ser bem sucedido na submissão. Assim, se você inserir um valor determinado em um campo do formulário e esconder este campo do usuário humano de modo que ele não consiga alterá-lo é quase certo que um spambot irá alterar o valor deste campo. Valendo-se disto se seu formulário for submetido com um valor diferente do que você determinou para o campo oculto é praticamente certo que trata-se de um spambot.

Por exemplo: coloque o código mostrado abaixo no seu formulário

<span style="display:none;visibility:hidden;">  
<label for="email">
Ignore este campo de texto. Ele está aqui para detectar spammers.  
Se você entar qualquer valor neste campo, sua mensagem não será enviada.</label>  
<input type="text" name="email" size="1" value="" /></span>

Notar que usamos CSS para esconder tanto o rótulo (label) como o campo (text input) da vista do usuário humano. Este código é oculto também para os modernos leitores de tela. Contudo se as CSS estiverem desabilitadas o código será visto. Por esta razão usamos um texto esplicando a finalidade do campo e advertindo o usuário a não alterar nada no campo de texto. Eu ainda nomeie o rótulo do campo como “email” que é uma grande 'isca' para spambots e é quase certo que o campo será por eles alterado.

A partir da basta que você confira se o conteúdo do campo está vazio. Se não for vazio ou é um spambot ou é um usuário com CSS desabilitada que alterou o campo não seguindo as instruções para deixar o campo intacto.

if(!empty($_POST['email'])) $spam=true;

Está tática assim como todas as demais aqui mostradas deverá resultar em uma mensagem de erro caso a variável $spam seja setada para true.

Validação dos dados submetidos pelo formulário

Talvez não fosse necessário citar este procedimento, mas lembre-se que se existirem campos do formulário que devam ser obrigatoriamente preenchidos os valores submetidos nestes campos devem seer validados por script no lado do do servidor. Valide, por exemplo, um campo de preenchimento obrigatório que requer um formato particular (tal como um endereço de email válido). Muitos bots deixam vazio ou submetem informação randômica em certos campos que não conseguem identificar. Seus mecanismos padrão de validação conseguem bloquear muitos spambots.

// Se a mensagem está vazia setar um erro  
if(empty($_POST['message'])) $error=true;  
// se o endereço de e-mail não está formatado corretamente, mostre uma mensagem de erro  if(!eregi("^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$", $_POST['email']))) {      
echo "Por favor entre um endereço de email válido.";  
}

Procura por conteúdo repetido em múltiplos campos do formulário

Alguns spambots preenchem com um mesmo texto os campos que não conseguem identificar. Se você tem dois campos no seu formulário que nunca serão preenchidos com o mesmo conteúdo e detectar o mesmo conteúdo nos campos seu script setará um erro. No formulário de registro do nosso fórum eu constatei que simplesmente checando e setando um erro se o usuário preencheu o seu nome igual ao sobrenome 80% de registros submetidos por bots foram bloqueados. Esta não é uma técnica perfeita e você deve assegurar-se com certeza que os campos considerados realmente não podem conter o mesmo conteúdo (Eu suponho que há chances de uma pessoa ter o nome igual ao sobrenome , huh?).

if($_POST['firstname'] == $_POST['lastname']) $spam=true;

Geração de conteúdo dinâmico, submissão em determinado ou pelo mesmo usuário

Gerando dinamicamente conteúdo em elementos de formulário ou criando variáveis de sessão você poderá assegurar-se de que a pessoa que visita seu formulário é a mesma que o submete. Por exemplo: quando seu formulário é acessado você poderá usar script no lado do servidor para escrever dinamicamente a hora em um campo oculto do formulário. Quando o formulário for submetido seu script determina a hora e compara os dois horários permitindo a submissão somente se um máximo intervalo de tempo, uma hora, por exemplo, decorreu entre o acesso e a submissão. A probabilidade de um spambot gerar a hora correta no campo oculto é muito remota. Você pode também criar cookies ou valer-se de outros sistemas de sessão para determinar o intervalo de tempo entre o acesso e a submissão da página que contém o formulário.

O código a seguir escreve a hora em formato UNIX em um campo oculto de formulário.

<input type="text" name="formtime" value="<?php echo time(); ?>" />

Quando o formulário for submetido você poderá calcular o intervalo de tempo decorrido entre o acesso e a submissão usando o valor escrito no campo oculto. Se a diferença for maior que um determinado valor seu script setará como spam. No exemplo a seguir a variável de controle será setada como spam se um intervalo maior que uma hora (3600 segundos) decorrer entre o acesso ao formulário e a submissão do mesmo. O script também seta como spam se o valor para a hora for alterado para algo diferente de formatação horária tal como um endereço de email ou uma URL.

if($_POST['formtime'] < time()-3600)  {      $spam=true;  }

Criação de um formulário de múltiplos estágios ou uma página de verificação

Criando um mecanismo de múltiplas submissões para o formulário, a maioria dos spambots não conseguirá encontrar o script de processamento final dos dados submetidos. Isto é uma tarefa fácil, pois basta devolver ao usuário, para verificação, os dados submetidos e fornecer um segundo botão para submissão final. Esta técnica torna-se mais eficiente se o formulário e a página de verificação forem processados na mesma URL. Se os dados do formulário forem gravados no servidor antes da verificação final (no lugar de serem guardados em campos ocultos que possam ser acessados por spambot), torna-se muito difícil a um sistema automatizado submeter o formulário.

if($formsubmitted == true) {      
// colocar dados no banco de dados e devolver ao usuário a página de verificação.   
// Se o usuário verificar as informações fornecidas, processar os dados contidos no banco de dados.  
}  else {      
// devolver o formulário vazio  
}

Certificar de que o formulário está sendo postado do seu servidor

Considerando que a maioria dos spambots posta para o script do seu formulário a partir de um computador remoto, você pode valer-se disto para detectar spambots submetendo formulários através do seu script de processamento. Existem muitos scripts capazes de verificar a 'page referrer' ou seja, a página que está sendo usada para acessar determinada página. É importante ressaltar que é muito fácil para os spambots burlar informações de 'page referrer' para simular a que chamada do formulário está vindo do seu servidor. E, além disto, alguns navegadores e firewalls não enviam informações 'referrer header'.

O código a seguir faz a verificação se a 'page referrer' (incorretamente denominada de ‘referer’ nas especificações para HTTP e em PHP) existe e caso exista se ela encontra-se no mesmo Web Site do script de processamento. Para navegadores e spambots que não enviam informações 'referrer' a mensagem nunca será setada como spam.

if((isset($_SERVER['HTTP_REFERER']) && 
stristr($_SERVER['HTTP_REFERER'],$_SERVER['HTTP_HOST']))) {      
$spam=true;  
}

Conclusão

A prevenção de spam em submissões de formulários na Web é um trabalho árduo. Contudo, sempre que possível devemos evitar transferir a tarefa ao usuário através do uso de CAPTCHA ou de outros testes de detecção de humanos. Toda vez que for transferida ao usuário a responsabilidade de provar que ele é um humano a acessibilidade estará comprometida. As técnicas aqui mostradas descrevem vários métodos de filtrar spambots em formulários sem transferir o ônus ao usuário.

Eu estou certo de que aqui não foram cobertas todas as possibilidades e é provável que existam falhas nas técnicas mostradas. Se você tem algum comentário ou conhece técnicas melhores poste na área de comentários desta matéria.

topo