Cross Site Request Forgery in Aspnet
How Cross Site Request Forgery Manifests in Aspnet
Cross-Site Request Forgery (CSRF) in ASP.NET applications exploits the trust a server has in a user's browser session. An attacker tricks an authenticated user's browser into submitting a malicious request to a vulnerable ASP.NET endpoint. The browser automatically includes session cookies (like .ASPXAUTH or ASP.NET_SessionId), causing the server to process the request as the legitimate user.
ASP.NET-Specific Attack Patterns:
- Classic Form Submission (MVC/WebForms): A vulnerable
<form>without an anti-forgery token. Attackers host a page with auto-submitting JavaScript:<form action="https://victim.com/Account/ChangeEmail" method="post"> <input type="hidden" name="newEmail" value="attacker@evil.com" /> <input type="submit" value="Click for free stuff!" /> </form> <script>document.forms[0].submit();</script> - AJAX/API Endpoints (Web API/MVC API): State-changing GET requests (violating REST principles) or POST/PUT/DELETE endpoints that rely solely on cookies for authentication. An attacker can use
Imagetags orfetch()from a malicious site:fetch('https://victim.com/api/orders/123/cancel', { method: 'POST', credentials: 'include' // Sends cookies automatically }); - Misconfigured Anti-Forgery in MVC: Using
[ValidateAntiForgeryToken]on actions but forgetting to include@Html.AntiForgeryToken()in the corresponding view, or mismatching token names due to custom form rendering. - WebForms ViewState MAC Bypass: If
ViewStateUserKeyis not set per-session, an attacker might manipulate ViewState to forge postbacks. While less common today, legacy WebForms apps remain vulnerable. - SameSite Cookie Misconfiguration: Setting
SameSite=NonewithoutSecure(or omittingSameSiteentirely in modern browsers) allows cross-site cookie transmission.
These flaws typically appear in account management (/Account/ChangePassword), financial transactions (/Checkout/Confirm), and administrative actions (/Admin/User/Delete).
Aspnet-Specific Detection
Detecting CSRF in ASP.NET requires examining both the HTML responses and API contract. Manual testing involves:
- Inspecting forms for missing
__RequestVerificationTokenhidden fields. - Checking if state-changing endpoints accept GET requests.
- Verifying that
[ValidateAntiForgeryToken]or[AutoValidateAntiforgeryToken]attributes are present on controller actions that modify data. - Reviewing
web.configorStartup.csforCookieSameSitesettings (e.g.,SameSiteMode.None).
Automated Scanning with middleBrick
middleBrick's black-box scanner tests for CSRF as part of its BOLA/IDOR and Authentication categories. It:
- Fetches HTML pages and parses forms to identify missing anti-forgery tokens in state-changing methods (POST, PUT, DELETE).
- Probes API endpoints (including those defined in OpenAPI specs) by sending cross-site simulation requests without valid tokens, looking for
200/201/204responses that indicate successful state changes. - Checks for
Set-Cookieheaders withSameSite=Noneor absentSameSiteattributes on authentication cookies. - Correlates findings with OpenAPI/Swagger definitions: if an operation is marked as modifying data but lacks security schemes or anti-forgery requirements, it flags potential CSRF.
Example CLI usage to scan an ASP.NET MVC app:
middlebrick scan https://your-aspnet-app.com/Account/ManageThe report will list endpoints vulnerable to CSRF under the BOLA/IDOR category, with severity based on the impact (e.g., email change = high, profile picture update = medium).
Aspnet-Specific Remediation
1. Use Built-in Anti-Forgery Tokens (MVC/Razor Pages)
For every form that performs a state-changing operation, generate and validate a token.
View (CSHTML):
@using (Html.BeginForm("ChangeEmail", "Account")) {
@Html.AntiForgeryToken()
<input type="email" name="newEmail" />
<button type="submit">Update</button>
}Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ChangeEmail(ChangeEmailViewModel model) {
// ... logic to change email
}For AJAX requests, send the token in a request header:
// In your layout or a common JS file
var token = $('input[name="__RequestVerificationToken"]').val();
$.ajax({
url: '/api/cart/checkout',
type: 'POST',
headers: {
'RequestVerificationToken': token
}
});2. Configure Cookie SameSite Strictly
In Program.cs (ASP.NET Core) or Startup.cs (older), set SameSite to Strict or Lax for auth cookies:
services.ConfigureApplicationCookie(options => {
options.Cookie.SameSite = SameSiteMode.Strict; // or Lax
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});For legacy ASP.NET (Framework), in web.config:
<system.web>
<httpCookies sameSite="Strict" requireSSL="true" />
</system.web>3. Validate Anti-Forgery for APIs
For JSON APIs, create a custom filter or middleware to validate the token from a header (e.g., X-CSRF-Token).
// Custom attribute for Web API
public class ValidateCsrfHeaderAttribute : AuthorizationFilterAttribute {
public override void OnAuthorization(HttpActionContext actionContext) {
var request = actionContext.Request;
var token = request.Headers.Contains("X-CSRF-Token")
? request.Headers.GetValues("X-CSRF-Token").FirstOrDefault()
: null;
if (string.IsNullOrEmpty(token) || !AntiForgery.Validate(token)) {
actionContext.Response = request.CreateResponse(HttpStatusCode.Forbidden);
}
}
}Apply to API controllers:
[ValidateCsrfHeader]
public class OrdersController : ApiController {
[HttpPost]
public IHttpActionResult Cancel(int id) { /* ... */ }
}4. Enforce Non-GET for State Changes
Never use GET for operations that change server state. Use [HttpGet] only for safe, idempotent operations.
5. Double-Submit Cookie Pattern (Alternative)
If anti-forgery tokens are impractical, implement a double-submit cookie: set a random cookie (XSRF-TOKEN) and require a matching header. The server compares the cookie value and header value. This is less robust than the token pattern but better than nothing.
Comparison of CSRF Mitigation Strategies in ASP.NET
| Strategy | Implementation Location | Effectiveness | ASP.NET Support |
|---|---|---|---|
| Anti-Forgery Token (synchronizer token pattern) | Form field + server validation | High (standard defense) | Built-in (@Html.AntiForgeryToken(), [ValidateAntiForgeryToken]) |
| SameSite=Strict/Lax Cookies | Cookie attribute | Medium-High (browser-enforced) | Configured via Cookie.SameSite or <httpCookies> |
| Custom Request Header (Double-Submit) | Header validation | Medium (vulnerable to subdomain attacks) | Custom middleware/attribute required |
| Origin/Referer Header Check | Server-side header validation | Low-Medium (headers can be stripped) | Manual implementation |
Note: The synchronizer token pattern (anti-forgery tokens) remains the most reliable defense for form-based ASP.NET apps.
Frequently Asked Questions
Does using HTTPS alone prevent CSRF in ASP.NET?
Are ASP.NET Web API endpoints automatically protected against CSRF?
UseCookieAuthentication), it remains vulnerable. Protection requires explicit implementation, such as validating a custom header or switching to token-based auth (e.g., JWT in Authorization header) which is not automatically sent cross-site.