CORS is a security feature that’s often misunderstood, and its misconfigurations are a surprisingly common source of web application vulnerabilities.

Let’s see how Burp Suite can help us uncover these misconfigurations by intercepting and manipulating requests.

Imagine a browser making a request to https://api.example.com from https://app.example.com. The browser, following CORS rules, will first send a preflight request to https://api.example.com with the OPTIONS method. This preflight request includes headers like Origin (indicating where the request is coming from, e.g., https://app.example.com) and Access-Control-Request-Method (e.g., GET). The server’s response to this preflight request is crucial. If the Access-Control-Allow-Origin header in the response matches the Origin of the request, or is a wildcard (*), the browser then proceeds to send the actual GET request.

Here’s a simplified flow of a legitimate request:

  1. Browser: Sends OPTIONS /resource to https://api.example.com
    • Origin: https://app.example.com
    • Access-Control-Request-Method: GET
    • Access-Control-Request-Headers: Authorization
  2. API Server: Responds with 200 OK
    • Access-Control-Allow-Origin: https://app.example.com
    • Access-Control-Allow-Methods: GET, POST, OPTIONS
    • Access-Control-Allow-Headers: Authorization
  3. Browser: Receives 200 OK and sees Access-Control-Allow-Origin matches its origin.
  4. Browser: Sends GET /resource to https://api.example.com
    • Origin: https://app.example.com
    • Authorization: Bearer <token>

Now, let’s use Burp Suite to probe for misconfigurations.

1. Basic Preflight Interception and Modification

First, configure your browser to use Burp Suite as a proxy and navigate to https://app.example.com. Then, try to perform an action that would normally trigger an API call.

In Burp’s Proxy tab, you’ll see the OPTIONS preflight request. Let’s say the server responds with Access-Control-Allow-Origin: https://app.example.com.

Diagnosis: We want to see if the API will accept requests from any origin, not just https://app.example.com. Action:

  • Right-click the OPTIONS request in Burp Proxy history.
  • Select "Send to Repeater".
  • In Repeater, change the Origin header from https://app.example.com to http://evil.com.
  • Send the request.

Observation: If the server responds with Access-Control-Allow-Origin: http://evil.com (or *), that’s a critical misconfiguration.

Fix: The server-side configuration needs to restrict the Access-Control-Allow-Origin header to only trusted origins. For example, if your API is only meant to be accessed by https://app.example.com, the configuration should explicitly state that: Access-Control-Allow-Origin: https://app.example.com.

2. Testing Access-Control-Allow-Credentials

This header controls whether the browser is allowed to send credentials (like cookies or HTTP authentication) with cross-origin requests.

Diagnosis: If Access-Control-Allow-Credentials is set to true for an origin that shouldn’t be allowed to send credentials, it can lead to session hijacking if an attacker can trick a user into making a request from their malicious site.

Action:

  • In Burp Repeater, take a preflight request where the Origin is https://app.example.com.
  • Modify the Origin header to http://evil.com.
  • Add or ensure the Access-Control-Allow-Credentials: true header is present in your request (though this header is typically part of the response, we’re testing if the server allows it to be sent in the request, and then observing the response).
  • Send the request.

Observation: If the server responds with Access-Control-Allow-Credentials: true even when the Origin is http://evil.com, it’s vulnerable. The browser will then allow http://evil.com to make authenticated requests to your API.

Fix: The Access-Control-Allow-Credentials header should only be set to true if the Access-Control-Allow-Origin is a specific, trusted origin (never *). If Access-Control-Allow-Origin is *, Access-Control-Allow-Credentials must not be true.

3. Exploiting Wildcard Access-Control-Allow-Origin

The most common and dangerous CORS misconfiguration.

Diagnosis: The server allows any origin to access its resources.

Action:

  • Take any preflight request intercepted by Burp.
  • Send it to Repeater.
  • Change the Origin header to http://malicious.com.
  • Send the request.

Observation: If the server responds with Access-Control-Allow-Origin: *, or Access-Control-Allow-Origin: http://malicious.com, then any website can make requests to your API, potentially reading sensitive data or performing actions on behalf of users if credentials are also allowed.

Fix: Configure the server to explicitly list allowed origins. For instance, in Nginx, this might look like:

add_header 'Access-Control-Allow-Origin' 'https://app.example.com' always;

Or, if you need multiple origins:

if ($http_origin = "https://app.example.com") {
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
}
if ($http_origin = "https://another.app.com") {
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
}

4. Missing Access-Control-Allow-Methods or Access-Control-Allow-Headers

If these are missing or too permissive, an attacker might be able to use HTTP methods or headers that weren’t intended for cross-origin access.

Diagnosis: The server allows a preflight request but doesn’t properly restrict which methods or headers can be used.

Action:

  • Intercept a preflight request.
  • Send it to Repeater.
  • Change the Access-Control-Request-Method header to something more powerful, like DELETE or PUT.
  • Change Access-Control-Request-Headers to include unexpected headers like Content-Type: application/json if it wasn’t previously allowed.
  • Send the request.

Observation: If the server responds with a 200 OK and Access-Control-Allow-Origin is valid, but the Access-Control-Allow-Methods or Access-Control-Allow-Headers in the response do not permit the requested method/headers, the browser will block the actual request. However, if the server does allow these, it’s a misconfiguration.

Fix: Ensure the Access-Control-Allow-Methods header lists only the HTTP methods your API endpoints support for cross-origin requests (e.g., GET, POST, OPTIONS). Similarly, Access-Control-Allow-Headers should list only the custom headers your API expects from cross-origin requests.

5. Exploiting Vary: Origin Header

The Vary header is used by caches to determine if a cached response is suitable for a given request.

Diagnosis: If Vary: Origin is not correctly set on responses that have an Access-Control-Allow-Origin header, caching proxies might serve an incorrect Access-Control-Allow-Origin to subsequent requests from different origins.

Action:

  • Make a request from https://app.example.com to your API. Observe the Access-Control-Allow-Origin in the response.
  • Make a request from https://another.app.com to your API. Observe its Access-Control-Allow-Origin.
  • If the API server does not include Vary: Origin in its responses, and a caching proxy is in use, there’s a potential for mis-caching.

Observation: An attacker could potentially poison the cache by making a request from their malicious site, causing the cache to serve that origin’s Access-Control-Allow-Origin to legitimate users.

Fix: For any response that includes an Access-Control-Allow-Origin header, ensure the server also includes Vary: Origin. This tells caches that the response content depends on the Origin header of the incoming request and prevents incorrect responses from being served.

6. CORS Bypass via Referer Header Manipulation (Less Common for CORS, but worth noting)

While CORS is primarily controlled by the Origin header, some older or misconfigured systems might incorrectly rely on the Referer header for access control.

Diagnosis: The API might be checking the Referer header instead of, or in addition to, the Origin header for access control.

Action:

  • In Burp Repeater, send a standard request to an API endpoint.
  • Modify the Referer header to http://evil.com/page.html.
  • Remove the Origin header entirely.
  • Send the request.

Observation: If the API still grants access and returns the requested data, it indicates a potential weakness. This is less a "CORS misconfiguration" and more a general access control flaw that can be triggered in a cross-origin context.

Fix: Ensure that access control logic strictly relies on the Origin header for cross-origin requests and that the Referer header is not used as the sole arbiter of access.

When you’ve fixed all CORS issues, the next error you’ll encounter is likely a different class of security vulnerability, such as a JSON Web Token (JWT) validation flaw or an insecure direct object reference (IDOR).

Want structured learning?

Take the full Burpsuite course →