CacheU
Web Security

Cross-Site Request Forgery (CSRF)

A detailed explanation of CSRF attacks, how they exploit browser cookie behavior, and how modern web applications prevent them using tokens, SameSite cookies, and origin validation.

Cross-Site Request Forgery (CSRF), also called XSRF or Session Riding, is a web security vulnerability where an attacker tricks an authenticated user into performing unintended actions on a web application.

The attack exploits the trust a server has in the user's browser.

Since browsers automatically attach authentication cookies to requests, a malicious website can trigger requests to another site using the victim's active session.

This can cause serious consequences such as:

  • transferring money
  • changing account passwords
  • modifying profile information
  • posting content on behalf of the user

Core Idea Behind CSRF

Web applications often rely on cookies for authentication.

Example login flow:

Diagram
sequenceDiagram User->>Server: Login Request Server-->>Browser: Session Cookie Browser->>Server: Authenticated Requests

Once authenticated, every request automatically includes:

Cookie: session_id=abc123

The server assumes:

If the cookie is valid, the request is legitimate.

CSRF abuses this assumption.


Why CSRF is Dangerous

Browsers automatically include cookies in every request to the same domain, regardless of where the request originated.

Example scenario:

User logs into:

https://bank.com

Browser stores:

session_cookie = logged_in_user

Later the user visits:

https://malicious-site.com

That page secretly triggers:

<img src="https://bank.com/transfer?amount=1000&to=attacker">

The browser automatically sends:

Cookie: session_cookie=logged_in_user

The bank receives:

GET /transfer?amount=1000&to=attacker

And processes it as a valid request from the user.

The user never intended this action.


CSRF vs XSS

These two vulnerabilities are often confused.

FeatureCSRFXSS
Requires injecting code in target site❌ No✅ Yes
Exploits browser trust✅ Yes❌ Not primarily
Uses victim session✅ YesSometimes
GoalPerform actions as victimExecute malicious scripts

CSRF does not require compromising the target site.

It only requires tricking the user into visiting another page.


How CSRF Attacks Work

A typical CSRF attack consists of three steps.


1. Victim Authentication

The victim logs into the target application.

Example:

https://bank.com

Server sets a cookie:

Set-Cookie: session_id=abc123

The user is now authenticated.


2. Malicious Payload Delivery

The attacker lures the victim to interact with malicious content.

Common delivery methods:

  • phishing email
  • malicious website
  • compromised advertisement
  • injected script
  • hidden iframe

Example malicious page:

<form action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="amount" value="5000">
  <input type="hidden" name="to" value="attacker">
</form>
 
<script>
document.forms[0].submit();
</script>

The form automatically submits when the page loads.


3. Forged Request Execution

The victim's browser sends the request.

Diagram
sequenceDiagram Victim Browser->>Bank Server: POST /transfer Note right of Victim Browser: Includes session cookie Bank Server-->>Victim Browser: Transfer successful

The server cannot distinguish between:

User intentionally submitted the request

or

Malicious site triggered it

Real Attack Example

Bank transfer endpoint:

POST https://bank.com/transfer

Parameters:

amount=1000
to=attacker_account

Attacker page:

<img src="https://bank.com/transfer?amount=1000&to=attacker_account">

When the victim loads the page, the request executes automatically.


Why CSRF Works

CSRF works because of three browser behaviors.


1. Cookies are automatically attached

Example request:

POST /transfer
Cookie: session_id=abc123

The browser does this automatically.


2. Servers trust cookies

Many systems rely only on:

session_cookie

to identify users.


3. Servers don't verify request origin

Without verification, the server cannot tell if the request came from:

bank.com

or

malicious-site.com

Prevention Techniques

To prevent CSRF attacks, applications must verify that requests originate from trusted sources.


1. Synchronizer Token Pattern (CSRF Tokens)

This is the most common protection technique.

The server generates a random secret token.

Example:

csrf_token = f91a82db129fa

This token is included in forms.

Example:

<form action="/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="f91a82db129fa">
</form>

When the form is submitted:

POST /transfer
csrf_token=f91a82db129fa

Server validates the token.

If the token is missing or invalid:

Request rejected

Why This Works

Attackers cannot read tokens from another origin due to browser security rules.

So they cannot include the correct token.


Example Implementation (Node.js)

import crypto from "crypto";
 
function generateCSRFToken() {
  return crypto.randomBytes(32).toString("hex");
}

Attach token to session:

req.session.csrfToken = generateCSRFToken();

Validate request:

if (req.body.csrfToken !== req.session.csrfToken) {
  return res.status(403).send("CSRF validation failed");
}

2. SameSite Cookies

Modern browsers support SameSite cookie attributes.

Example:

Set-Cookie: session_id=abc123; SameSite=Strict

Options:

ValueBehavior
StrictCookies never sent in cross-site requests
LaxCookies sent only for top-level navigation
NoneCookies allowed cross-site

Recommended:

SameSite=Lax

or

SameSite=Strict

3. Origin Header Validation

Servers can validate the request origin.

Example request:

Origin: https://app.bank.com

Server logic:

const allowedOrigin = "https://app.bank.com";
 
if (req.headers.origin !== allowedOrigin) {
  return res.status(403).send("Invalid origin");
}

4. Referer Header Validation

Another approach is checking the Referer header.

Example:

Referer: https://bank.com/dashboard

Server ensures requests originate from trusted pages.


5. Custom Request Headers

Require special headers that cannot be sent by simple cross-site requests.

Example:

X-CSRF-Token

JavaScript request:

fetch("/transfer", {
  method: "POST",
  headers: {
    "X-CSRF-Token": csrfToken
  }
});

Malicious HTML forms cannot send such headers.


6. User Interaction Verification

For sensitive actions require:

  • password re-entry
  • OTP verification
  • CAPTCHA

Example actions:

Password changes
Money transfers
Account deletion

Built-in CSRF Protection in Frameworks

Most modern frameworks automatically include CSRF protection.

Examples:

FrameworkProtection
DjangoBuilt-in CSRF middleware
Ruby on RailsAuthenticity token
Spring SecurityCSRF tokens
LaravelCSRF middleware
Expresscsurf package

Example Express middleware:

import csrf from "csurf";
 
const csrfProtection = csrf();
 
app.use(csrfProtection);

Relation Between CSRF and CORS

CSRF and CORS are often confused but solve different problems.

FeatureCSRFCORS
Prevents forged requests✅ Yes❌ No
Controls cross-origin reads❌ No✅ Yes
Browser security mechanismPartiallyYes
Protects server actionsYesNo

Important Insight

CSRF attacks do not need to read responses.

The attacker only needs to send the request.

Even if CORS blocks reading the response:

the action already happened

Example:

Money transferred
Password changed
Account modified

This is why CORS alone cannot stop CSRF.


Attack Flow Diagram

Diagram
flowchart LR A[User Logs into bank.com] --> B[Session Cookie Stored] B --> C[User Visits Malicious Site] C --> D[Hidden Request Sent to bank.com] D --> E[Browser Attaches Session Cookie] E --> F[Bank Processes Request]

Best Practices

Always combine multiple protections.

Recommended setup:

CSRF Tokens
+
SameSite Cookies
+
Origin Validation

For critical operations:

CSRF Token + Re-authentication

Key Takeaways

  • CSRF tricks authenticated users into performing unintended actions
  • It exploits automatic cookie behavior in browsers
  • Attackers only need to send requests, not read responses
  • State-changing requests are the primary targets
  • The best defense is CSRF tokens combined with SameSite cookies

CSRF remains one of the most important vulnerabilities in web security. Proper implementation of anti-CSRF protections ensures that only legitimate user actions are processed by the server.