Cross-Origin Resource Sharing (CORS)

Cross-Origin Resource Sharing

Cross-Origin Resource Sharing (CORS)

What is CORS?

CORS stands for Cross-Origin Resource Sharing, which manages cross-origin request. CORS is a mechanism that allows restricted resources (like images, scripts, data) to be requested from another domain.

It is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin.

CORS was introduced along with HTML5. It is a great feature that allows users to overcome the restrictions placed by Same Origin Policy and make the cross-origin HTTP request. But if not configured properly, it is capable of producing disastrous results.

Why CORS?

Allowing cross-origin requests is helpful, as many websites today load resources from different places on the Internet (stylesheets, scripts, images, and more). Means that servers must implement ways to handle requests from origins outside of their own. CORS allows servers to specify who can access the assets on the server, among many other things.

To verify whether a request originates from the same domain or from a cross-domain, the browser decides using the following four parameters:

  1. Protocol
  2. Host
  3. Port
  4. Origin Header

How does CORS manage requests from external resources?

Client and server exchange a set of headers to specify behaviours regarding cross-domain requests. These headers are used to describe the requests and responses. Let’s have a brief introduction about various headers in CORS.

  1. Origin: It is the header which is used to identify the domain from where the requested is executed. This value is used by the server to identify the authentic or cross-domain request.
  2. Access-Control-Request-Method: within the context of pre-flighted requests, the OPTIONS request sends this header to check if the target method is allowed in the context of cross-domain requests.
  3. Access-Control-Request-Headers: within the context of pre-flighted requests, the OPTIONS request sends this header to check if headers are allowed for the target method in the context of cross-domain requests.
  4. Access-Control-Allow-Credentials: It is the header which indicates that the authenticated data can be exposed or not. When initiating a pre-flight request, it indicated that the request can be made using credentials. If any simple GET request is made for a resource with credentials and if this header is not returned with the resource from the server then the response will be ignored by the browser and will not be returned to web content.
  5. Access-Control-Allow-Origin:  This header is used to notify that which domains are authorized or allowed for the request. This header is used in the context of a pre-flighted request.
  6. Access-Control-Allow-Methods: This header is used to notify that which methods are authorized or allowed in the context of the request. This header is used in the context of the pre-flighted request.
  7. Access-Control-Allow-Headers: This header is used to notify that which headers are authorized or allowed in the context of the request. This header is used in the context of the pre-flighted request.

Use Cases:

Simple requests. In simple request HTTP GET, HEAD and POST methods are used. And in the case, only content types with the following values are supported: text/plain, application/x-www-form-url-encoded and multipart/form-data.

Pre-flighted requests. A CORS pre-flight request initiates to check if the CORS protocol is understood and a server is aware using specific requested methods and headers. Firstly, a request (with the HTTP OPTIONS method) is made to check that what should be allowed to perform in the context of cross-domain requests.

For example, asking a server if it would allow a POST request, before sending a POST request, by using a pre-flight request:

OPTIONS /test 
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://test.org

If the server allows it, then it will respond to the preflight request with an Access-Control-Allow-Methods response header, which lists POST method is allowed:

HTTP/1.1 204 No Content
Connection: keep-alive
Access-Control-Allow-Origin: https://test.org
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Max-Age: 72300

When a browser needs data from a public API which is hosted on a different domain it will use Cross-Domain Request to checks whether the request is allowed or not.

The browser initiates an XHR request (XMLHttpRequest (XHR) is an API in the form of an object whose methods transfer data between a web browser and a web server).

Then, the browser sends an OPTIONS request to the API stating it wants to make a request. Part of the request is the custom headers that have been specified for the call. The public API must accept this OPTIONS request. Once the request is accepted the browser will process the actual request.

The above explanation can be understood easily with the help of the diagram given below.

Test Cases for CORS Misconfiguration:

1.    Misconfigured and Exploitable:

Access-Control-Allow-Origin: https://attacker.com
Access-Control-Allow-Credentials: true

Request and Response:

Take note from the request, I injected a header Origin: https://example.com in a request which queries the server for personal user details. And in the response, the server returns Access-Control-Allow-Origin: https://example.com, Access-Control-Allow-Credentials: true, which is a perfect misconfigured CORS scenario.

Steps to reproduce:

Open https://example.com in the browser then inspect the page and go to console.

Run the following code in the console and you would find the server response containing requested information:

 var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get',' https:// ████████’,true); req.withCredentials = true; req.send('{}'); function reqListener() { alert(this.responseText); };
<html>
<script>
Var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get',’ https:// ████████’,true); req.withCredentials = true; req.send('{}'); function reqListener() { alert(this.responseText); };
</script>
</html>

Open above code in any browser and you would find it pops up user information

2.    Poorly Implemented and Exploitable:

Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true

Request and Response:

Similarly, in this scenario server returns Access-Control-Allow-Origin: null, Access-Control-Allow-Credentials: true, which is again an exploitable scenario for CORS.

Similarly, running the below-mentioned exploit, the server responded with the requested information:

Resources access on the attacker’s server

3.    Bad Implementation but Not Exploitable:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Note: Modern browsers ignore the credential header when the origin is set to ‘*’.

Request and Response:

On the above response, it returns Access-Control-Allow-Origin: *, Access-Control-Allow-Credentials: true. In this case, the Access-Control-Allow-Credentials is always treated as false by modern browsers and doesn’t allow sharing of authenticated resources.

Because for wildcard origin Access-Control-Allow-Credentials is by default set to false and doesn’t accept user-defined value for this header which means sharing of authenticated resources will not be possible.

Run the below exploit and you would find it error information in the console of browser:

Question: How Wildcard origin (*) condition is different from Null origin(null) condition?

Answer: Null origin allows post-authentication sharing of resources if Access-Control-Allow-Credentials set to true but in Wildcard origin case, the Access-Control-Allow-Credentials is always treated as false and doesn’t allow sharing of resources.

IMPACT:

The major risk in these scenarios is that an attacker can tamper the Origin request HTTP header to forcefully provide the targeted resource content. When the browser web client is used, the header values are managed by the browser but also another “web clients” can be used to change/override the “Origin” header values.

Using these misconfigurations, the attacker can do many actions depending on the functionality of application like:

1) Read, Update, Delete Users information (Email, Location, Bio etc)

2) Stealing Authenticity tokens

3) View private data of accounts and even terminate accounts.

Recommendations to fix CORS Misconfiguration:

Implement below mitigations:

  1. Rather than using a wildcard or programmatically verifying supplied origins, use a whitelist of trusted domains
  2. Don’t generate Access-Control-Allow-Origin header based on the user-supplied Origin value
  3. Validate the Origin header
  4. Valid domain name
  5. Specify Vary: Origin
  6. Don’t trust null Origin
  7. Allow multiple origins

References:

https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

https://www.keycdn.com/support/cors

For More Blogs click here

  •  
  •  
  •  
  •  
  •  
  •  
  •