Advanced

What Is CSRF?

15 min β€’ 4 sections
1

Concept

Same-Origin Policy

Before understanding CSRF, it is important to understand what the browser's Same-Origin Policy (SOP) actually doesβ€”and, just as importantly, what it does not do.

An origin is defined by the combination of: Scheme + Host + Port

Scheme: The protocol used, such as http or https.

Host: The domain name or IP address, such as example.com.

Port: The network port, such as 80 or 443.

For example:

https://bank.com

and:

https://evil.com

are different origins.

The Same-Origin Policy generally prevents JavaScript running on one origin from freely reading sensitive data from another origin.

A script running on evil.com, for example, cannot normally make a request to bank.com and then read the response as though it belonged to evil.com.

JavaScript on:

evil.com
        ↓
Attempts to access: bank.com
        ↓
Request may be sent, depending on the mechanism
        ↓
But JavaScript is normally prevented from freely reading the response
without explicit cross-origin permission

This is the part of browser security that makes CSRF easy to misunderstand.

The Same-Origin Policy primarily protects the ability of one origin to access data belonging to another origin.

It does not mean that one website is incapable of causing a browser to send a request to another website.

For example, a page on evil.com can contain a form that submits to bank.com:

<form action="https://bank.com/change-email" method="POST">
    <input type="hidden" name="email" value="attacker@example.com">
    <button type="submit">Submit</button>
</form>

If the victim submits that form or if the attacker's page causes the form to be submitted automatically the browser can send the request to bank.com.

Victim visits: evil.com
        ↓
Attacker-controlled page creates a request
        ↓
Browser sends request to: bank.com
        ↓
The attacker cannot necessarily read bank.com's response
        ↓
But the request may still cause bank.com to perform the action

This is the gap CSRF exploits.

The attacker does not need to read the target application's response.

They only need the victim's browser to send a request that the target application interprets as legitimate.

If the victim is already authenticated to bank.com, the browser may automatically include the credentials associated with that site such as a session cookie subject to the cookie's scope and SameSite rules.

Victim is logged in to: bank.com
        ↓
Browser holds valid bank.com session cookie
        ↓
Victim visits: evil.com
        ↓
evil.com causes browser to send a request to bank.com
        ↓
Browser may attach the victim's bank.com credentials automatically
        ↓
bank.com receives: Authenticated request
        ↓
If no CSRF protection exists, the application may perform
an attacker-chosen action

The attacker may never see the response.

They may not know whether the request succeeded.

If the action is predictable changing an email address, submitting a form, enabling a setting, or performing another state-changing operation the damage can occur simply because the server trusted the browser's automatically attached credentials as proof that the request was intentionally initiated by the user.

That is the central idea behind CSRF:

Authentication answers: "Whose session is this?"

CSRF protection answers: "Did this authenticated user intentionally cause this request?"

The Same-Origin Policy helps prevent evil.com from reading private data from bank.com.

But CSRF operates in a different space:

Same-Origin Policy

Can the attacker read the response?
        ↓
Usually: No

CSRF

Can the attacker cause the victim's browser to send a state-changing request?
        ↓
Potentially: Yes

CSRF exists in that gap.

The attacker does not need to steal the victim's session or read the target application's response. They only need to cause the victim's already-authenticated browser to send a request that the target site mistakes for an intentional action.

2

Concept

Browser Credential Behavior

The mechanism CSRF exploits is the browser's ability to automatically attach credentials to a request based on where that request is going, rather than on whether the user intentionally initiated it.

When a browser sends a request to bank.com, it may automatically include cookies that are valid for that request including the user's session cookie provided the request matches the cookie's domain, path, Secure, and SameSite rules.

The browser does not ask: "Did the user intend to perform this action?"

Instead, it evaluates rules such as:

Request destination: bank.com
        ↓
Does this cookie belong to that destination?
        ↓
Do the Domain and Path rules match?
        ↓
Is HTTPS required?
        ↓
Do the SameSite rules allow the cookie on this request?
        ↓
If yes: Cookie may be attached automatically

This is the property CSRF exploits.

The user's authentication credential is associated with the destination, not with the user's current intent. An attacker cannot directly read the victim's session cookie, but may be able to cause the victim's browser to send a request to the site that owns it.

Victim is authenticated to: bank.com
        ↓
Browser holds: session=abc123...
        ↓
Victim visits: evil.com
        ↓
evil.com causes a request to: bank.com
        ↓
Browser evaluates whether the bank.com cookie should be attached
        ↓
If the applicable cookie rules allow it:

session=abc123... is sent automatically
        ↓
bank.com receives an authenticated request

This behavior is often described as ambient authority.

The credential is already present in the browser's credential store and becomes available automatically when the browser makes a request to the appropriate destination. The attacker does not need to know the credential's value or attach it manually.

That is the fundamental difference between stealing a session and exploiting CSRF.

That is the fundamental difference between stealing a session and exploiting CSRF.

Session hijacking:

Attacker obtains the credential
        ↓
Attacker sends it themselves


CSRF:

Attacker never obtains the credential
        ↓
Victim's browser sends it automatically

This is why the defenses covered later in CSRF prevention section place significant emphasis on cookie behavior, particularly SameSite.

SameSite changes the circumstances under which the browser will automatically include a cookie on a cross-site request, reducing the browser's ambient attachment of session credentials.

However, it is important to understand that SameSite is specifically a defense against cross-site cookie sending. It is not a general-purpose mechanism for proving user intent, which is why applications may still use explicit CSRF tokens or origin-based validation as additional protections.

Cookie Authentication vs Explicit Bearer Token:

This also explains why authentication mechanisms that require a credential to be explicitly added by application code are generally more resistant to classical CSRF.

Consider a bearer token stored only in application memory and sent in an Authorization header:

Application JavaScript
        ↓
Reads token from its own trusted application state
        ↓
Explicitly adds: Authorization: Bearer <token>
        ↓
Request sent to API

A malicious script running on evil.com does not automatically receive that token merely because the victim is authenticated to another site.

Nor can a normal cross-origin HTML form cause the browser to attach an arbitrary Authorization header containing a secret the attacker does not know.

evil.com
        ↓
Attacker wants to send: Authorization: Bearer <victim's token>
        ↓
But: Attacker does not know the token
        ↓
Browser does not automatically attach it based solely on destination
        ↓
Classical CSRF attack fails

This makes explicitly attached bearer-token authentication more naturally resistant to CSRF than cookie-based authentication.

The important distinction is not simply that one mechanism uses a "token" and the other uses a "cookie." A session cookie is also effectively a bearer credential.

The difference is how the credential reaches the request:

Cookie-based authentication

Credential may be attached automatically by the browser
        ↓
Creates CSRF risk


Header-based bearer authentication

Application must explicitly attach the credential
        ↓
Cross-site attacker normally cannot cause the browser to supply a secret
they do not possess

This protection depends on the token remaining inaccessible to the attacker's origin. If an attacker can steal the bearer token through XSS, malicious browser extensions, compromised client code, or another token-exposure vulnerability, they may simply use it directly.

So header-based bearer authentication does not eliminate authentication risk it primarily removes the specific ambient credential behavior that makes classical CSRF possible.

The central principle is:

CSRF exists because the browser may automatically attach credentials to a request based on its destination, even when the request itself was initiated by an attacker-controlled page.

With cookie-based sessions, defenses must account for that automatic behavior.

With explicitly attached credentials, the attacker faces an additional problem: they must actually possess the secret before they can cause it to be sent.

3

Concept

The Complete CSRF Attack Chain

Putting the Same-Origin Policy and browser credential behavior together produces the full CSRF attack chain.

A typical attack unfolds like this:

  1. The victim is authenticated to the target site and holds a valid session cookie in their browser.

  2. Without logging out, the victim visits a page the attacker controls. This might be a malicious website, or a legitimate site containing attacker-controlled content such as a forum post, comment, or injected advertisement.

  3. The attacker's page causes the victim's browser to send a request to the target application.

  4. If the applicable cookie rules allow it, the browser automatically attaches the victim's authentication cookie to that request.

  5. The target server receives what appears to be a legitimate authenticated request. Unless it performs an additional check to verify that the request was intentionally initiated from the legitimate application, it may perform the attacker-chosen action.

Victim is logged in to: bank.example.com
        ↓
Browser holds: session=victim-session
        ↓
Victim visits: evil.example.com
        ↓
Attacker-controlled page causes a request to bank.example.com
        ↓
Browser evaluates cookie rules
        ↓
If the request is permitted to carry the session cookie:
session=victim-session
        ↓
bank.example.com receives: Authenticated request
        ↓
No CSRF validation?
        ↓
Attacker-chosen action performed

The critical point is that the attacker does not need to know or steal session=victim-session.

The attacker chooses the request.

The victim's browser potentially supplies the credential.

A Minimal Example:

A traditional cross-site form submission is one of the clearest examples because browsers have long supported sending forms to other origins.

An attacker-controlled page could contain:

<form action="https://bank.example.com/api/transfer"
      method="POST"
      id="csrf-form">

  <input type="hidden"
         name="toAccount"
         value="attacker-account-001">

  <input type="hidden"
         name="amount"
         value="5000">
</form>

<script>
  document.getElementById('csrf-form').submit();
</script>

The attack works conceptually like this:

Attacker controls: evil.example.com
        ↓
Hidden form targets: bank.example.com/api/transfer
        ↓
Form contains attacker-chosen values: toAccount = attacker-account-001
amount    = 5000
        ↓
JavaScript submits the form automatically
        ↓
Victim's browser sends POST request to the real bank.example.com domain
        ↓
Browser evaluates whether the victim's bank.example.com session cookie may
be included
        ↓
If included, the server receives an authenticated request
        ↓
 Transfer may be performed

action="https://bank.example.com/api/transfer"

The request goes to the real target application.

The attacker is not impersonating bank.example.com, intercepting its traffic, or guessing the victim's credentials. They are simply causing the victim's browser to make a request to that domain.

toAccount and Amount

These values are entirely attacker-controlled.

The browser has no concept of whether the values represent the user's intent. From the browser's perspective, it is simply submitting a form.

Attacker controls:

What request is sent
        +
What parameters it contains

Browser potentially supplies: The victim's existing authentication state

That combination is the essence of CSRF.

Automatic Submission:

The JavaScript call:

document.getElementById('csrf-form').submit();

submits the form as soon as the attacker's page executes the code.

The victim does not need to:

  • Enter their password.

  • Click a confirmation button.

  • Know that the form exists.

  • Reveal their session cookie to the attacker.

Victim visits attacker-controlled page
        ↓
Page loads
        ↓
Hidden form is submitted
        ↓
Authenticated request reaches the target application
        ↓
Potential state change

Why the Server Cannot Rely on Authentication Alone:

From the target server's perspective, both of these requests may contain a valid session credential:

Legitimate request:

User visits bank.example.com
        ↓
User clicks "Transfer"
        ↓
Authenticated POST request
CSRF request:

User visits evil.example.com
        ↓
Attacker causes hidden form submission
        ↓
Authenticated POST request

Authentication alone answers:

"Which account is associated with this request?"

It does not necessarily answer:

"Did the owner of that account intentionally initiate this action from our application?"

Without an additional CSRF defense, those two requests can be difficult or impossible for the application to distinguish reliably.

That additional defense may involve a CSRF token, SameSite cookie restrictions, origin or Referer validation, or a combination of these controls.

The central attack model is therefore:

The attacker controls the request. The browser may supply the credentials. The server mistakes authentication for proof of intent.

4

Concept

State-Changing Requests

CSRF is primarily a threat to requests that change server-side state.

Typical targets include:

  • Transferring funds.

  • Changing a password or email address.

  • Deleting a resource.

  • Modifying an account or security setting.

  • Creating a new record or performing another action on the user's behalf.

A purely read-only request is generally a much weaker target for a classical CSRF attack.

The reason is structural: even if an attacker can cause the victim's browser to send a cross-site request, the Same-Origin Policy normally prevents the attacker's page from simply reading the target application's response.

Attacker causes request
        ↓
Target application returns data
        ↓
Same-Origin Policy
        ↓
Attacker's page normally cannot read the response
        ↓
Little direct value from blindly triggering a read

By contrast, a state-changing request can cause harm even when the attacker never sees the response.

Attacker chooses:

POST /change-email
email=attacker@example.com
        ↓
Victim's browser sends request
        ↓
Target application performs action
        ↓
State has changed
        ↓
Attack succeeds even if the response remains unreadable

The attack is therefore fundamentally blind request forgery.

The attacker controls:

βœ“ Which endpoint is targeted
βœ“ Which method is used
βœ“ Which parameters are supplied
βœ“ Which state-changing action the browser attempts to trigger

But, under the normal protections of the Same-Origin Policy, they do not automatically gain access to:

βœ— The target application's response
βœ— The victim's private data
βœ— Arbitrary information returned by the forged request

With IDOR/BOLA, the attacker sends a request using credentials they legitimately possess and deliberately targets an object they should not be allowed to access.

IDOR / BOLA

Attacker controls request
        ↓
Targets another user's object
        ↓
Server fails authorization check
        ↓
Attacker can directly read or modify that object

CSRF is different.

CSRF

Attacker controls request
        ↓
Victim's browser supplies the authentication state
        ↓
Attacker blindly triggers an action as the victim
        ↓
Response normally remains inaccessible to the attacker

The distinction can be summarized simply:

Vulnerability

Whose credentials are used?

What does the attacker gain?

IDOR / BOLA

The attacker's own authenticated session

Direct access to an object they should not be authorized to access

CSRF

The victim's existing authenticated session

The ability to trigger an attacker-chosen action as the victim

Why GET Must Not Change State:

This distinction also explains why GET requests should be reserved for operations that are safe and read-only.

If an application performs a state-changing action through a URL such as:

https://example.com/delete-account?id=123

an attacker may be able to trigger that request using something as simple as:

<img src="https://example.com/delete-account?id=123">

The browser attempts to load the image and, in doing so, sends a GET request to the target.

Victim visits attacker-controlled page
        ↓
Browser encounters: <img src="https://target.example/action">
        ↓
Browser automatically requests URL
        ↓
If applicable credentials are included
        ↓
State-changing action may occur

No form submission is required.

No JavaScript is required.

No user interaction is required.

This is why using GET for state-changing operations is especially dangerous.

It can also cause problems beyond deliberate CSRF attacks. Crawlers, browser prefetching, link-preview systems, security scanners, and other automated clients may follow a GET URL without understanding that it performs an irreversible action.

The general rule is:

GET
        ↓
Read / retrieve information


POST / PUT / PATCH / DELETE
        ↓
Create, modify, or remove state
        ↓
Apply appropriate CSRF protection when cookie-based authentication
creates cross-site request risk

HTTP method choice alone is not a CSRF defense. A POST endpoint can still be forged through a cross-site form submission if the application accepts the request without an additional CSRF check.

But reserving GET for safe, read-only operations removes an entire category of trivially triggerable state changes.

You've completed Cross Site Request Forgery

Great work β€” explore other topics to keep learning.