CSRF (cross-site request forgery, también escrito como XSRF) es una vulnerabilidad web en la que un atacante consigue que el navegador de una víctima ya autenticada ejecute acciones no deseadas sobre una aplicación donde la víctima mantiene sesión activa. El ataque no roba la cookie ni rompe el cifrado: aprovecha el hecho de que el navegador adjunta automáticamente las credenciales de sesión a cualquier petición dirigida al dominio objetivo, incluso cuando esa petición se origina en una página controlada por el atacante. La aplicación recibe la solicitud como si fuera legítima y la ejecuta porque confía en el navegador del usuario.
Lo esencial. CSRF explota la confianza del servidor en el navegador autenticado, no en el usuario. Las defensas modernas combinan tokens anti CSRF (synchronizer pattern), cookies
SameSite=LaxoStrict, validación de cabecerasOriginyReferer, y reautenticación en operaciones críticas. Frameworks como Django, Rails, Spring Security, ASP.NET y Laravel incluyen protección por defecto, pero solo si la configuración no se desactiva.
Qué es CSRF: mecanismo paso a paso
El flujo de un ataque CSRF se apoya en tres elementos simultáneos: una víctima autenticada, una aplicación que confía en las cookies del navegador para autorizar acciones, y una página o recurso controlado por el atacante que la víctima visita o carga sin advertirlo.
El primer paso es la sesión activa. La víctima inicia sesión en una aplicación legítima (por ejemplo, un panel bancario, un CMS corporativo o un servicio interno). El servidor emite una cookie de sesión que el navegador almacena para ese dominio. Esa cookie viaja en cada petición posterior al mismo origen.
El segundo paso es la página atacante. La víctima visita otra web (un blog, un foro, un correo HTML, un enlace en redes sociales) donde el atacante ha colocado código preparado: un formulario que se auto envía con JavaScript, una etiqueta <img> que dispara una petición GET, o un fetch() con credentials: 'include'. El navegador interpreta ese código como cualquier otro recurso.
El tercer paso es la ejecución silenciosa. Cuando el navegador realiza la petición forjada hacia el dominio víctima, adjunta automáticamente la cookie de sesión almacenada. El servidor recibe credenciales válidas, identifica al usuario y ejecuta la acción (transferencia, cambio de contraseña, alta de administrador) sin que la víctima haya hecho clic en nada distinto a una página externa. La confirmación del éxito ni siquiera necesita volver al atacante: basta con que la acción se complete en el servidor.
El punto crítico es que la aplicación no distingue entre una petición originada en su propia interfaz y una originada en un tercero, salvo que implemente comprobaciones específicas. Esa indistinción es la base del ataque.
Ejemplo técnico de exploit CSRF
A continuación, dos patrones clásicos. Se muestran con fines didácticos y de auditoría defensiva.
Petición GET disparada por una imagen embebida en un email HTML o web maliciosa:
<img src="https://app-victima.tld/transferir?destino=atacante&importe=5000" width="0" height="0" />
Si la aplicación procesa transferencias mediante GET (mala práctica recurrente en código legacy) y la víctima abre el correo o la página con sesión activa, el navegador realiza la petición y se incluye la cookie de sesión.
Petición POST mediante formulario auto enviado:
<form id="f" action="https://app-victima.tld/cuenta/cambiar-email" method="POST">
<input type="hidden" name="email" value="atacante@malicio.tld" />
</form>
<script>document.getElementById('f').submit();</script>
El formulario se envía sin interacción del usuario. La cookie de sesión viaja con la petición. Si no existe token anti CSRF ni validación de Origin, la aplicación cambia la dirección de correo asociada a la cuenta, lo que abre la puerta a un reset de contraseña posterior.
Estos patrones son trivialmente reproducibles en un laboratorio controlado (por ejemplo, DVWA, PortSwigger Web Security Academy o entornos propios) y forman parte de cualquier auditoría web responsable.
CSRF vs XSS vs SSRF: diferencias clave
| Vector | Origen del payload | Qué se explota | Quién ejecuta |
|---|---|---|---|
| CSRF | Sitio externo controlado por el atacante | Confianza del servidor en cookies automáticas | Navegador de la víctima |
| XSS | Inyección en la propia aplicación vulnerable | Confianza del navegador en el origen | Navegador de la víctima (con permisos del dominio) |
| SSRF | Parámetro controlable enviado al backend | Confianza del servidor en sus propias peticiones salientes | Servidor de la aplicación |
CSRF y XSS coexisten con frecuencia: un XSS exitoso anula cualquier protección CSRF porque el atacante puede leer el token desde dentro del dominio. Por eso XSS suele considerarse más grave y CSRF complementa el catálogo de defensas en profundidad.
Tipos de ataque CSRF
CSRF basado en GET. Funciona cuando la aplicación expone acciones que modifican estado mediante peticiones GET. Es el caso más fácil de explotar porque basta con una etiqueta <img>, <link> o redirección.
CSRF basado en POST. Requiere un formulario auto enviado o un fetch() con credentials. Es el escenario clásico contra paneles web.
CSRF sobre JSON. Históricamente se consideró seguro porque las peticiones con Content-Type: application/json disparan preflight CORS. Sin embargo, prefetch tricks, formularios con enctype="text/plain" y APIs mal configuradas que aceptan application/x-www-form-urlencoded como alternativa han permitido bypass en aplicaciones reales.
Login CSRF. El atacante no fuerza una acción autenticado como la víctima, sino que la fuerza a iniciar sesión con credenciales del atacante. La víctima cree estar usando su cuenta y entrega datos (búsquedas, mensajes, métodos de pago) que el atacante recupera al volver a la sesión.
State changing operations. Cualquier endpoint que altere datos persistentes (cambio de email, contraseña, dirección, permisos, suscripciones, pagos) es candidato a auditoría CSRF. Endpoints idempotentes de solo lectura no requieren protección, pero exigen revisión para confirmar que efectivamente no modifican estado.
Defensas modernas
CSRF tokens (synchronizer pattern)
El servidor genera un token aleatorio por sesión (o por petición), lo incluye en cada formulario o lo expone vía endpoint para clientes JavaScript, y lo valida en cada acción state changing. El token no debe viajar en la cookie de sesión y debe ser impredecible. Es la defensa de referencia y la que implementan los frameworks maduros.
Double submit cookie pattern
El servidor establece una cookie con un valor aleatorio y exige que cada petición state changing incluya ese mismo valor en una cabecera personalizada o en un campo del formulario. El servidor compara ambos. Es útil en arquitecturas sin sesión clásica, pero requiere cuidado con el ámbito de cookies y la integridad del valor.
SameSite cookies (Lax, Strict, None)
SameSite=Strict impide que la cookie se envíe en cualquier petición cross site, incluidos enlaces top level. SameSite=Lax (valor por defecto en navegadores modernos) bloquea cookies en POST y subrecursos cross site, pero las permite en navegación top level con GET. SameSite=None solo se usa con Secure y elimina la protección, por lo que exige tokens anti CSRF complementarios.
Validación de cabeceras Origin y Referer
El navegador adjunta Origin en peticiones POST y CORS, y Referer en la mayoría de peticiones. El servidor puede rechazar solicitudes cuyo origen no coincida con la lista blanca esperada. Es una capa defensiva sencilla y barata, complementaria a los tokens.
Custom request headers + CORS preflight
Si el endpoint exige una cabecera personalizada (por ejemplo, X-Requested-With: XMLHttpRequest o X-CSRF-Token: ...), el navegador disparará un preflight OPTIONS para peticiones cross origin, lo que permite al servidor rechazarlas. Esta técnica funciona bien en APIs consumidas por SPAs propias.
Reautenticación en acciones críticas
Cambio de contraseña, eliminación de cuenta, transferencias de fondos y modificaciones de permisos deberían exigir password o segundo factor, no solo cookie de sesión. Es la defensa más sólida contra CSRF y otros vectores donde la sesión esté comprometida.
Frameworks defaults
Django (CsrfViewMiddleware), Rails (protect_from_forgery), Spring Security (CsrfFilter), ASP.NET Core (AntiforgeryToken) y Laravel (VerifyCsrfToken) incluyen protección activa por defecto. La causa raíz de la mayoría de CSRF modernos no es la ausencia de la defensa, sino su desactivación deliberada para integraciones rápidas, endpoints API mal categorizados o exclusiones genéricas en la configuración.
Casos reales y CVEs públicos
CSRF aparece de forma recurrente en el catálogo CVE, especialmente en plugins WordPress, paneles de administración legacy, dispositivos IoT con interfaces web y software empresarial sin actualización. Búsquedas en el NVD por CSRF o cross-site request forgery devuelven entradas que cubren cambios de configuración en routers domésticos, modificación de cuentas en CMS, ejecución de acciones administrativas en herramientas DevOps y elevación de privilegios en aplicaciones internas. El patrón común es el mismo: endpoint state changing, sesión basada en cookie, ausencia de token o validación de origen.
No se trata de glamorizar exploits, sino de subrayar que la vulnerabilidad sigue activa en código real, particularmente en software heredado, plugins de terceros y endpoints añadidos a posteriori sin revisar la configuración anti CSRF del framework principal.
CSRF en APIs REST y GraphQL
Una SPA que se autentica mediante un token JWT enviado en la cabecera Authorization: Bearer ... es naturalmente inmune a CSRF clásico: el navegador no adjunta automáticamente esa cabecera en peticiones cross origin, y el atacante no puede leer el token desde otro dominio gracias a la política de mismo origen.
El escenario cambia cuando la autenticación se basa en cookies, incluso si la API es REST o GraphQL. Cookies con SameSite=None (necesario en arquitecturas multi dominio) reintroducen el riesgo y exigen protección anti CSRF explícita: tokens en cabecera personalizada, validación de Origin, o doble verificación con cookie y header.
En GraphQL, el riesgo se concentra en mutations. Una mutation expuesta vía POST con Content-Type: application/json queda cubierta por el preflight, pero algunas implementaciones aceptan application/x-www-form-urlencoded o GET para queries, y esa flexibilidad puede ser explotada. La recomendación es restringir explícitamente los content types aceptados y exigir cabecera personalizada en todas las mutations.
Cómo testear CSRF en una auditoría
Las herramientas que automatizan escaneo web (Burp Suite, ZAP, Acunetix, Nessus) detectan ausencia de tokens y configuraciones inseguras de SameSite, pero la confirmación manual sigue siendo imprescindible. El flujo típico en una auditoría:
- Identificar endpoints state changing mediante crawling autenticado.
- Capturar la petición legítima con Burp y replicarla retirando el token y modificando
Origin. - Construir una página de prueba con formulario auto enviado o
fetch()cross origin. - Verificar si la acción se completa con sesión activa de la víctima.
- Probar variantes: GET equivalente, content types alternativos, login CSRF, mutations GraphQL.
Patrones que los automatizadores no detectan: tokens predecibles, tokens reutilizables entre sesiones, validación de Origin permisiva con wildcards, exclusiones puntuales en middleware, y endpoints API añadidos fuera del flujo principal sin protección. Estos hallazgos solo aparecen con revisión manual y conocimiento del framework.
Los tests de regresión deberían cubrir cada endpoint state changing con un caso negativo (petición sin token, petición con origen externo) que se ejecute en CI para evitar regresiones cuando se desactiva CSRF middleware por error.
Encaje con OWASP Top 10
CSRF figuró como categoría independiente en OWASP Top 10 hasta 2017 (A8: Cross-Site Request Forgery). En la edición de 2021 desapareció como categoría propia porque la adopción generalizada de defensas en frameworks redujo su prevalencia relativa. Hoy el riesgo se categoriza dentro de Broken Access Control (A01:2021) cuando el endpoint no verifica adecuadamente el origen de la petición.
La retirada del Top 10 no implica que el riesgo haya desaparecido. Significa que el ratio de aplicaciones vulnerables es menor que el de otras categorías. En código legacy, plugins de terceros y APIs mal configuradas, CSRF sigue siendo un hallazgo frecuente en auditorías profesionales.
Preguntas frecuentes
¿CSRF sigue siendo relevante en 2026?
Sí. Aunque los frameworks modernos protegen por defecto, el problema persiste en código legacy, plugins, integraciones rápidas con CSRF desactivado y APIs basadas en cookies con SameSite=None. Toda auditoría web seria mantiene CSRF en su checklist.
¿SameSite=Lax es suficiente?
SameSite=Lax cubre la mayoría de los vectores POST y elimina ataques triviales basados en formularios cross site. No cubre top level GET ni escenarios complejos con redirecciones. La recomendación profesional es combinar SameSite=Lax o Strict con tokens anti CSRF para defensa en profundidad.
¿El token CSRF rompe APIs?
No, si se diseña correctamente. APIs autenticadas por token Bearer en header no necesitan CSRF token. APIs autenticadas por cookie deben exponer un endpoint para obtener el token o utilizar double submit cookie pattern. El problema aparece cuando se mezclan ambos modelos sin coherencia.
¿Hay CSRF en GraphQL?
Sí, en mutations expuestas con autenticación por cookie y aceptación de content types relajados. La defensa es la misma que en REST: tokens, validación de Origin, content type estricto y preflight obligatorio mediante cabecera personalizada.
¿Login CSRF qué es?
Es la variante en la que el atacante fuerza a la víctima a iniciar sesión con credenciales del atacante. La víctima genera actividad (búsquedas, mensajes, métodos de pago) que el atacante recupera después. Se mitiga con tokens anti CSRF también en el formulario de login y con verificación post login del navegador.
¿Cuándo NO necesito proteger un endpoint?
Endpoints estrictamente idempotentes y de solo lectura (GET puro sin efectos colaterales) no requieren CSRF token. Pero esa categorización debe verificarse: muchos endpoints aparentemente de lectura modifican logs, contadores o estado de sesión y deberían protegerse.
Recursos relacionados
- Pentesting de aplicaciones web
- Pentesting de APIs REST y GraphQL
- Qué es CORS y por qué importa en seguridad web
- Las 5 vulnerabilidades web más comunes en 2025
- Qué es Burp Suite y cómo se usa en pentesting web
- Qué es JWT y consideraciones de seguridad
Auditar CSRF y vulnerabilidades web con Secra
Secra realiza auditorías de aplicaciones web alineadas con OWASP Top 10 y OWASP Web Security Testing Guide. Cubrimos identificación de endpoints state changing, verificación de tokens anti CSRF, análisis de configuración SameSite, pruebas sobre APIs REST y GraphQL, y revisión de la configuración del framework (Django, Rails, Spring, ASP.NET, Laravel) para confirmar que las defensas por defecto no se han desactivado en integraciones puntuales.
Entregamos hallazgos priorizados, casos de prueba reproducibles y recomendaciones de hardening específicas para vuestra arquitectura. También diseñamos suites de regression test que se integran en CI para evitar reintroducir vulnerabilidades cuando el equipo modifica middleware o añade nuevos endpoints.
Si necesitáis una revisión profesional de CSRF, XSS, SSRF y el resto del catálogo OWASP, escribidnos desde /es/contacto/ y planificamos una auditoría adaptada al alcance de vuestra plataforma.
Sobre el autor
Equipo de Secra Solutions
Ethical hackers certificados OSCP, OSEP, OSWE, CRTO, CRTL y CARTE, con más de 7 años de experiencia en ciberseguridad ofensiva. Autores de los CVE-2025-40652 y CVE-2023-3512.