Get a Pentest and security assessment of your IT network.

Cyber Security

CSRF Protection for Web Services

TL;DR

Cross-Site Request Forgery (CSRF) lets attackers trick users into performing unwanted actions on a web service they’re logged into. This guide shows you how to protect your services using tokens, checking the Origin header, and other methods.

Understanding CSRF

Imagine you’re logged into your online banking. An attacker sends you an email with a link that *looks* harmless. Clicking it might actually send a request to your bank’s server to transfer money – without your knowledge! That’s CSRF in action.

How to Protect Your Web Services

  1. Use Anti-CSRF Tokens
    • Generate a unique, secret token for each user session.
    • Include this token as a hidden field in all forms or as a header with sensitive requests (e.g., POST, PUT, DELETE).
    • When the request is received, verify that the token matches the one stored for that user’s session. If they don’t match, reject the request.

    Example (Python/Flask):

    from flask import Flask, render_template, request, session
    import secrets
    
    app = Flask(__name__)
    app.secret_key = 'your_secret_key'
    
    @app.route('/')
    def index():
      if 'csrf_token' not in session:
        session['csrf_token'] = secrets.token_hex(16) # Generate a random token
      return render_template('index.html', csrf_token=session['csrf_token'])
    
    @app.route('/submit', methods=['POST'])
    def submit():
        if request.form['csrf_token'] == session['csrf_token']:
            # Process the form data safely
            return 'Form submitted successfully!'
        else:
            return 'CSRF token invalid!'
    
  2. Check the Origin Header
    • The Origin header tells you where the request came from.
    • Verify that the Origin header matches your expected domain(s). This prevents requests originating from malicious sites.
    • Be careful with subdomains – decide if they should be allowed or blocked.

    Example (Node.js/Express):

    const express = require('express');
    const app = express();
    
    app.post('/submit', (req, res) => {
      const allowedOrigins = ['https://yourdomain.com', 'https://www.yourdomain.com'];
      const origin = req.headers.origin;
    
      if (allowedOrigins.includes(origin)) {
        // Process the request safely
        res.send('Request processed successfully!');
      } else {
        res.status(403).send('Forbidden - Invalid Origin');
      }
    });
    
  3. Use SameSite Cookies
    • The SameSite attribute controls when cookies are sent with cross-site requests.
    • Set SameSite=Strict to only send the cookie on requests originating from your own domain. This offers strong CSRF protection but can break legitimate cross-site functionality.
    • SameSite=Lax is a more lenient option that allows cookies for top-level navigation (e.g., following links) but blocks them for POST requests.

    Example (setting in HTTP response header):

    Set-Cookie: sessionid=value; SameSite=Strict
  4. Double Submit Cookie Pattern
    • Generate a random value and set it as both a cookie *and* a hidden field in your form.
    • On the server, compare the cookie value with the hidden field value. If they match, the request is likely legitimate.
  5. Consider using a Web Application Firewall (WAF)
    • A WAF can automatically detect and block many common CSRF attacks.
    • It’s not a replacement for implementing proper CSRF protection in your code, but it adds an extra layer of security.

Important Notes

  • GET requests should never perform state-changing actions. Use POST, PUT, DELETE etc., for those.
  • Always validate user input on the server-side. Never trust data received from the client.
  • Regularly review your code and dependencies to identify and fix potential vulnerabilities.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation