What Is CSRF? The Attack Using Your Login
Cross-site request forgery (CSRF) is an attack that tricks your browser into sending a real, authenticated request to a site you're logged into—like your admin panel—without you meaning to, so the attacker can change settings, add a user, or redirect a payout using your own login session. No password is stolen. No malware is installed. Your browser just does what it's told, because it still thinks it's you.
Who this is for
This is for the owner or admin of a small business site—WordPress, Shopify, a custom-built dashboard, an indie SaaS—who wants a plain-English answer to "what is cross-site request forgery (CSRF)" and, more importantly, wants to know if their own admin panel is exposed. By the end you'll know exactly how the attack works, what a real one looks like, and the specific fix (a CSRF token) that makes it stop working.
How CSRF actually works, step by step
CSRF abuses one basic fact about browsers: when you're logged into a site, your browser holds a session cookie—a small file that proves "this browser belongs to a logged-in user"—and it attaches that cookie automatically to every request sent to that site, no matter which page told the browser to send it.
Here's the attack in practice:
- You log into your site's admin panel—say,
yourstore.com/admin—and leave the tab open, or close it but your session cookie stays valid. - An attacker sends you a link, or you land on a page they control, containing a hidden form or image tag that points at an action on your own site, like adding a new admin user or changing a payout bank account.
- Your browser loads that hidden request. Because it's a request to
yourstore.com, your browser automatically attaches your valid session cookie—it has no way of knowing the request wasn't something you meant to click. - If your site's admin panel doesn't check where the request actually came from, it processes the request as if you clicked "save" yourself.
A minimal hidden form might look like this, sitting invisibly on an attacker's page:
<form action="https://yourstore.com/admin/add-user" method="POST" id="f">
<input type="hidden" name="username" value="attacker2">
<input type="hidden" name="role" value="admin">
</form>
<script>document.getElementById('f').submit();</script>
You never see a form. You never click "submit." The page just loads, the script fires, and if you were logged in as an admin at that moment, attacker2 is now an admin on your site.
Three things CSRF can actually do to your site
- Change a setting silently — flip your store's shipping rules, disable two-factor authentication, or change the email address that receives password resets (redirecting future account recovery to the attacker).
- Add a new user or admin — the example above; once the attacker has their own admin account, they don't need your credentials at all going forward.
- Redirect a payout or refund destination — on payment or invoicing dashboards, a forged request to "update bank details" or "update payout email" can quietly reroute money on the next payment cycle.
Notice what's missing from all three: your password never left your head, and no malware touched your device. This is why CSRF is easy to underestimate—it doesn't look like a "hack" from the outside. It looks like an admin action, because technically, it was one—your browser just didn't ask you first.
Why this is possible: the same-origin gap
Browsers enforce a rule called the same-origin policy, which normally stops one website from reading data from another. The problem is that same-origin policy doesn't stop a page from sending a request to another site—it only stops it from reading the response. A hidden form submission or an <img> tag pointed at a URL is a one-way request, and cookies get attached regardless of which page triggered it. OWASP's community page on CSRF has a good technical breakdown of this gap: OWASP: Cross-Site Request Forgery.
This is also why CSRF has its own entry in the industry's standard weakness catalog, tracked as CWE-352, maintained by MITRE: CWE-352: Cross-Site Request Forgery.
The actual fix: CSRF tokens (and why they work)
A CSRF token is a random, unpredictable value the server generates and embeds in every form on your own site, tied to your current session. When the form is submitted, the server checks that the token in the request matches the one it issued.
Here's why this stops the attack cold: the attacker's hidden form on their own page has no way to read the token, because reading it would require loading your admin page and inspecting its contents—which same-origin policy does block. They can forge the request, but they can't forge a valid token to go with it.
A typical implementation looks like this in the HTML your server renders:
<form action="/admin/add-user" method="POST">
<input type="hidden" name="csrf_token" value="f3a9c1e7b2d84a...">
<input type="text" name="username">
<button type="submit">Add user</button>
</form>
On the server side, that token is checked against the value stored in the user's session before the action runs. No match, no action—regardless of whether the cookie was valid.
Other real defenses worth knowing about
| Defense | What it does | Where to check it |
|---|---|---|
| CSRF tokens | Per-session random value required on every state-changing form | Custom code, most modern frameworks by default |
SameSite cookie attribute | Tells the browser not to send the cookie on cross-site requests | Set-Cookie: session=...; SameSite=Lax; Secure; HttpOnly in response headers |
| Re-authentication for sensitive actions | Requires re-entering a password before changing payout/bank details or admin roles | Payment dashboards, account settings pages |
Checking the Origin/Referer header | Server rejects requests that didn't originate from your own domain | Server-side middleware or WAF rules |
| No state-changing GET requests | Actions like "delete user" or "add admin" require POST, never a plain link | Code review of admin routes |
None of these alone is bulletproof—SameSite=Lax still allows some top-level navigation requests through, for instance—which is why a real audit checks for CSRF tokens and cookie attributes and how sensitive actions are gated, rather than assuming one setting covers everything. You can check your current cookie and header configuration for free with our security headers scanner.
Is your site actually exposed? A quick self-check
You can spot obvious red flags yourself in a few minutes:
- [ ] Open your admin panel's "add user" or "change settings" form and view the page source (right-click → View Page Source). Look for a hidden input with a name like
csrf_token,_token, orauthenticity_token. If you don't see one, that form may be forgeable. - [ ] Check whether any admin action can be triggered by just visiting a URL (a plain GET link) rather than submitting a form—those are especially easy to forge.
- [ ] If you're on WordPress, confirm you're not running custom form handlers or plugins that skip WordPress's built-in
wp_nonce_field()protection—this is a common source of CSRF gaps in older or poorly maintained plugins. - [ ] If you use a custom-built admin dashboard, ask your developer directly whether CSRF tokens are implemented on every state-changing route, not just login.
If any of this is unclear, that's exactly the kind of thing a manual review is built to catch—automated scanners often miss CSRF because they can't tell a legitimate form submission from a forged one without understanding your app's logic. Our guide to manual vs. automated penetration testing walks through why that distinction matters here specifically.
Key takeaways
- CSRF doesn't steal your password—it hijacks your already-logged-in browser session to submit a real, authenticated request on your behalf.
- The tell-tale sign of exposure is a state-changing form (add user, change payout, disable 2FA) with no hidden CSRF token and no re-authentication step.
- CSRF tokens work because the attacker's page can never read a value they'd need same-origin access to see.
SameSite=StrictorSameSite=Laxcookies add a strong second layer, but shouldn't be your only defense—check your current settings with our security headers tool.- If you're not sure your admin panel or payment dashboard is protected, that uncertainty is worth resolving before an attacker finds it first.
If you want a straight answer on whether your specific site is exposed to this—not a generic checklist, but someone actually testing your login flows and forms—that's what a manual audit is for. Circuit is a one-time $49 human review of your whole site with exact fixes, or you can start with our free website security check if you just want a fast yes/no first.
A real human security engineer audits your whole site by hand and sends a full report — every issue, its severity, and the exact fix. From $49, with a 14-day money-back guarantee.
See pricing