Modern applications often depend on Cross-Origin Resource Sharing (CORS) to enable smooth integrations between services – but this convenience can become a serious security risk if misconfigured.
CORS-related flaws, part of OWASP’s Security Misconfiguration category (#5 in the Top 10), are often overlooked yet can expose sensitive APIs, compromise user data, and enable attackers to escalate privileges or impersonate users. To understand how these vulnerabilities arise, we must first grasp a foundational concept in web security: the origin.
What is the meaning of an origin?
Two websites are said to have same origin if they share the following:
- Scheme (http, https)
- Host name (google.com, facebook.com, securelayer7.net)
- Port number (80, 443 etc.)
For example, http://example.com and http://example.com/settings share the same origin. However, https://example.com:4657 and http://example.com:8080/settings have different origins.
The Same Origin Policy restricts how scripts from one origin can interact with resources from another. It’s a built-in browser security mechanism to isolate potentially malicious scripts.
What is CORS (Cross Origin Resource Sharing)?
CORS is a browser mechanism that extends the Same-Origin Policy by allowing servers to specify which origins can access their resources. It enables secure cross-origin requests for modern web applications.
Examples of cross-origin scenarios:
- Cross-Origin Writes: e.g., submitting a form (POST) to another domain.
- Cross-Origin Embedding: e.g., embedding images via <img src> or websites via <iframe src>.
CORS uses HTTP headers to define permitted origins and request types, balancing security with functionality. It allows trusted cross-origin interactions and is essential for Web 2.0+ applications, especially for integrating frontend frameworks with APIs.
Modern frontend applications (e.g., React, Angular, Vue) rely heavily on secure CORS configurations to connect with backend APIs and third-party services. Misconfigured CORS in such environments can expose sensitive data or enable unauthorized access.
Popular applications like Google, YouTube, and Flickr implement strict CORS rules to control access to their resources.
Key CORS Headers to Know
- Origin: Set by the browser in every CORS request. Indicates the source domain of the request.
- Access-Control-Allow-Origin: Set by the server in the response. Determines whether the request’s origin is permitted.
- Access-Control-Allow-Methods: Specifies the allowed HTTP methods (GET, POST, etc.).
- Access-Control-Allow-Headers: Lists headers that can be used in the actual request.
- Access-Control-Max-Age: Specifies how long preflight results can be cached by the browser.
A scenario to exploit CORS vulnerability:
Target: Vulnerable intranet application located at http://127.0.0.1:80/bwapp/ containing a secret at secret-cors-3.php. The Admin accesses it locally.
Goal: As an attacker, capture the secret remotely using a CORS misconfiguration.
The exploitation:
- The Admin (victim) visits the attacker’s site.
- The attacker hosts a website with a malicious script at http://127.0.0.1:4567.
3. The attacker’s site contains a payload that executes on page load.
4. The payload sends a CORS request to http://127.0.0.1:80/bwapp/secret-cors-1.php.
5. The vulnerable server responds with the secret.
6. The server has Access-Control-Allow-Origin: *, allowing any origin. The script sends the secret to the attacker’s server at http://127.0.0.1:7777.
7. The attacker monitors the logs and captures the secret.
Note:
CORS also involves preflight requests using the HTTP OPTIONS method. Improper handling of these requests can reveal CORS policies and increase the risk of exploitation.
How to mitigate CORS Vulnerability?
- Never set Access-Control-Allow-Origin to * for resources containing sensitive data.
- Allow only trusted domains explicitly, e.g., Access-Control-Allow-Origin: https://saurabh.com.
- Avoid using Access-Control-Allow-Credentials: true in combination with * origin. Modern browsers block this, but legacy systems may still be vulnerable.
The illustration below (not shown here) demonstrates that properly configured CORS headers prevent unauthorized access.
CORS Patch: Server-Side Validation (Common Mistake)
Using regex patterns incorrectly can lead to bypasses:
if (preg_match("/^https://mail.example.com$/", $_SERVER["HTTP_ORIGIN"])) {
header("Access-Control-Allow-Origin: https://mail.example.com");
}
In this example, . matches any character, allowing spoofed domains like https://mailxexample.com.
Correct Implementation:
if ($_SERVER["HTTP_ORIGIN"] == "https://mail.example.com") {
header("Access-Control-Allow-Origin: https://mail.example.com");
}
Additionally:
- Sanitize all cross-domain data before rendering it.
- Don’t blindly trust responses from third-party domains.
What if the Origin header is spoofed?
- If a user is tricked into visiting a malicious site, their browser won’t allow forged origin headers due to SOP.
- Attackers cannot spoof origin headers from the client side.
- Even in man-in-the-middle scenarios, it’s more valuable to steal cookies or tokens than to spoof origin headers.
Browser behavior is becoming stricter. Modern browsers enforce enhanced CORS and cookie policies, such as:
- Blocking credentials with wildcard origins.
- Enforcing SameSite cookie policies.
- Implementing Cross-Origin-Resource-Policy (CORP).
OWASP CORS Vulnerability:
This vulnerability falls under Security Misconfiguration in the OWASP Top 10. The root cause often lies in improper configuration of Access-Control-Allow-Origin headers.