The confusing thing about CSRF is not what the attacker does. It's why your server believes them.
Nothing gets stolen. The attacker never sees the session cookie, never cracks anything, and never touches your infrastructure. They just get the victim's browser to make a request, and the browser helpfully attaches the credential on their behalf.

Reading the diagram
Steps 1 and 2 are an ordinary login. Your app sets a session cookie, which is what it's supposed to do.
Step 3 is the only thing the victim does wrong, and it barely qualifies: they open a link. Step 4 hands their browser a page containing a form that submits itself, aimed at your domain.
Step 5 is the whole attack. The browser sends that POST to your app and, because the request is going to your domain, it attaches your session cookie. It does this automatically. It's not a bug, it's what cookies have always done.
By step 6 your server has received a request with a valid session and no way to tell it apart from a real one.
This is why the usual defences do nothing here. Rotating secrets, longer passwords, encrypting the database, HTTPS: none of them touch this. The request is legitimate in every way your server can measure. The only thing wrong with it is that the user did not intend it.
What actually stops it
Because the problem is intent rather than identity, the fix has to prove the request came from your own interface.
SameSitecookies.Laxis the modern browser default and blocks the cross-site POST in the diagram outright. This is most of your protection and you may already have it for free.- CSRF tokens. A per-session random value your page includes and the attacker's page cannot read. Worth adding on anything that moves money or deletes data.
- Re-authenticate for the serious things. Asking for a password before deleting an account defeats this regardless of cookies.
What does not work is checking the Referer header alone, which is stripped or spoofed often enough to be unreliable.
The Mermaid source
Copy this and adapt it to your own endpoints.
sequenceDiagram
autonumber
participant V as Victim's browser
participant E as evil-site.com (the attacker)
participant Y as your-app.com (yours)
V->>Y: logs in normally
Y-->>V: sets session cookie
Note over V,Y: so far, everything is fine
V->>E: victim opens a link in another tab
E-->>V: page with a hidden form that<br/>submits itself to your-app.com
rect rgb(254, 242, 242)
V->>Y: POST /account/delete
end
Note over V,Y: the browser attaches the session cookie<br/>automatically. nobody had to steal anything.
Y-->>V: valid cookie, so the request runs
Note over V,Y: your server never saw anything suspicious
How does the attacker get my session cookie?
They do not. That is the part people miss. The attacker never sees or touches the cookie. They only need the victim's browser to send a request to your domain, and the browser attaches the cookie to that request by itself, because that is what cookies are for. This is why stronger passwords, rotating secrets and better encryption do nothing against CSRF.
Does HTTPS protect against CSRF?
No. HTTPS stops someone reading the traffic in transit. In a CSRF attack nobody is reading traffic. The request is well formed, correctly encrypted, and carries a genuine session, which is exactly why the server accepts it.
Is SameSite enough on its own?
SameSite=Lax is the default in modern browsers and it blocks the common cross-site POST, so it stops most of this. It is not a complete answer: older browsers, deliberately relaxed SameSite=None cookies, and some same-site subdomain setups still leave a gap. Add CSRF tokens on anything that moves money or deletes data.
Are your cookies set correctly?
A scan checks your cookie flags, including SameSite, on every response.