CORS Implementation & Various Headers, CORS series (Part 2)

9 hours ago 6
BOOK THIS SPACE FOR AD
ARTICLE AD

Vipul Jain

It’s an HTTP response header which is sent by the server to tell the browser whether it allows a specific origin to allow access its resources or not.

The purpose is to control cross-origin requests and securely allow only those which the server permits.

Let us assume a request is made from one origin to another (cross-origin):
Consider that your browser is on https://example.com.

A JavaScript script on example.com tries to fetch a resource from https://api.anotherwebsite.com/data.The browser sends a request to the target server (https://api.anotherwebsite.com):This includes an Origin header, which specifies the origin of the request (e.g., https://example.com).GET /data HTTP/1.1
Host: api.anotherwebsite.com
Origin: https://example.com

The server responds with an Access-Control-Allow-Origin header:

If the server allows access to the origin (https://example.com), it includes the matching Access-Control-Allow-Origin: https://example.com header in its response.If the origin isn’t allowed, the browser blocks the response due to the Same-Origin Policy (SOP).HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: https://example.com

Browser’s action:

The browser compares the origin of the request (https://example.com) with the value of Access-Control-Allow-Origin in the server's response.If they match, the browser allows the resource to be used by the requesting page.If they don’t match (or the header is absent), the browser blocks the response for security reasons.

1. Wildcard (*)

The server can use Access-Control-Allow-Origin: * to allow any origin to access the resource.

Access-Control-Allow-Origin: *

This is mainly used for public APIs or resources with no sensitive data.

Limitations of wildcard:

It is allowed only for unauthenticated requests e.g., a public API.BUT If the request includes credentials (e.g., cookies, HTTP authentication, or client-side SSL certificates) then in that case,
if the browser sees credentials: true in the request and Access-Control-Allow-Origin: *, it will block the response because exposing credentials to any origin is a significant security risk.Further wildcards can not be used with some other value for e.g. Access-Control-Allow-Origin: https://*.normal-website.com

2. Null Origin:

A null origin occurs in specific scenarios where the request does not have a valid origin. Consider the example:

Request Originating from file:// URLs:

If we open an HTML file directly from our computer (e.g., file:///C:/index.html), it uses the file:// protocol.Browsers consider file:// URLs as having a null origin because they aren’t related to a specific domain.

The default behavior:
The default behavior of cross-origin resource requests is for requests to be passed without credentials like cookies and the Authorization header.

If the requested server uses Access-Control-Allow-Credentials header then the requesting site can send the request along with the credentials also. Now it is up-to the server to accept those credentials or not and if accepted the requesting site can access the response in that case.

Consider this scenario:

You have an active session on the main website which has the domain, https://main-website.com.

This means that the browser has stored a cookie for this session e.g.
JSESSIONID=<your_session_cookie>.

Now you visit another website which has the domain https://malicious-website.com. Mistakenly you click a link on this website which sends a request to the main website (which has your session running) with java-script as:

fetch("https://main-website.com/secure-data", {
credentials: "include",
});

This “include credentials” directive tells the browser to include the stored credentials (in this case the session cookie) while sending the cross-origin request.

The browser eventually sends the following request:

GET /secure-data HTTP/1.1
Host: main-website.com
Origin: https://malicious-website.com
Cookie: JSESSIONID=<your_session_cookie>

Now comes the role of the server and the CORS headers.

If the server of the main website responds as:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true

In this case the browser will check two things:
1) Whether the origin from where the request is initiated, is it allowed or not as per the Access-Control-Allow-Origin header value this means if this header contains same value as the Origin header or not.
2) The browser checks whether inclusion of credentials is allowed or not in the cross origin request.

If the value for both the headers is same in the first check and the inclusion of credentials in the cross-origin request is allowed then the malicious website will be able to access the response to its request using the credentials of the user.

IMPACT:

This will allow the malicious website to read sensitive data from the main website’s response. Consider if this main website is a banking site then in that case the malicious website has access to the user’s critical financial details.

BUT if the server responds as:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: false

Since the value of Access-Control-Allow-Credentials header is false thus even though that malicious origin is allowed, the credentials are not included and in this case the browser blocks access to the response even though the request itself was sent. Even if one of the conditions is not met, the browser will block access to the response.

In cases when the cross-origin request contains some:

Non-standard HTTP methods e.g., PUT, DELETE, PATCH.Custom request headers like Special-Request-Header.The request uses Content-Type values other than the standard ones e.g. application/x-www-form-urlencoded, multipart/form-data, or text/plain.

This indicates some sort of risky request, hence to handle this even before the actual request is sent, the browser sends a request with OPTIONS header to the target server. The aim is to ask the server for permission about various methods and headers that are being requested in the cross-origin request.

Consider this example:

Suppose the cross-origin request is as shown:

OPTIONS /data HTTP/1.1
Host: example.com
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header
"OPTIONS” indicates that this is a pre-flight request and not the actual data request."Origin” tells about the domain making the request."Access-Control-Request-Method” tells the server which HTTP method is being asked for in the request e.g. in this case is PUT."Access-Control-Request-Headers" lists any custom headers that are being requested e.g. in this case is Special-Request-Header.

Now consider the response of the server as:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240

204 No Content means that is a pre-flight request and not the actual data request.

The response contains all the headers which gives information about which all origins, methods, headers are allowed and whether inclusion of credentials in the request is allowed or not.

Access-Control-Max-Age header explains about how long this response can be cached, in this case 240 seconds, this means subsequent requests within 240 seconds won’t trigger a new pre-flight check.

After this the browser either proceeds with the request if the server allows all the requested methods, headers and the origin but if any of the conditions fail then the request is blocked.

Therefore pre-flight checks helps the browser handle potentially risky requests or those with non standard methods and headers.

In the next blog we will discuss about exploiting CORS vulnerability.

Read Entire Article