Red Team · Medium
Cross-Site Request Forgery

Understand how CSRF tricks authenticated users into performing unintended actions, how to craft a proof-of-concept, and the protections that stop it.

Medium Red Team Path ⏱ 20 min read
Learning Progress
0%

CSRF Explained

Cross-Site Request Forgery (CSRF) is an attack that tricks an authenticated user's browser into making an unintended request to a web application. Because the browser automatically attaches cookies to every request, the application sees the request as legitimate — even though the user didn't initiate it.

The impact depends entirely on what the forged request does. Classic examples include changing a user's email address, transferring funds, adding an admin account, or deleting data — all without the victim's knowledge. CSRF is particularly insidious because the victim sees nothing unusual — there's no error, no warning, and often no visible activity at all. The attack happens silently in the background while the user is doing something completely unrelated on a different tab.

⚠️OWASP A01:2021: CSRF falls under Broken Access Control. A successful CSRF attack on an admin account can result in full application compromise.

Why Browsers Make CSRF Possible — The Cookie Problem

To understand CSRF, you need to understand one fundamental behaviour of web browsers: they automatically attach cookies to every HTTP request sent to a domain, regardless of where that request originated. This was a deliberate design decision made in the early web to support persistent login sessions — without it, you'd have to log in to every page you visited. But this same behaviour is what CSRF exploits.

The valet key analogy: Imagine you hand your car key to a valet at a restaurant. The valet has temporary authority to use your car. Now imagine someone else — a stranger — walks up to the valet stand and says "I need the car from table 12 moved to the exit." If the valet doesn't verify who's asking, they'll comply, because the key proves the authority, not the person making the request. CSRF is exactly this: a third party issues a request using the authority (the session cookie) that belongs to someone else, and the server complies because the credentials check out.

The reason CSRF works — and not every cross-site request is an attack — is the combination of three conditions that must all be true simultaneously:

Remove any one of these three conditions and the attack fails. CSRF defences — tokens, SameSite cookies, origin header checks — each work by breaking one of these conditions.

📖Historical context: CSRF has been known since at least 2001, when Peter Watkins documented it. Despite being one of the oldest known web vulnerabilities, it continued to appear in major platforms for decades. Netflix (2006), ING Direct bank, and YouTube were all publicly reported as CSRF-vulnerable in the 2000s. The vulnerability is so persistent because it doesn't require a code flaw per se — it requires the presence of protective measures that aren't always added by default.

Same-Origin Policy — Why It Doesn't Stop CSRF

A common misconception is that the browser's Same-Origin Policy (SOP) prevents CSRF. The SOP prevents JavaScript on one origin from reading responses from another origin — but it does not prevent the browser from sending requests to another origin, and it does not prevent cookies from being attached to those requests. The attack doesn't need to read the response; it just needs the server to process the request. That's the gap CSRF exploits.

Think of it this way: the Same-Origin Policy is a one-way mirror. Malicious JavaScript on evil.com can send a form submission to bank.com with the victim's cookies — it just can't see the response. For state-changing operations like transfers, password changes, or account deletions, that's enough. The attacker doesn't need to see the confirmation page; they just need the action to execute.

The CSRF Attack Flow

Three conditions must be true for a CSRF attack to work: the victim must be authenticated, the application must use predictable request parameters (no random token), and the browser must send credentials automatically with cross-site requests.

Attack Flow
1. Victim logs into bank.com → session cookie stored in browser
2. Victim visits attacker-controlled page (evil.com)
3. Attacker page silently submits:
   POST https://bank.com/transfer
   amount=5000&to_account=99999
4. Browser automatically attaches victim's bank.com session cookie
5. Bank.com receives a valid, authenticated POST request
6. Bank processes the transfer — it looks legitimate
7. Victim has no idea anything happened

The attacker never needs to be on the same network as the victim. They don't need the victim's password or session token. They don't interact with the victim directly at all. The entire attack is delivered by getting the victim to load a page — which could be a link in an email, a comment on a forum, an ad, or an embedded image. The victim's own authenticated browser does all the work.

🚨The quiet attack: Unlike phishing which asks the victim to type something, or malware which requires installation, CSRF requires only that the victim loads a page while logged in. A well-crafted CSRF payload executes in a fraction of a second, leaves no visible trace, and completes before the victim has time to notice anything.

CSRF in Practice

Example 01Basic HTML Form CSRF — Silent Auto-Submit

The most fundamental CSRF payload is an HTML form that submits itself automatically using JavaScript the moment the page loads. The form targets the vulnerable endpoint, contains all required parameters as hidden fields, and fires before the user sees anything. The page can display completely normal content — a fake news article, an image gallery, anything — while the form submits invisibly in the background.

<!-- Attacker's page at evil.com -->
<form action="https://target.com/change-email" method="POST" id="csrf">
  <input type="hidden" name="email" value="[email protected]">
  <input type="hidden" name="confirm_email" value="[email protected]">
</form>
<script>document.getElementById('csrf').submit();</script>
<!-- Victim visits page → email silently changed to attacker's address -->
<!-- Attacker now triggers "forgot password" → gets reset link → full account takeover -->

The consequence chain here is important: changing an email address alone might seem low-severity. But combined with a password reset flow, it becomes a full account takeover. A single CSRF on an email-change endpoint can be the first step in a two-stage account compromise.

Example 02GET-Based CSRF — The Image Tag Attack

If a state-changing operation is performed via GET request — which is a design error, as GET should be idempotent and read-only — the attack surface is even larger. Browsers automatically make GET requests to load images, and those requests carry cookies. An attacker can embed a zero-pixel image whose URL is actually a destructive endpoint.

Why GET is dangerous for state changes: The HTTP specification defines GET as a "safe" method — one that should never modify server state. Many developers treat this as an optional guideline rather than a security requirement. The browser treats GET requests as inherently safe to make automatically, which is precisely why using GET for state-changing actions creates CSRF vulnerability without any JavaScript at all.

<!-- Can be embedded in an email, a forum post, any HTML content -->
<img src="https://target.com/delete-account?confirm=yes" width="0" height="0">
<!-- Browser requests this "image" with victim's session cookie attached -->
<!-- Account deleted -- no JavaScript, no user interaction beyond loading the page -->

<!-- Another variant: fund transfer -->
<img src="https://bank.com/transfer?to=99999&amount=500" width="0" height="0">
<!-- This could appear in any email client that renders HTML -->
Example 03Identifying CSRF Vulnerability in Burp

The identification process in a web application assessment is systematic: intercept every state-changing request in Burp, check for CSRF tokens, and where absent, verify exploitability by replaying from a different session. A request with no CSRF token is a candidate; a request that succeeds when replayed from a different browser with a different session cookie confirms exploitability.

# Step 1: In Burp, intercept a state-changing POST
POST /account/update HTTP/1.1
Host: target.com
Cookie: session=abc123

[email protected]&phone=555-1234
# No csrf_token parameter → candidate for CSRF

# Step 2: Verify it requires authentication (session check)
# Remove Cookie header → should fail → confirms session is required

# Step 3: Replay from different session (different browser/incognito)
# Use a different session cookie → if the update succeeds → CSRF confirmed
# The request doesn't require anything unique to the original user

# Step 4: Build PoC HTML page and test against test account
Example 04CSRF Token Bypass Attempts

The presence of a CSRF token field in a form does not guarantee protection. Developers frequently implement token validation incorrectly in ways that leave the application still exploitable. Each bypass below represents a real implementation error found in production applications.

# Bypass 1: Remove the token field entirely
[email protected]  (no csrf_token field at all)
# Some servers only check the token if it's present — absence passes

# Bypass 2: Submit an empty token
[email protected]&csrf_token=
# Some servers check non-null but not non-empty

# Bypass 3: Use another user's valid token (not session-tied)
[email protected]&csrf_token=other_users_known_token
# Token valid globally, not per-user → shared token pool vulnerability

# Bypass 4: Change POST to GET (method override)
GET /account/[email protected] HTTP/1.1
# Some frameworks process GET and POST equally for state changes

CSRF Impact Across Application Types

CSRF severity varies dramatically based on what state-changing operations the application exposes. The following scenarios illustrate why context matters when assessing CSRF findings.

Scenario ABanking Application — Unauthorised Fund Transfer

A banking application allows authenticated users to transfer funds via a POST request with recipient account and amount parameters. No CSRF token is present. An attacker crafts a malicious page and distributes it via a phishing email disguised as a bank notification: "Your statement is ready — click here to view." The link leads to a page that displays a fake PDF while silently submitting a fund transfer in the background.

The victim clicks the link while logged into their online banking (which they left open in another tab). The transfer executes immediately. The victim's session cookie — still valid — authenticates the request. The bank's server processes it as a legitimate transfer. No password was phished, no malware was installed. The entire attack was a single HTML page.

🚨Severity: This is a critical CSRF finding. CVSS v3.1 scores this approximately 8.0 (High) when financial loss is the direct impact — affecting Integrity (High) and potentially Availability via account drainage.
Scenario BEnterprise SaaS — Admin Account Creation

A SaaS platform's admin panel allows administrators to create new user accounts via a POST to /admin/users/create. The endpoint lacks a CSRF token. An attacker sends a spear-phishing email to a known admin, containing an embedded image whose loading triggers a GET request that creates a new admin-level backdoor account with attacker-controlled credentials.

The admin opens the email on a device where they're logged into the admin panel. The image loads. The account is created. The attacker now has persistent admin access to the platform without ever having logged in, cracked a password, or triggered any alerts. The compromised admin account has no unusual login activity — the legitimate admin is still using it normally.

This scenario illustrates a critical point: CSRF on privileged endpoints is a persistence mechanism, not just a nuisance. The attacker doesn't need to maintain the CSRF attack after initial compromise — one successful trigger creates a permanent foothold.

Scenario CSocial Platform — Stored CSRF via User Content

A social platform allows users to post content that renders HTML. The platform's profile settings endpoint is vulnerable to CSRF. An attacker posts a message containing a hidden zero-pixel form that auto-submits, targeting the settings endpoint to change the viewer's privacy settings to "public" and add the attacker as a trusted contact.

Every authenticated user who views the attacker's post silently has their settings changed. This is a stored CSRF — the payload persists in the database and fires for every visitor. The impact scales with the popularity of the post. A high-traffic post could affect thousands of users' accounts. Combined with a stored XSS vulnerability, this becomes a self-propagating worm.

This pattern — stored CSRF embedded in user-generated content — was the mechanism behind the 2005 MySpace Samy worm, which spread to over one million profiles in 20 hours using a combination of stored XSS and CSRF to add the attacker as a friend on every profile it touched.

What CSRF Exposure Means for an Organisation

What You Need to Know

🍪
SameSite Cookie Attribute
Modern browsers default new cookies to SameSite=Lax, blocking cross-site POST requests from carrying cookies. The primary modern browser-level defence — but not a complete solution alone.
🎫
CSRF Tokens
Unpredictable, session-tied values embedded in forms. The server validates the token on every state-changing request — an attacker can't forge it without reading the victim's page (blocked by SOP).
🔍
Same-Origin Policy
Browsers prevent JavaScript from reading cross-origin responses — but still send cookies with cross-origin requests. CSRF exploits the sending, not the reading. SOP does not prevent CSRF.
📋
CVSS Scoring
CSRF on high-privilege functions (admin, money transfer) scores 8.0+ CVSS. CSRF on a comment form may score 4.3. Endpoint context determines severity — always score per-endpoint, not per-finding-class.
🔗
Three Conditions
CSRF requires: (1) authenticated victim, (2) predictable request parameters, (3) automatic cookie attachment. Remove any one condition and the attack fails. Defences target each condition.
📬
Origin Header Validation
Servers can check the Origin or Referer header to verify requests come from expected pages. A complementary defence — Origin headers can't be forged by JavaScript but can be absent.
Ready to put it into practice?
Proceed to the Lab

You've covered the theory. Now apply it hands-on in the simulated environment.

Start Lab — CSRF
← Return to all labs