githubEdit

Cross origin resource sharing (CORS)

CORS (Cross-Origin Resource Sharing) — guide for web hacking / defender awareness

  • Cross-Origin Resource Sharing (CORS) is a browser mechanism that enables controlled access to resources located outside of a given domain.

  • SOP (Same Origin Policy) = locks on your house to stop neighbours from sneaking in.

  • CORS = special permission keys so a friendly neighbour can visit.

  • Misconfigured CORS = giving a key to anyone who says they are your friend even if they're not.


What is CORS

Imagine two houses:

  • House A: example.com

  • House B: otherwebsite.com

Normally, if you live in House A, you can't just walk into House B's living room and read their private letters. This is the Same Origin Policy (SOP) — it keeps things safe and private.

CORS is like giving House B a special key:

  • House B gives permission: "Hey browser, it's okay for House A to read certain things in my house if they come with a key."

Why use CORS

  • Sometimes websites need to share data — e.g., example.com wants to ask weather.com for a forecast.

  • CORS lets browsers relax SOP rules so example.com can talk to weather.com in a controlled way.

Where does the vulnerability come from?

Common misconfigurations and issues:

  1. Bad configuration: trusting any origin (Access-Control-Allow-Origin: * + credentials true)

    • Analogy: Putting a sign on your front door “Everyone welcome — even with keys to the safe inside.”

  2. Trusting user input (reflecting Origin header without validation)

    • Analogy: Letting anyone who says "I'm John" in without checking.

  3. Trusting any subdomain (loose suffix matching)

    • Analogy: Trusting anyone whose last name is "Advisor" — you trust EvilAdvisor too.

  4. Trusting weird origins like null

    • Analogy: Letting in anyone who says they’re from nowhere.

  5. Ignoring protocol (allowing http origins for https site)

    • Analogy: Letting a safe be opened by a key coming via an unlocked bicycle (HTTP).

  6. Forgetting Vary: Origin (cache poisoning)

    • Analogy: Leaving your mailbox open; a stranger plants fake letters.

Real-world example (high level)

  • A crypto exchange loads sensitive info (API key) on the account page via AJAX when a user is logged in.

  • If the exchange incorrectly trusts and reflects the Origin header (or whitelists null, wildcards, or insecure subdomains) and Allow-Credentials is enabled, then a malicious site can cause a logged-in victim’s browser to request that endpoint and read the response — exfiltrating the API key.

Diagrams (conceptual):

Normal Safe Case:

  • User at example.com → Browser blocks request (SOP) → bitcoin.com: "No, you can’t ask me!"

Dangerous CORS Misconfiguration:

  • Attacker site attacker.com pretends to be trusted → bitcoin.com API responds with secrets → attacker steals API key.


lab: CORS vulnerability with basic origin reflection

1

Introduction

  • Scenario: penetration tester inspects a crypto exchange that loads private info via AJAX after login.

  • Issue: server reflects the Origin header without strict validation, allowing attacker-controlled origin values.

  • Impact: if victim visits malicious page, their browser will include session cookies (withCredentials: true), and the server will allow the response to be read by the malicious origin.

2

Vulnerability — problem

  • Source: server reflects user-supplied Origin header without strict validation.

  • Sink: Access-Control-Allow-Origin accepts attacker's site + Access-Control-Allow-Credentials: true.

  • Challenge: determine if server reflects arbitrary origins and leaks sensitive data.

3

End goal

  • Steal victim's API key from /accountDetails using a crafted CORS exploit.

4

Reconnaissance plan

  • Initial test: log in normally and observe AJAX request for /accountDetails.

  • Inspect vulnerability: send the same request in Burp Repeater, add header Origin: https://example.com, and check if the response reflects that Origin.

5

Attack — crafting the exploit

  • Exploit payload to run from attacker-controlled site:

  • Upload payload to exploit server and deliver to victim. Victim’s browser auto-fetches API key and sends it to attacker logs.

6

Trigger & enumerate

  • Deliver exploit to victim, retrieve API key from exploit server logs, and use it to complete the lab.

Why the exploit works:

  • Server trusts arbitrary Origin (reflects attacker-supplied value).

  • Allow-Credentials enabled: victim's session cookies included.

  • Victim's browser exposes sensitive API key to attacker's site.

Real-world impact:

  • Account takeover, data leakage, bypass of authentication protections.


Whitelisted null origin explanation (analogy)

  • Office allows guests if name/address are on guest list (SOP).

  • They also allow people who write "No Address" (Origin: null) for devs/local files.

  • Attackers can write "No Address" and be let in, then access secure file room and exfiltrate documents.

Mapping:

  • "No Address" = Origin: null

  • Security guard = server's CORS policy

  • File room = sensitive endpoint

  • Sneaking copies out = sending stolen data to attacker site

  • Attacker disguise = sandboxed iframe or other trick that causes Origin: null


lab: CORS vulnerability with trusted null origin

1

Introduction

  • Scenario: server’s CORS policy whitelists the null origin (often for local development).

  • Attack: force the victim’s browser to send a request with Origin: null (e.g., sandboxed iframe). If the server allows such requests with credentials, the attacker can retrieve and exfiltrate sensitive data.

2

Vulnerability — problem

  • Source: server accepts Origin: null in Access-Control-Allow-Origin.

  • Sink: combined with Access-Control-Allow-Credentials: true, cross-origin requests include cookies.

  • Challenge: generate a request from victim’s browser with Origin: null so server allows the response to be read.

3

End goal

  • Steal administrator’s API key from /accountDetails using a malicious page that forces Origin: null.

4

Reconnaissance plan

  • Log in and view My Account; see AJAX to /accountDetails returning API key.

  • Send a request with header Origin: null via Burp Repeater; confirm server reflects null in ACAO and allows credentials.

5

Attack — crafting the exploit

  • Payload (host on exploit server) to force Origin: null via sandboxed iframe:

  • Upload to exploit server and deliver to victim. Victim visits malicious page → browser sends Origin: null request → server responds with API key → key exfiltrated to attacker logs.

6

Trigger & enumerate

  • Deliver exploit to victim; check exploit server logs for stolen API key and submit it to complete the lab.

Why the exploit works:

  • Null origin whitelisted.

  • Browser includes cookies (allow-credentials).

  • Sandboxed iframe causes Origin: null.

Real-world impact:

  • Sensitive data theft, account compromise, SOP bypass via null origin.


Exploiting XSS via CORS trust relationships (high level)

Analogy:

  • Bank stores spare vault key at a trusted subdomain.

  • If that subdomain has an XSS (broken lock), an attacker can steal the spare key and access the main vault.

Mapping:

  • Bank vault = sensitive API endpoint (/api/requestApikey)

  • Spare key at friend’s house = CORS trust to subdomain

  • Broken lock = XSS on subdomain

  • Thief using the key = attacker JS on subdomain pulling data from main site

Even if main site is secure, trusting an insecure subdomain to store access is risky.


Breaking TLS with poorly configured CORS (high level)

Analogy:

  • Main system uses HTTPS locked vans. Trusted subdomain uses HTTP bicycles without locks.

  • A network attacker (MITM) intercepts the HTTP bicycle traffic, tampers with requests, and gets the main service to send vault documents to the attacker.

Mapping:

  • Locked vans = HTTPS

  • Bicycle without locks = HTTP subdomain

  • Mail thief controlling the road = MITM attacker

  • Vault documents = sensitive API response

  • Main post office trusting bicycle = CORS whitelist including HTTP origin

Trusting insecure (HTTP) origins in CORS can allow MITM-based exfiltration of otherwise HTTPS-protected data.


lab: CORS vulnerability with trusted insecure protocols (HTTP subdomain)

Introduction

  • Scenario: site trusts all subdomains regardless of HTTPS/HTTP. Attacker finds an HTTP subdomain with XSS, injects JS, and uses CORS trust to read data from main HTTPS site.

Vulnerability — problem

  • Source: CORS trusts all subdomains, including insecure HTTP ones.

  • Sink: Access-Control-Allow-Credentials: true sends victim cookies.

  • Challenge: inject JS into HTTP subdomain to read sensitive data from the secure main site.

End goal

  • Steal admin API key from /accountDetails via XSS on an HTTP subdomain exploiting CORS trust.

Reconnaissance plan

  • Log in, observe /accountDetails returns API key.

  • Test Origin: http://subdomain.lab-id and confirm server reflects it in ACAO.

  • Find a product page on HTTP subdomain vulnerable to XSS (productId parameter).

Attack — crafting the exploit

  • Example attack flow: inject JS on HTTP subdomain to make a CORS request to the HTTPS main site and exfiltrate result:

Good:

  1. Only allow trusted sites (no reflection or fuzzy matches)

  • Do not reflect the Origin header blindly. Use an exact allowlist (scheme + host + port).

Good example (Node/Express):

  1. Never whitelist null

  • Browsers send Origin: null from file:, data:, sandboxed iframes. Do not accept null for sensitive endpoints. Use explicit dev origins like https://localhost:3000 instead.

Bad:

  1. Avoid wildcards on internal networks

  • Do not use ACAO: * for sensitive or internal APIs.

Bad:

Good:

  1. Remember: CORS ≠ server-side security

  • CORS controls what browsers can read. It does not replace authentication, authorization, CSRF protections, rate limiting, or session management.

Other best practices:

  • Enforce HTTPS (reject http:// origins).

  • Minimize allowed methods/headers:

  • Add Vary: Origin when ACAO is dynamic to prevent cache poisoning.

  • Keep server-side protections (authN/authZ, CSRF, rate limiting).

Quick checklist:

  • Exact allowlist (scheme+host+port), no reflection.

  • No wildcards (*) for sensitive endpoints.

  • No null origin whitelisting.

  • Enforce HTTPS only origins.

  • Tighten methods/headers; preflight responds 204.

  • Vary: Origin when ACAO is dynamic.

  • Keep server-side auth and protections active.


Example snippets and tests

Good server response for authenticated endpoints (example):

Bad patterns to avoid:

  • Echoing req.headers.origin without validation.

  • Allowing Access-Control-Allow-Origin: null for production.

  • Using Access-Control-Allow-Origin: * on sensitive endpoints.

Quick curl tests:

Minimal Nginx strict allowlist (concept):

Spring Boot strict CORS (concept):


Attack ↔ Defense quick map (summary)

  • ACAO: * on sensitive endpoints → risk: any site can read it → defense: exact trusted origin(s) only.

  • Reflecting Origin without validation → risk: full data exfiltration → defense: exact allowlist (scheme+host+port).

  • Whitelisting null → risk: sandbox/file/data abuse → defense: never allow null in production.

  • Allowing HTTP origins → risk: MITM/HTTPS bypass → defense: HTTPS-only origins.

  • Missing Vary: Origin with dynamic ACAO → risk: cache poisoning → defense: set Vary: Origin.

  • Over-permissive methods/headers → risk: expanded attack surface → defense: minimize to required.

  • Relying on CORS as auth → risk: direct API abuse → defense: keep robust authN/authZ and CSRF protections.


Final checklist (concise)

  • Exact allowlist (scheme+host+port); no reflection.

  • No wildcards (*) for sensitive endpoints.

  • No null origin whitelisting.

  • HTTPS-only origins; reject http://.

  • Tighten methods/headers; preflight responds 204.

  • Vary: Origin when ACAO is dynamic.

  • Keep server-side auth/CSRF/authorization/rate limits.

Last updated