Prevenir el spam del formulario de contacto web php

13 minutos de lectura

avatar de usuario
usuario7858610

Soy un diseñador web aficionado, busqué en stackoverflow.com y otros sitios web y encontré muchas soluciones para este problema que tengo, pero ninguna funcionó (probablemente porque las implementé incorrectamente). Espero que alguien con más conocimientos pueda ayudarme con una solución simple o mostrarme cómo implementar una de las soluciones que encontré.

El problema: tengo un formulario de contacto php muy simple en el sitio web de mi empresa. Ha funcionado muy bien durante años, pero en la última semana ha sido pirateado. Ahora recibo cientos de envíos de formularios de contacto al día sin comentarios, solo tienen direcciones de correo electrónico (aparentemente válidas) y una cadena de caracteres en el campo de nombre (como “58ee8b52eef46”).

He probado varias técnicas para evitar este spam y, o rompen mi formulario php, o no evitan el spam. Si es posible, me gustaría una solución que NO requiera una prueba de texto distorsionado de Captcha, y NO requiera que se completen todos los campos del formulario.

Aquí está mi código PHP completo:

<?php
if(isset($_POST['email'])) {
  $email_to = "[email protected]";
  $email_subject = "website form submission";

  function died($error) {
    echo "We are very sorry, but there were error(s) found with the form you submitted. ";
    echo "These errors appear below.<br /><br />";
    echo $error."<br /><br />";
    echo "Please go back and fix these errors.<br /><br />";
    die();
  }

  if (!isset($_POST['name']) ||
    !isset($_POST['email']) ||
    !isset($_POST['telephone']) ||
    !isset($_POST['comments'])) {
    died('We are sorry, but there appears to be a problem with the form you submitted.');       
  }

  $name = $_POST['name'];
  $email_from = $_POST['email'];
  $telephone = $_POST['telephone'];
  $comments = $_POST['comments'];

  $error_message = "";
  if(strlen($error_message) > 0) {
    died($error_message);
  }
  $email_message = "Form details below.\n\n";

  function clean_string($string) {
    $bad = array("content-type","bcc:","to:","cc:","href");
    return str_replace($bad,"",$string);
  }

  $email_message .= "Name: ".clean_string($name)."\n";
  $email_message .= "Email: ".clean_string($email_from)."\n";
  $email_message .= "Telephone: ".clean_string($telephone)."\n";
  $email_message .= "Comments: ".clean_string($comments)."\n";

  $headers="From: ".$email_from."\r\n" .
             'Reply-To: '.$email_from."\r\n" .
             'X-Mailer: PHP/' . phpversion();
  @mail($email_to, $email_subject, $email_message, $headers);  
?>

Thank you for contacting us. We will be in touch with you soon. You will now be redirected back to example.com.
<META http-equiv="refresh" content="2;URL=http://www.example.com">

<?php
}
die();
?>

  • has mirado captcha

    – RiggsFolly

    12/04/2017 a las 20:33

  • Estoy seguro de haberte mencionado esto antes, pero ahora Google Recaptcha es invisible para la mayoría de los visitantes legítimos.

    –Steve

    12/04/2017 a las 20:36

  • He considerado usar Captcha. Pero preferiría una solución que no use captcha para mantener una apariencia limpia en mi sitio web.

    – usuario7858610

    12/04/2017 a las 20:37

  • Nadie debería usar reCaptcha nunca. No es ético porque para usarlo, debe infectar deliberadamente su sitio web con spyware dirigido a sus usuarios. Cualquier persona que no dé su consentimiento para el seguimiento (por ejemplo, mediante el bloqueo de secuencias de comandos de terceros de Google) no podrá utilizar ninguna parte de su sitio “protegida” por reCaptcha.

    – Skylar Ittner

    12 de julio de 2019 a las 4:32


  • Demasiadas veces he tenido que hacer más de una docena de clics para pasar un Captcha, ya que ahora reemplazan algunas imágenes por otras nuevas. PITAS de verdad. ¡Por favor, evite usarlos!

    – Patanjali

    1 de julio de 2021 a las 20:48

avatar de usuario
Steve

Un truco simple es crear un campo honeypot:

html

<!-- within your existing form add this field -->
<input type="text" id="website" name="website"/>

CSS

/*in your css hide the field so real users cant fill it in*/
form #website{ display:none; }

php

//in your php ignore any submissions that inlcude this field
if(!empty($_POST['website'])) die();

  • Sí, website es una buena opción general, porque la mayoría de los spambots tontos buscan dejar un enlace. Puede agregar tantos campos de honeypot como desee. Incluso podría agregar un honeypot llamado emaily cambie el nombre de su campo de correo electrónico real a otra cosa (como emailaddress).

    –Steve

    12/04/2017 a las 21:33

  • @vega cambiar de isset a !empty eso fue un error en mi respuesta: los campos de formulario vacíos se envían como cadenas vacías, por lo que siempre se establecerán

    –Steve

    26 de julio de 2017 a las 11:55

  • Esta publicación tiene 2 años y ya no parece hacer nada. He probado esto en algunos sitios web y los bots parecen tener en cuenta esta técnica.

    – bolvo

    3 jun 2019 a las 13:00


  • Tuve el problema de que el navegador completaba automáticamente uno o más de mis honeypots. La solución fue agregar el atributo “autocomplete=’off'” a cada elemento del honeypot.

    – EMF inversa

    15 de junio de 2019 a las 15:20


  • Si el bot está diseñado para un sitio web específico, no caería en esta trampa

    – Abhishek Choudhary

    7 de junio de 2020 a las 7:05

Un enfoque aún más simple que funciona para mí. Literalmente, todo el spam que recibo (d) tenía una URL en el mensaje. Así que filtré eso y no he recibido ningún mensaje de spam desde entonces. Solía ​​recibir unos 10 a la semana.

Agrega esto debajo de tu línea $mensaje_error = “”; en su archivo php:

if(preg_match('/http|www/i',$comments)) {
    $error_message .= "We do not allow a url in the comment.<br />";
  }

El /i en preg_match lo hace independiente de mayúsculas y minúsculas. El ‘http’ también filtra para ‘https’.

  • ¡He estado usando esto en un sitio que recibe mucho spam de los bots y funciona! ¿Cómo agregaría una segunda entrada, por ejemplo, dirección? Probé a continuación y tampoco funcionó. if(coincidencia_preg(‘/http|www/i’,$empresa)) { and if(coincidencia_preg(‘/http|www/i’,$mensaje)) { if(coincidencia_preg(‘/http|www/i’, $mensaje,$empresa)) { echo

    – Control Z

    17 de julio de 2020 a las 21:05

  • ¡Ay, genial!

    – Aym Dev

    18 de septiembre de 2020 a las 16:11

  • Excepto que algunas veces necesita permitir que una URL esté en el mensaje. Mi solución FormSpammerTrap (ahora en la versión 10, pronto será la versión 11) permite varias URL y muchas otras personalizaciones del formulario. Técnicas muy efectivas utilizadas en el código: mis sitios no reciben spam.

    –Rick Hellewell

    20 de marzo de 2021 a las 19:20

Los campos ocultos, las preguntas tontas (¿cuánto es 3+4?), etc., no son muy efectivos para bloquear el spam en los formularios.

Investigué esto hace varios años y se me ocurrió una solución que llamo “FormSpammerTrap”. Utiliza código JavaScript para ‘observar’ para enfocar/hacer clic en los campos obligatorios. Los procesos automatizados, a menos que estén muy personalizados para un sitio específico (lo que lleva más tiempo del que los propietarios de robots de spam quieren tomar), no pueden ‘enfocar/hacer clic’ en un campo obligatorio.

Tengo una solución gratuita en mi www.FormSpammerTrap.com sitio. Y hay un formulario que los spambots pueden intentar enviar spam… y no lo han hecho durante más de 3 años. Le invitamos a probarlo… todo es de código abierto, por lo que puede ver cómo funciona. (Y, si usa el formulario, no recopilo su correo electrónico. Respondo una vez y luego elimino su correo electrónico).

Mi técnica es mucho más efectiva para bloquear spambots. No han podido enviar spam al formulario de contacto de ese sitio.

  • No estoy seguro de por qué el voto negativo: ** Agregado el 12 de julio de 2018 ** El truco es agregar un evento al hacer clic/en el foco que cambia el parámetro de acción a la página de procesamiento real. De lo contrario, el valor predeterminado que uso es un sitio tipo honeytrap. Creo que es difícil para un spammer simular esos eventos, aunque tal vez sea posible. La técnica bloquea una gran cantidad de bot-spammers. Y aún así, después de un par de años usando la técnica en ese sitio, los bots no han enviado spam al formulario. (Defino un bot spammer que envía múltiples envíos a través del ataque, no solo un envío). Funciona para mí.

    –Rick Hellewell

    13 de julio de 2018 a las 0:22

  • ¿Es su sistema compatible con formularios legítimos como 1Password?

    – Esteban R.

    13 de julio de 2018 a las 23:15


  • Debería serlo, aunque nunca lo he probado. Solo tiene algo de Javascript para cambiar las cosas con un evento de clic y de enfoque. Dado que los bots de spam no pueden hacer Javascript (fácilmente), esto bloquea muchos de ellos. Puede agregar fácilmente reCaptcha al formulario si lo desea. No tiene nada de especial, solo se implementó en los formularios, por lo que todo lo que necesita hacer es cambiar algunas variables, incluir un archivo y llamar a la función que ‘construye’ el formulario. Es gratis para probar y usar; con todas las funciones. Visite el sitio para obtener más detalles.

    –Rick Hellewell

    14 de julio de 2018 a las 1:25

  • Los rellenadores de formularios funcionan con FormSpammerTrap (FST). Y hay mucha personalización disponible para crear un formulario con todo tipo de campos. La protección contra bots es excelente; Nunca he recibido spam automatizado con mi solución. La versión 11 se lanzará pronto. Todos los detalles en el sitio FST.

    –Rick Hellewell

    20 de marzo de 2021 a las 19:21

  • Hasta la versión 14 ahora; trabajando en la versión 15. V14 tiene toneladas de funciones nuevas (idiomas y más) y hay toneladas de funciones personalizables. Puede agregar el bloqueo de spam FST a cualquier formulario. Todavía todo gratis. Ver v14 en uso en mi sitio FormSpammerTrap (enlace arriba). Ha existido desde 2011, sigue siendo la mejor solución, en mi humilde opinión.

    –Rick Hellewell

    26 de mayo a las 21:46

Por lo general, los bots envían un formulario muy rápido. Entonces, en base a eso, otra solución podría ser agregar otro campo oculto que contenga la cantidad de segundos que pasaron desde que se abrió la página. Esto se puede hacer usando JavaScript. Luego verifíquelo en PHP. Si el número de segundos es inferior a 5 segundos, entonces es spam (es más probable que el cliente real necesite más tiempo para ajustar el formulario). Puede ajustar la cantidad de segundos según la cantidad de campos que contenga el formulario.

avatar de usuario
benroe

Cree un campo de formulario y ocúltelo para los usuarios. En el script php, compruebe si este campo se envía, pero está vacío. Ahora sabe que la solicitud es de su formulario y un usuario.

El spam llenará el campo oculto, o si usan su script php directamente, el campo de protección contra spam no está configurado.

HTML

<input name="website" type="text" class="website"/>

CSS

form .website{ display:none; } /* hide because is spam protection */

PHP

# spam protection
if (isset($_POST["website"]) && $_POST["website"] == "") {
  # your php code to mail here
} else {
  http_response_code(400);
  exit;
}

Puede encontrar más métodos para proteger un formulario php de spam aquí: https://zinoui.com/blog/proteger-los-formularios-web-del-spam

  • Es muy fácil para un robot de spam robusto encontrar y enviar campos ocultos. Y esos bots pueden estar altamente automatizados para encontrar y explotar formularios.

    –Rick Hellewell

    20 de marzo de 2021 a las 19:22

avatar de usuario
KrondaliX

Para mi respuesta, ya que superé esto, simplemente agregaré algunas nuevas posibilidades porque el honeypot de Steve es extremadamente bueno pero fue secuestrado (tal vez nuevos softwares para enviar spam en estos días) y el captcha hecho a mano (lo que es 3 + 4) no lo hizo funciona para mí incluso con números aleatorios, funcionó durante un tiempo pero dejó de funcionar después de un tiempo. No sé cómo superaron esto, pero tuve que agregar algunos códigos…

Entonces logré obtener la IP del spammer de esta manera:

$ip = $_SERVER['REMOTE_ADDR'];

Luego agregué $ip al correo electrónico enviado por mi código php en el asunto y luego agregué este código para verificar los resultados sin enviar spam a mi bandeja de entrada:

if ($ip == '1.1.1.1') /*<-- this is an example*/
{
 $fp = fopen('spam_log.txt', 'a');
 fwrite($fp, 'Inputname: '.$inputname.' IP: '.$ip."\n");
 fclose($fp); die;
}

Con esto, estuve a salvo por un tiempo porque la ip del spammer no cambiaba muy a menudo.

Lo que más obtuve fueron URL, así que agregué esto:

if (strstr($inputname, 'http')){die;} /*<-- did that for each input i had*/
if (strstr($inputname, 'www')){die;} /*<-- did that for each input i had*/

Pero a veces recibí correos no deseados sin direcciones URL… por casualidad recibí correos electrónicos no deseados esencialmente cirílicos, así que usé este código:

$inputname_cyrillic = (bool) preg_match('/[\p{Cyrillic}]/u', $inputname);
if ($inputname_cyrillic){die;}

También puede agregar árabe o griego si es necesario, eso funciona bien ya que no puedo leer estos idiomas y no estoy interesado en eso.

Si es ruso, árabe o griego, puede hacer lo contrario y simplemente agregar el código {Común} que está relacionado con AZ si solo desea recibir caracteres cirílicos, árabes o griegos.

Este hilo me ayudó mucho, así que quería contribuir con mi experiencia.

  • Es muy fácil para un robot de spam robusto encontrar y enviar campos ocultos. Y esos bots pueden estar altamente automatizados para encontrar y explotar formularios.

    –Rick Hellewell

    20 de marzo de 2021 a las 19:22

avatar de usuario
rickdenhaan

Si el correo no deseado que recibe no tiene un comentario, ¿por qué no simplemente agregar una marca para eso? No hay absolutamente ninguna razón para que un visitante humano real envíe su formulario de contacto sin un comentario.

Dado que no desea agregar un captcha, la solución más fácil a corto plazo sería verificar que el comentario tenga una cantidad mínima de caracteres y que contenga al menos una cierta cantidad de palabras.

Por ejemplo:

$comments = trim($_POST['comments']); // trim() to strip off whitespace from beginning and end, like spaces and linebreaks

if (strlen($comments) < 20 || substr_count($comments, " ") < 3) {
    died('Your comment is too short.');
}

Esta es una verificación muy simple para ver que el comentario contiene al menos 20 caracteres y al menos 3 espacios (4 palabras). Ajuste según sea necesario.

  • Hola, gracias por esta respuesta. He implementado otra solución similar a la tuya. Sin embargo, ocasionalmente recibimos un envío de formulario de alguien que simplemente quiere saber más información, y solo incluye un correo electrónico o un número de teléfono sin comentarios. De hecho, hemos convertido clientes potenciales como este en ventas, por lo que no quiero eliminar la posibilidad de recibir formularios sin comentarios. Espero que tenga sentido.

    – usuario7858610

    12 abr 2017 a las 20:44

  • Tiene sentido, pero eso realmente abre la puerta a los robots de spam. En ese caso, puede considerar agregar una casilla de verificación “solo envíeme información” y deshabilitar el botón de envío de forma predeterminada (para que los bots no puedan enviar el formulario), luego habilitarlo usando javascript cuando se haya ingresado el comentario. o el usuario marca esa casilla de verificación.

    – rickdenhaan

    12 abr 2017 a las 20:54

  • No estoy seguro de que deshabilitar el botón de enviar funcione con spambots que usan técnicas automatizadas (como CURL). Sus técnicas podrán ‘ver’ un campo oculto, incluso un botón de envío oculto, y enviar el formulario.

    –Rick Hellewell

    25 de abril de 2018 a las 2:23

¿Ha sido útil esta solución?