← Back to Article List         
CSRF vs XSS Attacks

CSRF vs XSS Attacks

Published on 27 Sep 2026     4 min read ASP.NET Core MVC
MVC

CSRF vs XSS Attacks

CSRF XSS
Tricks a logged-in user into sending an unwanted request Injects malicious JavaScript into a webpage
Uses the user’s authentication cookie Runs code inside the user’s browser
Example: Unauthorized money transfer Example: Stealing cookies or user data

CSRF protection

ASP.NET Core uses anti-forgery tokens to confirm that a form request came from the application.

<form asp-action="Delete" method="post">
    <button type="submit">Delete</button>
</form>

The Form Tag Helper automatically generates the token.

Validate it in the action:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Delete(int id)
{
    return RedirectToAction("Index");
}

Additional protection:

options.Cookie.SameSite = SameSiteMode.Lax;

XSS protection

Razor automatically HTML-encodes displayed values:

<p>@Model.Comment</p>

If the comment contains <script>, it is displayed as text instead of being executed.

Additional protections:

  • Validate and sanitize user input.
  • Avoid Html.Raw() for untrusted content.
  • Use a Content Security Policy.
  • Mark sensitive cookies as HttpOnly.
  • Do not insert untrusted input directly into JavaScript.

Interview answer

CSRF sends an unauthorized request using the user’s existing login cookie. Prevent it using anti-forgery tokens and SameSite cookies.

XSS injects malicious scripts into a page. Prevent it using Razor output encoding, input sanitization and Content Security Policy.

Library: Basic CSRF and Razor encoding protections are built into ASP.NET Core; no additional package is normally required.

 

What does [ValidateAntiForgeryToken] do?

[ValidateAntiForgeryToken] protects MVC form submissions from CSRF attacks.

It checks whether the request contains a valid anti-forgery token generated by the application.

View

<form asp-action="Delete" method="post">
    @Html.AntiForgeryToken()
    <button type="submit">Delete</button>
</form>

The Form Tag Helper normally generates the token automatically for POST forms.

Controller

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Delete(int id)
{
    // Delete record
    return RedirectToAction("Index");
}

How it works

ASP.NET Core compares:

  • A token stored in a cookie
  • A token submitted with the form

If they do not match or are missing, the request is rejected with HTTP 400 Bad Request.

Interview point: It verifies that a state-changing request originated from the application’s own form, helping prevent CSRF attacks.

Library: Built into ASP.NET Core MVC; no additional NuGet package is required.

 

Apply Anti-Forgery Validation Globally

Register AutoValidateAntiforgeryTokenAttribute as a global MVC filter:

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(
        new AutoValidateAntiforgeryTokenAttribute());
});

This automatically validates anti-forgery tokens for unsafe HTTP methods:

  • POST
  • PUT
  • PATCH
  • DELETE

It does not validate safe methods such as GET, HEAD, OPTIONS, and TRACE.

Exclude a specific action

[IgnoreAntiforgeryToken]
[HttpPost]
public IActionResult ExternalWebhook()
{
    return Ok();
}

Use this exclusion carefully—for example, an external webhook that cannot provide your MVC anti-forgery token should use another validation method such as a signature.

Interview point: Global validation avoids adding [ValidateAntiForgeryToken] separately to every state-changing MVC action.

Library: Microsoft.AspNetCore.Mvc.ViewFeatures; included with ASP.NET Core MVC, so no additional NuGet package is normally required.

 

How do you prevent SQL injection?

SQL injection occurs when untrusted user input is included directly in a SQL command.

Main prevention methods

  • Use parameterized queries.
  • Use EF Core LINQ queries.
  • Never build SQL using string concatenation.
  • Validate input, but do not depend on validation alone.
  • Use a database account with minimum required permissions.
  • Use stored procedures with parameters.

Unsafe code

var sql = "SELECT * FROM Users WHERE Name = '" + name + "'";

Safe parameterized query

var command = new SqlCommand(
    "SELECT * FROM Users WHERE Name = @Name", connection);

command.Parameters.AddWithValue("@Name", name);

EF Core

var user = await context.Users
    .FirstOrDefaultAsync(x => x.Name == name);

EF Core converts the value into a SQL parameter automatically.

For raw SQL:

var users = await context.Users
    .FromSqlInterpolated($"SELECT * FROM Users WHERE Name = {name}")
    .ToListAsync();

Interview point: The primary defense is parameterization. It treats user input as data rather than executable SQL.

Libraries: EF Core requires packages such as Microsoft.EntityFrameworkCore.SqlServer. Direct SQL Server access commonly uses Microsoft.Data.SqlClient.

 

Enforcing HTTPS and HSTS

Configure middleware

if (!app.Environment.IsDevelopment())
{
    app.UseHsts();
}

app.UseHttpsRedirection();

How they work

  • UseHttpsRedirection() redirects HTTP requests to HTTPS.
  • UseHsts() sends the Strict-Transport-Security header, instructing browsers to use only HTTPS for future requests.

Configure HSTS

builder.Services.AddHsts(options =>
{
    options.MaxAge = TimeSpan.FromDays(365);
    options.IncludeSubDomains = true;
    options.Preload = true;
});

Important points

  • Place these middleware components early in the pipeline.
  • Do not normally enable HSTS during development.
  • Configure a valid TLS/SSL certificate.
  • HSTS works only after the browser successfully connects through HTTPS.
  • In production, the reverse proxy or load balancer may also handle HTTPS redirection.

Interview answer: HTTPS encrypts data while it travels between client and server. HSTS tells browsers to always use HTTPS, helping prevent protocol-downgrade and cookie-hijacking attacks.

Library: Built into ASP.NET Core; no additional NuGet package is required.