Forms Without CSRF Protection
ID |
html.forms_without_csrf_protection |
Severity |
low |
Resource |
Authentication |
Language |
Html |
Tags |
CWE:352, NIST.SP.800-53, OWASP:2021:A4, PCI-DSS:6.5.4, PCI-DSS:6.5.6 |
Description
This rule identifies HTML forms that do not include Cross-Site Request Forgery (CSRF) protection mechanisms. Forms that perform state-changing operations (such as POST, PUT, DELETE requests) without CSRF tokens are vulnerable to attacks where malicious sites can trigger unwanted actions on behalf of authenticated users.
The rule detects forms lacking common CSRF protection patterns including hidden token fields, proper anti-CSRF headers, or framework-specific CSRF implementations.
Rationale
Cross-Site Request Forgery (CSRF) is an attack that forces authenticated users to execute unwanted actions on a web application. Without proper CSRF protection, an attacker can trick a user’s browser into submitting malicious requests using the user’s authenticated session.
Common risks associated with missing CSRF protection include:
-
Unauthorized State Changes: Attackers can perform actions such as changing passwords, transferring funds, modifying account settings, or deleting data without the user’s knowledge or consent.
-
Session Riding: Malicious sites can leverage the user’s authenticated session cookies to perform privileged operations that the user never intended.
-
Reputation Damage: Successful CSRF attacks can lead to unauthorized transactions, data manipulation, and loss of user trust.
Consider the following insecure example:
<form method="POST" action="/api/transfer-funds">
<input type="text" name="recipient" />
<input type="number" name="amount" />
<button type="submit">Transfer</button>
</form>
This form lacks any CSRF protection, making it vulnerable to attacks from malicious websites.
Remediation
Implement CSRF protection for all forms that perform state-changing operations.
Recommended approaches:
1. Synchronizer Token Pattern (most common):
<form method="POST" action="/api/transfer-funds">
<input type="hidden" name="csrf_token" value="a8f7d9e2b1c4..." />
<input type="text" name="recipient" />
<input type="number" name="amount" />
<button type="submit">Transfer</button>
</form>
2. Double Submit Cookie Pattern:
<form method="POST" action="/api/transfer-funds">
<input type="hidden" name="csrf_token" id="csrf-token" />
<input type="text" name="recipient" />
<input type="number" name="amount" />
<button type="submit">Transfer</button>
</form>
<script>
document.getElementById('csrf-token').value = getCsrfCookieValue();
</script>