CSRF y CORS: Protege las solicitudes del navegador

Security2026-09-14TryQuickToolBox

Has construido una aplicación web con una API limpia, pero luego notas solicitudes extrañas en tus registros, o peor, un escáner de seguridad marca tu sitio por configuraciones incorrectas de CSRF y CORS. Estas dos siglas a menudo se agrupan, pero resuelven problemas diferentes. Malinterpretarlas puede dejar a tus usuarios vulnerables o romper solicitudes legítimas entre orígenes.

En este artículo, aclararemos qué son realmente CSRF y CORS, cómo interactúan con la seguridad del navegador y te daremos pasos concretos para proteger tus aplicaciones sin romper la funcionalidad.

¿Qué es CSRF y por qué debería importarte?

Cross-Site Request Forgery (CSRF) es un ataque que engaña al navegador de un usuario para que envíe una solicitud a un sitio donde está autenticado. Imagina que has iniciado sesión en tu banco en bank.com. Luego visitas un sitio malicioso que contiene una etiqueta de imagen como <img src="https://bank.com/transfer?to=attacker&amount=1000">. Tu navegador incluye automáticamente tus cookies del banco con la solicitud, y si el banco no tiene protecciones CSRF, la transferencia se realiza.

El punto clave: CSRF explota la confianza que un sitio tiene en el navegador del usuario. El atacante no necesita robar tu sesión; solo necesita que tu navegador haga una solicitud en tu nombre.

Cómo funcionan los ataques CSRF

Para que un ataque CSRF tenga éxito, se deben cumplir tres condiciones:

Los objetivos comunes son operaciones que cambian el estado: cambiar el correo electrónico, transferir fondos, publicar contenido o modificar permisos.

¿Qué es CORS y por qué existe?

Cross-Origin Resource Sharing (CORS) es un mecanismo del navegador que permite o deniega que las páginas web realicen solicitudes a un dominio diferente al que sirvió la página. Es una extensión de la Política del Mismo Origen (SOP), que restringe cómo un documento o script cargado desde un origen puede interactuar con recursos de otro origen.

Sin CORS, un sitio malicioso podría usar JavaScript para leer datos de la API de tu banco si has iniciado sesión. CORS brinda a los servidores una forma de permitir explícitamente ciertas solicitudes entre orígenes.

La Política del Mismo Origen (SOP)

Dos URL tienen el mismo origen si el protocolo, el host y el puerto son idénticos. Por ejemplo, https://example.com/app y https://example.com/api comparten el mismo origen, pero http://example.com (protocolo diferente) y https://api.example.com (host diferente) no.

SOP evita que los scripts de un origen lean respuestas de otro origen. CORS relaja esto añadiendo encabezados HTTP que le indican al navegador si debe permitir la solicitud.

CSRF vs CORS: diferencias clave

Es crucial entender que CSRF y CORS no son opuestos; abordan preocupaciones de seguridad diferentes. CSRF se trata de prevenir solicitudes no autorizadas que cambian el estado, mientras que CORS se trata de controlar qué orígenes pueden leer respuestas.

Aspecto CSRF CORS
Objetivo principal Prevenir solicitudes falsificadas Controlar lecturas entre orígenes
Vector de ataque Sitio malicioso desencadena solicitudes Sitio malicioso lee respuestas
Mecanismo de defensa Tokens, cookies SameSite Encabezados HTTP (Access-Control-*)
Aplicación por el navegador Ninguna (el servidor debe validar) Sí (el navegador bloquea lecturas)

Cómo defenderse contra CSRF

Existen varias estrategias probadas para mitigar CSRF. No necesitas todas, pero es prudente superponer defensas.

1. Usa tokens anti-CSRF

La defensa más robusta es incluir un token único e impredecible en cada solicitud que cambia el estado. El servidor valida el token antes de procesar. Los tokens deben estar vinculados a la sesión del usuario y no exponerse en las URL (para evitar fugas a través de encabezados de referrer).

// Ejemplo: Generar y validar un token CSRF en Node.js/Express
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });

app.get('/form', csrfProtection, (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});

app.post('/process', csrfProtection, (req, res) => {
  // El token se valida automáticamente
  res.send('OK');
});

2. Configura cookies SameSite

Los navegadores modernos admiten el atributo SameSite para las cookies. Establecerlo en Lax o Strict evita que el navegador envíe cookies en solicitudes entre sitios, lo que bloquea muchos ataques CSRF. Lax permite cookies en navegaciones de nivel superior (por ejemplo, al hacer clic en un enlace), mientras que Strict bloquea todas las solicitudes entre sitios.

Set-Cookie: sessionId=abc123; SameSite=Lax; Secure; HttpOnly

3. Verifica los encabezados Origin y Referer

Verifica el encabezado Origin o Referer en las solicitudes entrantes. Si no coinciden con tu dominio esperado, rechaza la solicitud. Esta es una capa adicional simple pero efectiva.

4. Usa encabezados personalizados para AJAX

Si tu API se consume a través de JavaScript, requiere un encabezado personalizado como X-Requested-With. Los navegadores aplican la verificación previa (preflight) de CORS para encabezados personalizados, por lo que un simple POST de formulario desde un sitio malicioso no lo incluirá.

Configurar CORS correctamente

Las configuraciones incorrectas de CORS también pueden provocar problemas de seguridad. El error más común es establecer Access-Control-Allow-Origin: * mientras también se permiten credenciales. Esa combinación está prohibida por los navegadores, pero a veces los desarrolladores intentan sortearla de manera insegura.

Mejores prácticas para encabezados CORS

# Ejemplo: Configuración de Nginx para CORS
location /api/ {
  if ($http_origin ~* (https://(app|admin)\.example\.com)) {
    add_header 'Access-Control-Allow-Origin' $http_origin;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
  }
  if ($request_method = 'OPTIONS') {
    return 204;
  }
}

Recuerda que CORS lo aplica el navegador, no el servidor. No es un sustituto de la autenticación o autorización; es una forma de relajar la política del mismo origen de manera segura.

Poniéndolo todo junto

Proteger las solicitudes del navegador requiere un enfoque por capas. Aquí tienes una lista de verificación rápida:

  1. Usa tokens anti-CSRF para todas las operaciones que cambian el estado.
  2. Configura cookies SameSite en Lax o Strict.
  3. Valida los encabezados Origin/Referer en el servidor.
  4. Configura CORS con precisión: lista blanca de orígenes, limita métodos y evita comodines con credenciales.
  5. Prueba regularmente tu aplicación con escáneres de seguridad y verificaciones manuales.

Al comprender los roles distintos de CSRF y CORS, puedes evitar errores comunes y construir una aplicación web más segura.

Preguntas frecuentes

¿Puede CORS prevenir ataques CSRF?

No, CORS no previene CSRF. Los ataques CSRF no dependen de leer respuestas; simplemente desencadenan solicitudes. CORS controla qué orígenes pueden leer respuestas, pero no bloquea el envío de la solicitud. Para prevenir CSRF, necesitas tokens, cookies SameSite o validación de origen.

¿Es seguro establecer Access-Control-Allow-Origin en '*'?

Establecerlo en '*' es seguro solo si tu API no usa credenciales (cookies, autenticación HTTP). Si hay credenciales involucradas, los navegadores rechazarán la respuesta. Para API autenticadas, especifica siempre orígenes exactos.

¿Necesito protección CSRF si uso JWT en encabezados Authorization?

Si almacenas JWT en cookies, aún necesitas protección CSRF porque las cookies se envían automáticamente. Si almacenas JWT en memoria y los envías a través del encabezado Authorization, CSRF no es una preocupación porque el atacante no puede establecer encabezados personalizados entre orígenes. Sin embargo, debes protegerte contra XSS para mantener el token seguro.

¿Listo para probar los encabezados CORS de tu API? Usa nuestro Analizador de Registros de Nginx para inspeccionar patrones de solicitudes y detectar intentos sospechosos entre orígenes.