TL;DR
Knowing a CSRF token doesn’t automatically let an attacker make valid POST or PUT requests. Proper implementation, including checking the Origin header and SameSite cookies, is crucial to prevent attacks.
Understanding the Problem
Cross-Site Request Forgery (CSRF) tokens are designed to protect against attackers making unwanted actions on your website on behalf of a logged-in user. However, simply possessing the token isn’t enough for an attack to succeed. Modern browsers and server-side checks provide additional layers of security.
Steps to Prevent POST/PUT Attacks Even With Token Knowledge
- Verify the Origin Header
- The
Originheader tells you where the request came from. A legitimate request will have an origin matching your domain. - Important: Don’t rely solely on the
Refererheader, as it can be easily spoofed or missing. - Example (Python/Flask):
- Example (Node.js/Express):
- Use SameSite Cookies
- The
SameSiteattribute on cookies controls when they are sent with cross-site requests. - Set
SameSite=StrictorSameSite=Laxfor your CSRF token cookie. This prevents the browser from sending the token along with requests originating from different domains. - Example (setting in PHP):
- Double Submit Cookie Pattern
- Store the CSRF token in both a cookie and a hidden form field.
- On submission, verify that the values match on the server-side. This makes it harder for attackers to forge requests without access to your domain’s cookies.
- Token Rotation
- Regularly regenerate CSRF tokens (e.g., after each form submission or periodically). This limits the window of opportunity for an attacker if a token is compromised.
- Input Validation and Output Encoding
- Always validate all user inputs to prevent injection attacks that could bypass CSRF protection.
- Encode outputs properly to avoid XSS vulnerabilities, which can be used in conjunction with CSRF.
- Consider using a well-vetted cybersecurity framework
- Frameworks like Django and Ruby on Rails have built-in CSRF protection mechanisms that handle many of these details for you.
from flask import Flask, request
app = Flask(__name__)
@app.route('/update', methods=['POST'])
if request.origin != 'https://yourdomain.com':
return "Unauthorized", 403
const express = require('express');
const app = express();
app.post('/update', (req, res) => {
if (req.headers.origin !== 'https://yourdomain.com') {
return res.status(403).send('Unauthorized');
}
});
setcookie('csrf_token', $token, ['samesite' => 'Strict']);
Why Knowing the Token Isn’t Enough
Even with a valid token, an attacker needs to bypass browser security features (like SameSite cookies) and server-side checks (Origin header verification). Modern browsers are designed to prevent cross-site requests from sending sensitive cookies automatically.
Testing Your CSRF Protection
- Use tools like Burp Suite or OWASP ZAP to simulate CSRF attacks.
- Attempt to submit a POST/PUT request with the correct token from a different domain and verify that it is blocked by your server.

