HIGH cross site request forgeryaspnet

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="[email protected]" />
      <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 Image tags or fetch() 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 ViewStateUserKey is 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=None without Secure (or omitting SameSite entirely 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 __RequestVerificationToken hidden 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.config or Startup.cs for CookieSameSite settings (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/204 responses that indicate successful state changes.
  • Checks for Set-Cookie headers with SameSite=None or absent SameSite attributes 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/Manage

The 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

StrategyImplementation LocationEffectivenessASP.NET Support
Anti-Forgery Token (synchronizer token pattern)Form field + server validationHigh (standard defense)Built-in (@Html.AntiForgeryToken(), [ValidateAntiForgeryToken])
SameSite=Strict/Lax CookiesCookie attributeMedium-High (browser-enforced)Configured via Cookie.SameSite or <httpCookies>
Custom Request Header (Double-Submit)Header validationMedium (vulnerable to subdomain attacks)Custom middleware/attribute required
Origin/Referer Header CheckServer-side header validationLow-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?
No. HTTPS encrypts data in transit but does not stop the browser from automatically sending cookies with cross-site requests. CSRF exploits the browser's same-origin policy weakness for credentialed requests, which HTTPS does not address.
Are ASP.NET Web API endpoints automatically protected against CSRF?
No. Web API (especially JSON APIs) typically does not use anti-forgery tokens by default. If the API relies on cookies for authentication (e.g., with 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.