Qué protege realmente un formulario: CAPTCHA, honeypot, trampa de tiempo, CSRF
La mayoría de los formularios de contacto confían en un único truco contra el spam, y muchos de esos trucos solo detienen a los bots más simples. Qué detiene cada capa de protección, qué cuesta y qué combinación tiene sentido.
El spam a través de formularios de contacto rara vez procede de una persona que teclea a mano. Casi siempre es software que encuentra formularios, rellena todos los campos y envía el resultado, miles de veces. Existen varias defensas, y actúan en puntos muy distintos. Saber lo que hace realmente cada una le ayuda a evitar dos errores: un formulario sin protección real y un formulario tan vigilado que las personas reales se rinden.
- Honeypot: bots simples que rellenan todos los campos
- Trampa de tiempo: scripts que envían nada más 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 una sola fuente
- Prueba de trabajo: envíos masivos baratos, sin seguimiento ni acertijos
- Comprobaciones en el servidor: todo lo que esquiva el navegador
- Los bots dirigidos lo esquivan; si está mal oculto, los lectores de pantalla lo anuncian
- Bots que esperan; sin una firma en el servidor es fácil de falsificar
- Un obstáculo para todos, barreras de accesibilidad, a menudo de terceros; existen servicios que los resuelven
- Los bots que cargan primero la página también obtienen un token válido
- Spam repartido entre muchas direcciones IP
- Un remitente decidido con capacidad de cálculo; requiere JavaScript
- Nada por sí solas, pero sin ellas cualquier otra capa es decoración
Honeypot y trampa de tiempo: filtros invisibles
Un honeypot es un campo adicional que las personas nunca ven, como un campo llamado «website» oculto con CSS. Los bots simples rellenan todos los campos, por lo que un honeypot relleno indica automatización y el servidor puede descartar el mensaje discretamente. Los bots escritos para su sitio, o los que renderizan la página como un navegador, lo esquivan. Ocúltelo correctamente: un campo simplemente desplazado fuera de la pantalla puede ser anunciado por los lectores de pantalla, alcanzarse con la tecla Tab o rellenarse con el autocompletado. Utilice aria-hidden, tabindex -1 y autocomplete off, además de una etiqueta neutra que pida a quien llegue allí que lo deje vacío.
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 comprobarse en el servidor y protegerse frente a manipulaciones, por ejemplo firmada o guardada en la sesión: un simple campo de tiempo oculto lo reescribe el bot sin más. Mantenga el umbral bajo, ya que el autocompletado también hace rápidas a las personas reales. Los bots que simplemente esperan consiguen pasar: una trampa de tiempo es un filtro, no un muro.
CAPTCHA: eficaz, pero no gratis
Un CAPTCHA pide una prueba de que no está actuando un bot, desde acertijos con imágenes hasta comprobaciones 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, por eso es tan popular. Pero cada acertijo visible es un obstáculo ante el que algunos visitantes se rinden, y la mayoría de los servicios cargan un script de terceros, lo que plantea cuestiones de privacidad y de consentimiento. Además, un CAPTCHA solo ayuda si está bien configurado: una clave de sitio de prueba pública, un widget sin su script o un token que el servidor nunca verifica parecen protección, pero no lo son. Una comprobación gratuita en formexposed.com señala estos errores desde fuera.
La accesibilidad forma parte de ese coste. Los acertijos con imágenes dejan fuera 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 lógicas complicadas suponen una carga para las personas con discapacidades cognitivas. El criterio de conformidad 1.1.1 de las WCAG 2.2 exige una alternativa textual que describa la finalidad del CAPTCHA y formas alternativas para distintos sentidos. Las comprobaciones en segundo plano evitan la mayor parte de esto, pero cuando sospechan algo, la alternativa suele volver a ser un acertijo visual: pruebe ese camino 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 introduce 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 el visitante nunca pretendió. En un formulario de contacto público tiene un efecto secundario: se rechazan los bots que envían directamente a la dirección del formulario sin cargar la página. Cualquier bot que obtenga la página y devuelva el token consigue pasar. La mayoría de los frameworks y plugins de formularios incluyen tokens CSRF de todos modos: manténgalos activados, pero no los cuente como protección antispam.
Lo que tiene que ocurrir en el servidor
- Valide de nuevo cada campo en el servidor: campos obligatorios, longitud, formato del correo electrónico y ningún salto de línea en los campos que acaban en las cabeceras del correo.
- Verifique los tokens de CAPTCHA y de prueba de trabajo en cada envío, con el servicio emisor o en su propio código, y rechace los tokens reutilizados.
- Limite los envíos por dirección IP y franja de tiempo. Así se detienen las avalanchas desde una sola fuente; el spam repartido entre muchas direcciones necesita otras capas.
- Considere la prueba de trabajo: antes de enviar, el navegador resuelve una pequeña tarea de cálculo. Los visitantes no ven ningún acertijo y no se hace ningún seguimiento, pero el envío masivo se encarece.
Una combinación sensata: dos o tres capas
- 1Empiece por las capas invisibles: un honeypot accesible y una trampa de tiempo firmada, ambos comprobados en el servidor.
- 2Añada un límite de frecuencia por dirección IP para que una sola fuente no pueda inundar el formulario.
- 3Si el spam dirigido sigue pasando, añada una prueba de trabajo o un CAPTCHA, preferiblemente uno sin acertijo visible y con una alternativa accesible.
- 4Mantenga el token CSRF que proporciona su framework, como extra, no como defensa.
- 5Pruebe el resultado como visitante (solo con teclado, con un lector de pantalla, en un móvil) y compruebe que los mensajes reales siguen llegando.
En muchos sitios, el honeypot, 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 es la reserva para cuando eso no basta. En WordPress, el plugin gratuito de formexposed combina honeypot, comprobación de tiempo y prueba de trabajo sin necesidad de Google. Para ver lo que su formulario muestra desde fuera (qué capas están presentes, si un CAPTCHA está configurado de forma eficaz), una comprobación gratuita en formexposed.com solo necesita un dominio, sin cuenta. No puede ver el código de su servidor, así que la parte del servidor sigue siendo tarea suya.