Qué protege realmente un formulario: CAPTCHA, campo trampa, trampa de tiempo y CSRF
La mayoría de los formularios de contacto dependen de un solo recurso contra el spam, y muchos de esos recursos solo detienen a los bots más simples. Qué frena cada capa de protección, qué costo tiene y qué combinación conviene.
El spam por formularios de contacto rara vez proviene de una persona que escribe a mano. Casi siempre es software que encuentra formularios, llena todos los campos y envía el resultado miles de veces. Existen varias defensas, y actúan en puntos muy distintos. Conocer lo que realmente hace cada una le ayuda a evitar dos errores: un formulario sin protección real y uno tan protegido que las personas reales se dan por vencidas.
- Campo trampa: bots simples que llenan todos los campos
- Trampa de tiempo: scripts que envían inmediatamente después de cargar la página
- CAPTCHA: la mayor parte de la automatización genérica
- Token CSRF: solicitudes enviadas directamente al endpoint
- Límite de frecuencia: avalanchas desde un solo origen
- Prueba de trabajo: envíos masivos de bajo costo, sin seguimiento ni acertijos
- Verificaciones del lado del servidor: todo lo que omite el navegador
- Los bots dirigidos lo omiten; si está mal oculto, los lectores de pantalla lo anuncian
- Los bots que esperan; sin una firma del lado del servidor, es fácil falsificarla
- Un obstáculo para todos, barreras de accesibilidad y, a menudo, terceros; existen servicios que lo resuelven
- Los bots que primero cargan la página también obtienen un token válido
- El spam distribuido entre muchas direcciones IP
- Un remitente decidido con potencia de cómputo; requiere JavaScript
- Nada por sí solas, pero sin ellas las demás capas son decoración
Campo trampa y trampa de tiempo: filtros invisibles
Un campo trampa es un campo adicional que las personas nunca ven, como uno llamado «website» oculto con CSS. Los bots simples llenan todos los campos, por lo que un campo trampa con contenido indica automatización y el servidor puede descartar el mensaje sin avisar. Los bots programados para su sitio, o los que renderizan la página como un navegador, lo omiten. Ocúltelo correctamente: un campo que solo se desplazó fuera de la pantalla puede ser anunciado por los lectores de pantalla, recibir el foco con la tecla Tab o llenarse con el autocompletado. Use aria-hidden, tabindex -1 y autocomplete off, además de una etiqueta neutral que pida dejarlo vacío a quien llegue a él.
Una trampa de tiempo registra cuándo se entregó el formulario y rechaza los envíos que llegan con una rapidez inverosímil. Las personas necesitan unos segundos para leer y escribir; muchos scripts envían en una fracción de segundo. La marca de tiempo debe verificarse en el servidor y estar protegida contra manipulaciones, por ejemplo mediante una firma o conservándola en la sesión: un campo de tiempo oculto sin más protección simplemente lo reescribe el bot. Mantenga bajo el umbral, ya que el autocompletado también hace rápidas a las personas reales. Los bots que simplemente esperan logran pasar: una trampa de tiempo es un filtro, no un muro.
CAPTCHA: eficaz, pero no gratuito
Un CAPTCHA pide una prueba de que no está actuando un bot, desde acertijos con imágenes hasta verificaciones que se ejecutan en segundo plano; entre los servicios habituales están reCAPTCHA, hCaptcha, Cloudflare Turnstile y Friendly Captcha. Detiene la mayor parte de la automatización genérica, y por eso es tan popular. Pero cada acertijo visible es un obstáculo ante el que algunos visitantes se dan por vencidos, y la mayoría de los servicios carga un script de terceros, lo que plantea cuestiones de privacidad y consentimiento. Además, un CAPTCHA solo ayuda si está bien configurado: una clave pública de sitio para pruebas, un widget sin su script o un token que el servidor nunca verifica parecen protección, pero no lo son. Una verificación gratuita en formexposed.com señala esos errores desde el exterior.
La accesibilidad forma parte de ese costo. Los acertijos con imágenes excluyen a las personas ciegas y a muchas personas con baja visión, las alternativas de audio no ayudan a las personas sordociegas y las tareas de lógica difíciles suponen una carga para quienes tienen discapacidades cognitivas. El criterio de conformidad 1.1.1 de WCAG 2.2 exige una alternativa textual que describa la finalidad del CAPTCHA y modalidades alternativas para distintos sentidos. Las verificaciones en segundo plano evitan la mayor parte de estos problemas, pero cuando detectan algo sospechoso, la alternativa suele volver a ser un acertijo visual: pruebe ese recorrido con un teclado y un lector de pantalla.
Token CSRF: protección contra la falsificación, no contra el spam
Un token CSRF es un valor aleatorio que el servidor coloca en el formulario y espera recibir de vuelta. Se diseñó contra la falsificación de solicitudes entre sitios, en la que otro sitio web hace que el navegador de un visitante envíe una solicitud que este nunca quiso enviar. En un formulario de contacto público tiene un efecto secundario: se rechaza a los bots que envían directamente a la dirección del formulario sin cargar la página. Cualquier bot que obtiene la página y devuelve el token logra pasar. La mayoría de los frameworks y plugins de formularios ya incluye tokens CSRF: manténgalos activados, pero no los cuente como protección contra el spam.
Lo que debe ocurrir en el servidor
- Valide de nuevo cada campo en el servidor: campos obligatorios, longitud, formato del correo electrónico y ausencia de saltos de línea en los campos que terminan en los encabezados del correo.
- Verifique los tokens de CAPTCHA y de prueba de trabajo en cada envío, con el servicio que los emite o en su propio código, y rechace los tokens reutilizados.
- Limite los envíos por dirección IP y ventana de tiempo. Esto detiene las avalanchas desde un solo origen; el spam distribuido entre muchas direcciones necesita otras capas.
- Considere la prueba de trabajo: antes de enviar, el navegador resuelve una pequeña tarea de cómputo. Los visitantes no ven ningún acertijo y no se realiza seguimiento, pero el envío masivo se vuelve costoso.
Una combinación sensata: dos o tres capas
- 1Empiece por las capas invisibles: un campo trampa accesible y una trampa de tiempo firmada, ambos verificados en el servidor.
- 2Agregue un límite de frecuencia por dirección IP para que un solo origen no pueda inundar el formulario.
- 3Si sigue pasando spam dirigido, agregue una prueba de trabajo o un CAPTCHA, de preferencia sin acertijo visible y con una alternativa accesible.
- 4Mantenga el token CSRF que proporciona su framework, como un extra, no como una defensa.
- 5Pruebe el resultado como visitante: solo con teclado, con un lector de pantalla y en un celular, y compruebe que los mensajes reales sigan llegando.
En muchos sitios, el campo trampa, la trampa de tiempo y el límite de frecuencia juntos ya eliminan la mayor parte del spam genérico sin ningún obstáculo visible; el CAPTCHA queda como reserva para cuando eso no basta. En WordPress, el plugin gratuito de formexposed combina campo trampa, verificación de tiempo y prueba de trabajo sin necesitar Google. Para ver qué muestra su formulario desde el exterior —qué capas están presentes y si un CAPTCHA está configurado de forma eficaz—, una verificación gratuita en formexposed.com solo necesita un dominio, sin cuenta. No puede ver el código de su servidor, por lo que la parte del lado del servidor sigue siendo responsabilidad suya.