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:
- Browser: Sends
OPTIONS /resourcetohttps://api.example.comOrigin: https://app.example.comAccess-Control-Request-Method: GETAccess-Control-Request-Headers: Authorization
- API Server: Responds with
200 OKAccess-Control-Allow-Origin: https://app.example.comAccess-Control-Allow-Methods: GET, POST, OPTIONSAccess-Control-Allow-Headers: Authorization
- Browser: Receives
200 OKand seesAccess-Control-Allow-Originmatches its origin. - Browser: Sends
GET /resourcetohttps://api.example.comOrigin: https://app.example.comAuthorization: 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
OPTIONSrequest in Burp Proxy history. - Select "Send to Repeater".
- In Repeater, change the
Originheader fromhttps://app.example.comtohttp://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
Originishttps://app.example.com. - Modify the
Originheader tohttp://evil.com. - Add or ensure the
Access-Control-Allow-Credentials: trueheader 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
Originheader tohttp://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-Methodheader to something more powerful, likeDELETEorPUT. - Change
Access-Control-Request-Headersto include unexpected headers likeContent-Type: application/jsonif 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.comto your API. Observe theAccess-Control-Allow-Originin the response. - Make a request from
https://another.app.comto your API. Observe itsAccess-Control-Allow-Origin. - If the API server does not include
Vary: Originin 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
Refererheader tohttp://evil.com/page.html. - Remove the
Originheader 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).