What Cross-Site Request Forgery Attacks Exploit
CSRF attacks exploit the fact that browsers automatically attach a site's cookies to any request sent to that site, even one triggered by a malicious page hosted elsewhere. If a logged-in bank customer visits an attacker's page containing a hidden auto-submitting form pointed at yourbank.com/Transfer, the browser happily includes the victim's valid authentication cookie, and the server -- seeing a properly authenticated request -- has no way to know the submission wasn't intentional unless it checks for something the attacker's page couldn't have obtained: a per-session anti-forgery token.
Cricket analogy: It's like a fan's stadium wristband (cookie) being scanned automatically at the members' gate even if someone else physically walked them there without their knowledge -- the gate trusts the wristband, not the intent behind the walk.
How @Html.AntiForgeryToken Defeats the Attack
Adding @Html.AntiForgeryToken() inside a Razor <form> renders a hidden input (__RequestVerificationToken) containing a random, unpredictable value that is also mirrored into a cookie sent to the browser separately from the session cookie. Because the attacker's malicious page has no way to read the victim's cookies or embed the correct hidden field value -- same-origin policy blocks cross-site cookie reads -- any forged form submission will either omit the token entirely or send a mismatched value, and the server rejects it before the action runs.
Cricket analogy: It's like a franchise requiring both a player's membership wristband AND a unique one-time code texted to their registered phone before allowing a locker-room-only door to open, a code an outsider could never intercept.
Wiring Up Server-Side Validation
The token by itself does nothing unless the receiving action is decorated with [ValidateAntiForgeryToken], which compares the cookie-based token against the form-field token and rejects the request with a 400 if they don't match or either is missing. Best practice is to apply this to every state-changing HTTP POST/PUT/DELETE action -- never to GET actions, since GET requests shouldn't mutate state in the first place -- and, for AJAX-heavy SPAs layered on MVC, to manually read the token from the DOM and attach it as a request header, since jQuery's $.ajax won't include hidden form fields automatically the way a normal form POST does.
Cricket analogy: It's like a stadium's turnstile scanner (the filter) actually rejecting entry if the wristband and the printed ticket number don't match, rather than just displaying both without comparing them.
@* View: Views/Account/ChangePassword.cshtml *@
@using (Html.BeginForm("ChangePassword", "Account", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.PasswordFor(m => m.NewPassword)
<button type="submit">Change Password</button>
}
// Controller
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize]
public ActionResult ChangePassword(ChangePasswordViewModel model)
{
if (!ModelState.IsValid) return View(model);
var result = UserManager.ChangePassword(
User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
return result.Succeeded
? RedirectToAction("Index", "Manage")
: View(model);
}
// Manually attaching the token for an AJAX request
var token = $('input[name="__RequestVerificationToken"]').val();
$.ajax({
url: '/Account/ChangePassword',
type: 'POST',
headers: { 'RequestVerificationToken': token },
data: { newPassword: $('#newPassword').val() }
});GET requests should be idempotent and never change server state, so they don't need anti-forgery tokens at all -- the real fix for a state-changing GET link is to convert it into a POST form, not to bolt a token onto it.
Forgetting [ValidateAntiForgeryToken] on even one state-changing POST action leaves that specific endpoint fully exposed to CSRF, regardless of how well every other action in the controller is protected -- the token check is per-action, not automatically inherited site-wide.
- CSRF exploits the browser's automatic cookie attachment to trick a server into processing an unintended request as if the victim intended it.
- @Html.AntiForgeryToken() renders a hidden field and a matching cookie with an unpredictable, session-specific value.
- [ValidateAntiForgeryToken] on the receiving action compares the form field and cookie values, rejecting mismatches with a 400.
- Same-origin policy prevents an attacker's page from reading the victim's cookie or reproducing the matching hidden field value.
- Protection should be applied to every state-changing POST/PUT/DELETE action, never relied on for GET requests.
- AJAX requests must manually read and attach the token as a header since it isn't part of a normal form POST body automatically.
- The check is per-action; missing it on a single endpoint leaves that endpoint exposed even if others are protected.
Practice what you learned
1. What browser behavior does a CSRF attack fundamentally rely on?
2. What does @Html.AntiForgeryToken() render into the page?
3. What does [ValidateAntiForgeryToken] do when the form field token and cookie token do not match?
4. Why don't GET requests typically need anti-forgery token protection?
5. Why must AJAX requests manually attach the anti-forgery token as a header?
Was this page helpful?
You May Also Like
Securing MVC Applications
A practical checklist of ASP.NET MVC security concerns beyond authentication -- output encoding, HTTPS enforcement, secure headers, and safe error handling.
Authentication in MVC
How ASP.NET MVC applications verify user identity using Forms Authentication, ASP.NET Identity, OWIN middleware, and external login providers.
Session and State Management
How ASP.NET MVC preserves data across stateless HTTP requests using Session, TempData, ViewData/ViewBag, cookies, and out-of-process session stores.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics