API Security: Learn about CORS

Oct 22, 2022 By Puneet verma

  

Resource Sharing

A web application hosted on a.com

  • Accessing the resource from a.com is same-origin(SO) resources sharing
  • Accessing any other domain or subdomain is referred to as cross-origin resources sharing(CORS)

For security reasons, browsers implemented a same-origin policy(SOP), i.e. restriction of cross-origin resources.

  • A web application may freely use cross-origin resources like images, stylesheets, scripts, iframes, and cross-domain requests like HTTP requests(Ajax call, APIs) are forbidden by default by the same-origin security policy(SOP).

Cross-Origin Resource Sharing (CORS)

Defines a way for the client application to interact with the resources outside its domain.

Though limiting an application to use the same origin resources enhances security may not always be practical. We often require 3rd party integrations.

Cross-Origin Resource Sharing (CORS) is an HTTP-header-based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources.

 

Working of CORS

We have to include the Access-Control-Allow-Origin header in the response of our application.

A web browser compares the Access-Control-Allow-Origin with the requesting website's origin and permits access to the response if they match.

Example

Suppose a website with the origin normal-website.com causes the following cross-domain request to robust-website.com

GET /data HTTP/1.1
Host: robust-website.com
Origin : https://normal-website.com

The server on robust-website.com returns the following response:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com

The browser will allow code running on normal-website.com to access the response because the origins match

Do Read https://portswigger.net/web-security/cors/access-control-allow-origin

 

How to allow CORS?

We need to add a CORS header in each API response. 
 

Access-Control-Allow-Origin: http://www.example.com

Access-Control-Allow-Origin: *'

Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE

Access-Control-Allow-Headers: Content-Type, X-Auth-Token, Origin, Authorization

 

Preflight

In order to relax the SOP, CORS helps modern browsers to achieve cross-domain resource access. With this relaxation new thread arises like CSRF.  

As per the W3C specification, the browser first makes the preflight request to validate whether the supported methods are valid from the server.

For any non-simple request, the browser sends a preflight request without client intervention. When the browser gets a valid server response, it requests with the actual HTTP request method.

Simple Request
For certain requests, preflight is not performed by the browser.

Http method:  GET/HEAD/POST
Content Type: application/x-www-form-urlencoded or multipart/form-data or text/plain

Refer to w3c CORS specification for details

We cannot force browsers to avoid the options request in case of non-simple requests type.

Does CORS protect against CSRF?

CORS is not meant to protect your application from crafted HTTP requests, and it will protect against certain kinds of attacks where the user's cookies or access tokens are involved.
    
Example
Let's imagine the user is logged in to their banking site at a.com and user is navigated to the malicious b.com. That page includes javascript that tries to send a request to a.com. Since the user is logged into A.com, that request, if sent, would include cookies that identify the user.

  • A cookie is accessible in this request because the request is going to a.com only.
  • In this type of request, the origin will be b.com only. If CORS is correctly configured, the ajax request of the attacker's site will be rejected, as, by default, it will only accept requests by the same site or some predefined domains.
  • For non-simple requests, the browser sends the preflight request.

 

In CORS-supported browsers

  • The Origin the header cannot be set by the user
  • It's the browser that rejects the response of non-matching origin
  • Browser send preflight request, not the application