GIVEAWAY
Win the ultimate AI security check with a free pentest giveaway!
GIVEAWAY
Win the ultimate AI security check with a free pentest giveaway!

Browser Security: Same Origin Policy vs CORS, Misconfigurations

This blog guides how to understand and evaluate CORS (Cross-Origin Resource Sharing) misconfigurations. As pentesters, accurately assessing the risks associated with CORS settings is crucial during web application tests. Covering the fundamentals of the Same Origin Policy, detailing CORS exceptions, and providing a comprehensive risk assessment table, this blog serves as a practical reference to improve your security evaluations.

Basics of Web Storage and Cookies

Before diving directly into the topic of Same Origin Policy, it may be helpful to briefly understand the usage of web storage and cookies.

Web storage, which came with HTML5, is a database technology that allows data to be stored on the browser side and accessed via JavaScript. There are two different storage areas: Local Storage and Session Storage on the browser.

Both are used for the same purpose, which is to store data and use this data on the browser side with JavaScript. Key differences include:

Local Storage

Session Storage

Persists in the respective browser until it is manually deleted

Remains active only as long as the relevant tab is open and the session is alive.

Accessed from all tabs open in the browser (only the related domain can access its data)

Only accessed by the relevant tab

Cookies, on the other hand, existed even before HTML5, during the HTML4 era. They are an older form of storage compared to web storage and have a much smaller storage capacity. Cookies are set based on the values received from server responses and are sent to the server with every request made to the relevant domain automatically.

website-cookies-explainer-graphic

With a different perspective:

 

Cookies

Local Storage

Session Storage

Capacity

4KB

10MB

5MB

Browser

HTML4/HTML5

HTML5

HTML5

Accessible Places

All windows

All windows

Only related tab

Life time

Manual set

Always

Deleted when tab closed

Storage

Browser and server

Browser

Browser

Sent automatically with request?

Yes

No

No

The key point to remember is when a request is made from the browser to any website, if the cookie information is related to that website in the browser, then the request will include this cookie value. Therefore, all requests made to a website where you have an active session are sent in an authenticated state. Keeping this in mind will make the Same Origin Policy more understandable.

Same Origin Policy 

Web applications use JavaScript to make web pages interactive and also to perform tasks like sending requests in the background, or updating the interface based on the responses. Even if we don't see the browser refreshing, these applications can make changes to the HTML visuals presented to us while communicating with the server and making web requests in the background. Web requests made with JavaScript must adhere to the Same Origin Policy (SOP) rules.

The Same Origin Policy is a security mechanism that prevents a website’s JavaScript from making requests to a different address (origin) than the site's address .

For example, when we open the Google.com web application, the JavaScript applications running in the background cannot send requests to websites other than Google.com (except with certain conditions). JavaScript code running in your browser cannot send requests to another site from your browser. If we try this, we will encounter an error such as 'cross origin request blocked.'

Imagine having Facebook and an online banking account open in different tabs on the same browser. The Same Origin Policy ensures that the Facebook application cannot access the DOM structure of the banking application open in the adjacent tab, nor can it attempt to send requests to the banking application's domain using JavaScript. If it could, we know these requests would include the browser's cookie information, allowing actions to be taken on behalf of users as authenticated. When a website’s JavaScript code tries to interact with another website, the browser does a security check. It compares the origin (web address) of the first website with the origin of the second website to see if they match. This is part of a security rule called The Same Origin Policy (SOP).

Origin: It is composed of the scheme (http/https), the domain (google.com, youtube.com, etc.), and the port number (443, 80, 8080).

same-orgin-policy-cybersecurity-explainer-graphic

Some examples can be examined below for better understanding.

Origins

Same Origin?

Explanation

http://google.com
https://google.com

The browser identifies these as different origins because the schemes of the two addresses are different.

https://youtube.com
https://youtube.com/test

The browser identifies these as the same origin because the directory information is not significant for the origin.

https://reddit.com
https://reddit.com:8443

The browser identifies these as different origins because the port numbers need to be the same to be considered the same origin.

While we are at google.com, let's try to send a request to youtube.com with javascript HMLHttpRequest.

browser-error-from-same-origin-policy-rules

The browser determines that we cannot perform this operation based on the Same Origin Policy rules.

Therefore, the SOP isolates one website from others, blocking requests intended to be sent to different sites.

CORS Exception

We know that modern web applications provide services by exchanging data via JavaScript (XHR) requests from multiple servers, domains, APIs or different web applications. However, as mentioned above, the Same Origin Policy defines a rule that prevents this.

If the developed applications need to exchange information by making requests to different domains and origins with JavaScript, CORS (Cross-Origin Resource Sharing) helps to relax the SOP rule. 

As the name implies, CORS allows for resource sharing between origins. To understand this mechanism, we can take a closer look at how the SOP rule is applied.

To enforce the SOP rule, browsers first send a preflight request using the OPTIONS method to the web application being requested via JavaScript. (The preflight request is sent under certain conditions, such as when specific HTTP methods and headers are set. Even if a preflight request is not sent, the restrictions still apply.) The purpose of this request is to ask the target server whether the intended request is allowed. If the necessary CORS headers are defined on the target server, it will permit the request. However, if these headers are not defined, the server will respond with a rejection to the OPTIONS request, and the browser will not send the original request that JavaScript was trying to make.

CORS-javascript-example

To provide a real-world example, if we look at the console logs in Firefox DevTools for an XMLHttpRequest made from google.com to stackoverflow.com, we can see the following messages. The messages indicate that stackoverflow.com has rejected the request from google.com due to the CORS Policy, stating that the preflight request did not pass access control.

CORS-preflight-request-browser-example

When we examine the relevant OPTIONS request, we can see headers such as 'Access-Control-Request-Method' and 'Origin' among the headers automatically added by the browser. The server receiving the request will perform CORS checks based on these headers added by the browser.

browser-access-control-request-PUT-example

Cross-Origin Resource Sharing

Cross-Origin Resource Sharing (CORS) is a standard that allows servers to determine who can reach them via JavaScript requests through the browser. Therefore, CORS serves as a solution to the restrictions imposed by the Same Origin Policy, providing a workaround as needed.

In other words, CORS headers are used to specify how our web application wants to respond to JavaScript requests (XHR) coming from other web applications. Below, we examine these header details defined on the server side and their possible values.

Access-Control-Allow-Origin

This header specifies which origins are allowed to send requests. 

Access-Control-Allow-Origin: youtube.com ➡️ Requests from youtube.com will pass the CORS check and be transmitted.
Access-Control-Allow-Origin: * ➡️ Allows requests from all origins.

Access-Control-Allow-Methods

This header specifies which methods are allowed. Access-Control-Allow-Methods: GET, HEAD, PUT, PATCH, POST, DELETE

Access-Control-Allow-Headers

This header specifies which headers are allowed in the incoming request. Access-Control-Allow-Headers: Content-Type, Accept

Access-Control-Max-Age

This header specifies how long the response to the preflight request can be cached, indicating how long subsequent requests can be made without another preflight. ;Access-Control-Max-Age: 1728000

Access-Control-Allow-Credentials

This header determines whether incoming requests can be accepted with cookie information, essentially whether the request can be considered authenticated. As mentioned earlier, cookie information is automatically sent with the request. This header will indicate whether the receiving server will accept these cookie details.

Access-Control-Allow-Credentials: true
Access-Control-Allow-Credentials: false

After the response headers are set on the server side as mentioned above, the incoming request must pass through all header checks for CORS to accept it. This means that even if a web request's origin is correct, the CORS mechanism will reject it if it contains an unsupported header..

In line with this information, I'd like to share a table I came across while researching, with some modifications, to better understand potential scenarios, their risks, and impacts. This could be useful in accurately evaluating CORS findings in automated security scanning tools during security research.

Misconfiguration/Risk Table

Server Header

Access Control Allow (Example Value)

Access Control Allow Credentials (Example Value)

Risk

Why? (Explanation)

Allow All Origins (*) (wildcard)

True

High

Allowing all origins and setting the credentials value to true is a dangerous scenario. This configuration effectively disables the Same Origin Policy. Consequently, a malicious site in another tab could send requests to your misconfigured server, potentially accessing sensitive data from an authenticated session.

False

Info

In this case, the risk will be quite low because the browser will not be able to send the response of authenticated requests. But in the future, it might use credentials “True”. So flag this as informational.

Allow Subdomains *.website.com

True

Medium

In this scenario, if there is an XSS vulnerability in one of the subdomains, the malicious javascript code could exploit this vulnerability. Normally, if we have resolved this vulnerability and have javascript code only for our main site, the impact of this situation would be limited to the domain of the main site.

False

Info

In this case, even if there is an XSS vulnerability in the subdomains, the effect will be low because authenticated requests cannot be sent.

Null allowed null

True

Medium

Sometimes, due to leftover settings from the development period, the server may allow the origin value to be null. However, by making a request through the browser, attackers can obtain our information and send authenticated requests by including the origin information as null. If the credentials value is true, this can be exploited for information leaks

False

Info

As in the above examples, in this case, it is not possible to share data, so the risk will be low.

Resources

https://www.packetlabs.net/cross-origin-resource-sharing-cors

https://www.youtube.com/watch?v=zul8TtVS-64

https://we45.com/blog/3-ways-to-exploit-cors-misconfiguration

https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties

https://www.youtube.com/watch?v=j5Ew2WlHNi8

State of Pentesting Blog CTA 2024

Back to Blog
About Ahmet Can Karaağaçlı
Ahmet Can, a seasoned Computer Engineer, boasts over 4 years of diverse experience in cybersecurity as a Pentester, IT Auditor, Cybersecurity Consultant, and Bug Bounty Validator. His proficiency spans internal and external penetration testing, Web/API and mobile application security assessments, threat modelling social engineering, source code reviews, and security process evaluations within frameworks like COBIT and NIST. Beyond his professional roles, cybersecurity isn't just a career for Ahmet Can; it's his passion and hobby. His commitment to staying current is evident through active bug bounty participation, showcasing his ongoing dedication to mastering emerging threats. More By Ahmet Can Karaağaçlı
A Pentester’s Guide to Prototype Pollution Attacks
Core Pentester Harsh Bothra guides us through prototype pollution attacks in his latest blog. This covers a security vulnerability that allows attackers to exploit JavaScript runtimes.
Blog
Jan 2, 2023
OAuth Vulnerabilites Pt. 1
Welcome to part one of OAuth Vulnerabilities. Core Pentester Shubham Chaskar overviews Oauth, commonly used grant types, entities, misconfiguration, and more.
Blog
Jan 23, 2023