{"id":6003,"date":"2025-11-29T02:26:51","date_gmt":"2025-11-29T02:26:51","guid":{"rendered":"https:\/\/cybersecurityinfocus.com\/?p=6003"},"modified":"2025-11-29T02:26:51","modified_gmt":"2025-11-29T02:26:51","slug":"csrf-protection-tokens-vs-referer-checks","status":"publish","type":"post","link":"https:\/\/cybersecurityinfocus.com\/?p=6003","title":{"rendered":"CSRF Protection: Tokens vs Referer Checks"},"content":{"rendered":"<h2>TL;DR<\/h2>\n<p>Anti-CSRF tokens are much more reliable than relying on the Referer header or simple POST request checks to prevent Cross-Site Request Forgery (CSRF) attacks. This guide explains why and how to implement token-based protection.<\/p>\n<h2>Understanding CSRF<\/h2>\n<p>CSRF lets an attacker trick a logged-in user into performing unwanted actions on a web application they\u2019re currently using.  Imagine you\u2019re logged into your bank, and an attacker sends you a malicious link or gets you to visit a compromised website. That site could then make requests *as if* it were you, potentially transferring money without your knowledge.<\/p>\n<h2>Why Referer Checks Aren\u2019t Enough<\/h2>\n<p>The Referer header tells the server where the request came from.  It seems like a good idea to only accept POST requests that originate from your own site. However, this is easily bypassed:<\/p>\n<p>Browser Settings: Users can disable sending the Referer header.<br \/>\nProxy Servers: Proxies can modify or remove the Referer header.<br \/>\nJavaScript: JavaScript can initiate requests without a Referer header, or spoof it.<\/p>\n<p>Therefore, relying solely on Referer checks is insecure.<\/p>\n<h2>Why Simple POST Testing Isn\u2019t Enough<\/h2>\n<p>Checking if a POST request was made *at all* doesn\u2019t prevent CSRF. An attacker can still send a valid POST request; they just need to get the user to trigger it.  This isn\u2019t protection, it\u2019s simply knowing a request happened.<\/p>\n<h2>Implementing Anti-CSRF Tokens: The Right Way<\/h2>\n<p>Anti-CSRF tokens add a secret, unique value to each form submission that the server validates. Here\u2019s how:<\/p>\n<h3>1. Token Generation<\/h3>\n<p>When a user loads a page with a form (e.g., changing their password), generate a random, cryptographically secure token on the *server-side*.  Don\u2019t use predictable values!<\/p>\n<p># Example Python using secrets module<br \/>\nimport secrets<br \/>\ntoken = secrets.token_hex(16)<\/p>\n<h3>2. Token Inclusion in Forms<\/h3>\n<p>Embed this token as a hidden field within your form.<\/p>\n<p>&lt;form action=&#8221;\/change-password&#8221; method=&#8221;post&#8221;&gt;<br \/>\n  &lt;input type=&#8221;hidden&#8221; name=&#8221;csrf_token&#8221; value=&#8221;{{ csrf_token }}&#8221;&gt;<br \/>\n  &#8230; other form fields &#8230;<br \/>\n&lt;\/form&gt;<\/p>\n<h3>3. Token Storage (Server-Side)<\/h3>\n<p>Store the token associated with the user\u2019s session on the server. Common methods include:<\/p>\n<p>Session Variables: The simplest approach, but can be limited by session storage mechanisms.<br \/>\nDatabase: More robust for larger applications and scalability.<\/p>\n<h3>4. Token Validation<\/h3>\n<p>When the form is submitted:<\/p>\n<p>Retrieve the token from the form submission.<br \/>\nRetrieve the stored token for that user\u2019s session.<br \/>\nCompare the tokens. If they match, the request is likely legitimate. If not, reject it.<\/p>\n<p># Example Python (simplified)<br \/>\nif request.method == &#8216;POST&#8217;:<br \/>\n    submitted_token = request.form[&#8216;csrf_token&#8217;]<br \/>\n    stored_token = session.get(&#8216;csrf_token&#8217;)<br \/>\n    if submitted_token == stored_token:<br \/>\n        # Process the form data<br \/>\n        &#8230;<br \/>\n    else:<br \/>\n        # Reject the request &#8211; CSRF detected!<br \/>\n        abort(403)<\/p>\n<h3>5. Token Rotation<\/h3>\n<p>For extra security, regenerate the token after each successful submission or periodically (e.g., every hour). This limits the window of opportunity for an attacker if a token is compromised.<\/p>\n<h2>Important Considerations<\/h2>\n<p>HTTPS: Always use HTTPS to protect tokens in transit.<br \/>\nToken Length: Use sufficiently long and random tokens (at least 32 characters).<br \/>\nFramework Support: Most web frameworks (Django, Flask, Ruby on Rails, Laravel, etc.) provide built-in CSRF protection mechanisms \u2013 use them! They handle token generation, storage, and validation for you.<\/p>\n<p>The post <a href=\"https:\/\/blog.g5cybersecurity.com\/csrf-protection-tokens-vs-referer-checks\/\">CSRF Protection: Tokens vs Referer Checks<\/a> appeared first on <a href=\"https:\/\/blog.g5cybersecurity.com\/\">Blog | G5 Cyber Security<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>TL;DR Anti-CSRF tokens are much more reliable than relying on the Referer header or simple POST request checks to prevent Cross-Site Request Forgery (CSRF) attacks. This guide explains why and how to implement token-based protection. Understanding CSRF CSRF lets an attacker trick a logged-in user into performing unwanted actions on a web application they\u2019re currently [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-6003","post","type-post","status-publish","format-standard","hentry","category-news"],"_links":{"self":[{"href":"https:\/\/cybersecurityinfocus.com\/index.php?rest_route=\/wp\/v2\/posts\/6003"}],"collection":[{"href":"https:\/\/cybersecurityinfocus.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cybersecurityinfocus.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/cybersecurityinfocus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6003"}],"version-history":[{"count":0,"href":"https:\/\/cybersecurityinfocus.com\/index.php?rest_route=\/wp\/v2\/posts\/6003\/revisions"}],"wp:attachment":[{"href":"https:\/\/cybersecurityinfocus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6003"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cybersecurityinfocus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6003"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cybersecurityinfocus.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6003"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}