Protección CSRF y prevención de la manipulación de formularios

Entiende los ataques CSRF y cómo los tokens impiden que un atacante secuestre tus formularios. Descubre por qué todos necesitan protección CSRF.

Borrador

Imagina que alguien engaña a un visitante para que haga clic en un enlace mientras tiene abierta la sesión de su banco. Ese enlace lleva a un formulario oculto que, sin que el visitante lo sepa, envía al banco una orden para transferir dinero. El banco ve una petición legítima de un usuario autenticado y la procesa. El atacante ha movido dinero con la cuenta de la víctima sin haber conocido nunca su contraseña.

Eso es el CSRF (Cross-Site Request Forgery, falsificación de petición en sitios cruzados): un ataque en el que un atacante engaña a una víctima para que envíe, sin darse cuenta, un formulario o una petición a otra web en la que ya tiene la sesión iniciada.

Qué aprenderás: qué son los ataques CSRF y cómo funcionan, por qué son tan peligrosos aunque haya otras medidas de seguridad, cómo los evitan los tokens CSRF y cómo proteger tus formularios.

¿Qué es el CSRF?

CSRF (se pronuncia "sea-surf") significa Cross-Site Request Forgery. Es un ataque que aprovecha que, si tienes la sesión iniciada en una web, tu navegador confía automáticamente en ella e incluye tu sesión en cada petición que haces a ese sitio, aunque la petición venga de otra web.

El ataque consiste en engañar a un visitante con la sesión iniciada para que envíe, sin saberlo, un formulario a una web donde tiene cuenta. El atacante no puede ver la contraseña de la víctima. No la necesita. Solo hace falta que la víctima ya tenga la sesión iniciada y que le engañe para que haga una petición (como enviar un formulario oculto) que haga lo que el atacante quiere.

El CSRF se diferencia de otros ataques porque no necesita robar credenciales ni romper el cifrado. Explota la confianza de la víctima en la web. Como la víctima ya está autenticada, la web confía en las peticiones que parecen venir de ella.

Cómo funcionan los ataques CSRF

Un ataque CSRF ocurre en tres pasos.

Paso 1: la víctima tiene la sesión iniciada en tu sitio

Alguien visita tu web e inicia sesión en su cuenta. Su navegador ahora tiene una cookie de sesión activa que demuestra que está autenticado. Esa sesión sigue activa mientras siga usando el sitio.

Paso 2: el atacante le engaña para que visite una página maliciosa

Con la sesión aún abierta en tu sitio, la víctima visita una página que controla el atacante (quizá un enlace de redes sociales, un anuncio engañoso o una web que parece legítima). En esa página hay un código oculto que envía un formulario a tu sitio.

Paso 3: el formulario se envía solo con la sesión de la víctima

El formulario oculto se envía a tu web. Como la víctima ya tiene la sesión iniciada, su navegador incluye automáticamente su cookie de sesión en la petición. Desde el punto de vista de tu formulario, es una petición legítima de un usuario autenticado. El formulario la procesa como si la víctima lo hubiera enviado a propósito.

El atacante ha hecho algo en tu sitio con la cuenta de la víctima sin que ella lo sepa. Pudo cambiar su contraseña, transferir dinero, actualizar su perfil o enviar datos.

Por qué funciona aunque haya otras medidas de seguridad

Los ataques CSRF esquivan varias funciones de seguridad habituales:

HTTPS no frena el CSRF. Los datos viajan cifrados, pero el atacante no necesita interceptarlos. Solo envía la petición desde el navegador de la víctima, en el que el propio navegador ya confía.

La protección con contraseña no frena el CSRF. El atacante nunca necesita la contraseña de la víctima. Solo aprovecha que la víctima ya tiene la sesión iniciada.

Un buen sistema de inicio de sesión no frena el CSRF. Aunque la autenticación sea perfecta, si la víctima tiene la sesión iniciada, el ataque funciona.

Por eso la protección contra el CSRF es una capa propia. Las demás medidas de seguridad no la cubren. Tienes que diseñar los formularios para que resistan este ataque.

Tokens CSRF: cómo detienen el ataque

La solución es un token CSRF. Es una cadena única e impredecible que tu servidor genera para cada formulario. Así funciona:

Tu servidor crea un token único para cada visitante

Cuando alguien carga una página con un formulario, tu servidor genera un token aleatorio y lo asocia a la sesión de ese usuario. El token es distinto cada vez y exclusivo de ese usuario.

El token va dentro del formulario

El token se incluye como campo oculto en el formulario HTML. Cuando el visitante envía el formulario, el token viaja con él.

Tu servidor verifica el token antes de procesar el envío

Cuando se envía el formulario, tu servidor comprueba si el token del envío coincide con el que generó para la sesión de ese usuario. Si coincide, el formulario se procesa. Si no (o si no hay token), se rechaza.

El formulario oculto del atacante no puede incluir un token válido, porque los tokens son impredecibles y únicos para cada sesión. Un atacante en otro dominio no puede ver ni adivinar el token. Por eso su ataque falla. El formulario oculto se envía, pero tu servidor lo rechaza porque el token no coincide.

Cómo se ve un token CSRF en la práctica

En HTML, un formulario protegido contra CSRF tiene este aspecto:

<form method="POST" action="/submit-form"> <input type="hidden" name="csrf_token" value="a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"> <input type="email" name="email" placeholder="Your email"> <button type="submit">Submit</button> </form>

El campo `csrf_token` está oculto. El visitante no lo ve, pero se envía junto con los datos del formulario. Tu servidor lo comprueba antes de procesar el correo o cualquier otro dato.

Protección CSRF según el tipo de formulario

Formularios HTML tradicionales

Los formularios HTML estándar (los que envían datos a tu servidor con POST) necesitan tokens CSRF. Esto incluye formularios de contacto, de inicio de sesión, de restablecimiento de contraseña y cualquier formulario que cambie datos en tu servidor.

Formularios AJAX y JavaScript

Los formularios que se envían con JavaScript a un endpoint de una API también necesitan protección CSRF. El token puede ir dentro del propio formulario, guardarse en una cookie u obtenerse de una metaetiqueta antes de enviar la petición.

Peticiones de API sin estado

Si tu API usa autenticación basada en tokens (como JWT), la protección CSRF funciona de otra manera. El navegador no puede adjuntar automáticamente un token JWT como hace con una cookie de sesión, así que el CSRF tradicional es una amenaza menor. Aun así, lo recomendable es incluir un token CSRF adicional para mayor protección.

Otras protecciones que funcionan junto con los tokens CSRF

Los tokens CSRF son la defensa principal, pero funcionan mejor junto con otras prácticas de seguridad.

Cookies SameSite

Al definir una cookie de sesión, puedes añadir un atributo `SameSite` que indica al navegador que no incluya la cookie cuando la petición venga de otro dominio. Así el formulario oculto del atacante no puede usar la sesión de la víctima.

Comprobación de la cabecera Referer

Tu servidor puede comprobar la cabecera Referer para ver de dónde viene la petición. Si un envío dice venir de tu dominio pero el Referer muestra otro, probablemente sea un ataque. (Sin embargo, las cabeceras Referer se pueden falsificar, así que esta no es una defensa completa.)

Patrón de cookie de doble envío

En este método, el token CSRF se guarda tanto en una cookie como en un campo del formulario. Tu servidor comprueba que coinciden antes de procesar. Es menos común que los tokens tradicionales, pero funciona bien en aplicaciones sin estado.

Cómo implementar la protección CSRF

Los detalles dependen de tu tecnología, pero el patrón es el mismo:

  1. Genera un token único por sesión. Cuando un usuario inicia sesión o carga una página con formulario, tu backend genera un token nuevo.
  2. Guarda el token en el servidor. Guárdalo asociado a la sesión de ese usuario.
  3. Incluye el token en el formulario. Añádelo como campo oculto en el HTML o como metaetiqueta que JavaScript pueda leer.
  4. Valida al enviar. Antes de procesar los datos del formulario, comprueba que el token enviado coincide con el guardado para esa sesión.
  5. Regenera el token tras las acciones sensibles. Cuando un usuario cambie su contraseña o haga algo crítico, genera un token nuevo.

La mayoría de los frameworks modernos generan y validan los tokens CSRF automáticamente. Si usas un framework, la protección CSRF suele estar activada por defecto. Solo asegúrate de no desactivarla sin querer.

Errores comunes que dejan los formularios vulnerables

Desactivar la protección CSRF por comodidad. Algunos desarrolladores apagan las comprobaciones CSRF para probar la API con más facilidad o simplificar el código. No lo hagas. Crea una vulnerabilidad real.

Usar un token estático para todos los usuarios. El token debe ser único para la sesión de cada usuario. Un token igual para todos (o igual para todos los usuarios todos los días) no protege contra el CSRF.

No regenerar los tokens. Si usas el mismo token durante semanas, el atacante tiene más tiempo para aprovecharlo. Regenera los tokens con regularidad y siempre después de operaciones sensibles.

Confiar solo en las cookies SameSite. SameSite ayuda, pero no basta. Usa los tokens CSRF como defensa principal y SameSite como respaldo.

Olvidar los tokens en algunos formularios. Si proteges unos formularios con tokens y otros no, los atacantes usarán los desprotegidos. Todo formulario que modifique datos necesita protección.

Qué hace WEMASY para la protección CSRF

Los formularios de WEMASY incluyen automáticamente protección con token CSRF en cada formulario que creas. No tienes que configurarla ni pensar en ella. Cuando un visitante envía un formulario, WEMASY valida el token antes de guardar el envío. Esta protección viene integrada y activada por defecto.

Descubre más sobre las opciones de seguridad de los formularios en la página de precios.

Preguntas frecuentes

¿Puede un atacante adivinar un token CSRF?
En teoría, no. Los tokens CSRF son criptográficamente aleatorios y cambian con frecuencia. Un atacante que intentara adivinar un token tendría que probar miles de millones de posibilidades. En la práctica, los tokens CSRF son tan impredecibles que adivinarlos no es un ataque viable. La fuerza del token viene de su aleatoriedad y su unicidad, no de mantenerlo en secreto.
¿Qué pasa si un visitante envía un formulario y el token no es válido?
El envío se rechaza. Tu servidor no procesa los datos del formulario ni guarda el envío. El visitante suele ver un mensaje de error (como "Sesión caducada" o "Petición no válida") y se le pide que lo intente de nuevo. Desde el punto de vista del atacante, el formulario oculto simplemente no funciona.
¿Necesito protección CSRF si mi formulario no pide iniciar sesión?
Sí. Los ataques CSRF también pueden funcionar en formularios que no requieren autenticación. Un atacante puede usar el CSRF para engañar a un visitante y que envíe datos no deseados a cualquier formulario, tenga o no la sesión iniciada. Todo formulario que procese envíos necesita protección CSRF.
¿En qué se diferencia el CSRF del XSS?
El Cross-Site Scripting (XSS) es cuando un atacante inyecta código malicioso en tu web que se ejecuta en el navegador de los visitantes. El CSRF es cuando un atacante engaña al navegador de un visitante para que envíe un formulario a otro sitio. Son ataques distintos con defensas distintas. Los tokens CSRF protegen contra el CSRF; la validación y la sanitización de las entradas protegen contra el XSS.
¿Y los ataques a apps móviles? ¿Sirven los tokens CSRF?
Las apps móviles son menos vulnerables a los ataques CSRF tradicionales porque no adjuntan cookies automáticamente como hacen los navegadores. Aun así, deberían usar autenticación basada en tokens o en certificados. Si una app móvil usa cookies o tokens que se envían automáticamente con las peticiones, también debería validar tokens CSRF como capa de protección adicional.

Ponlo en práctica
en tu propia web.

Empieza gratis con WEMASY y crea tu web en pocos minutos.