Automated vulnerability scanners (like Nessus or Qualys) fail completely when testing ASP.NET Core APIs. They look for outdated server headers or missing security flags. They do not understand that your `[Authorize]` attribute is misconfigured, or that your Entity Framework binding logic allows an attacker to overwrite another user's password. A true ASP.NET Core penetration test requires manual, adversarial review of the C# controller logic and middleware pipeline.

Mass Assignment and Over-Posting in Entity Framework

Entity Framework (EF) Core allows developers to bind HTTP request payloads directly to database entity models. While this drastically reduces boilerplate code, it introduces critical mass assignment (over-posting) vulnerabilities. If your database model contains columns that should only be modified by system administrators, an attacker can simply append those fields to their JSON request payload.

During our audits, we aggressively fuzz profile update and registration endpoints. We inject structural JSON modifications, adding fields like {"roleId": 1}, {"isPremium": true}, or {"walletBalance": 999999}.

// VULNERABLE controller action binding directly to DB entity
[HttpPost]
public async Task<IActionResult> UpdateProfile([FromBody] User userEntity)
{
    // Flaw: binds all JSON fields directly to EF tracking model
    // If the attacker passed "IsAdmin": true in JSON, EF updates the DB.
    _context.Users.Update(userEntity);
    await _context.SaveChangesAsync();
    return Ok();
}

The Remediation: You must strictly decouple your API presentation layer from your database layer. Implement dedicated Data Transfer Objects (DTOs). The controller must only accept a `ProfileUpdateDto` that contains explicitly permitted fields.

// SECURE pattern using strictly scoped DTOs
public class ProfileUpdateDto
{
    public string DisplayName { get; set; }
    public string EmailAddress { get; set; }
}

[HttpPost]
public async Task<IActionResult> UpdateProfile([FromBody] ProfileUpdateDto dto)
{
    // We retrieve the user context securely via claims
    var user = await _context.Users.FindAsync(User.GetUserId());
    if (user == null) return NotFound();
    
    // Explicit, manual mapping prevents over-posting
    user.DisplayName = dto.DisplayName;
    user.EmailAddress = dto.EmailAddress;
    
    await _context.SaveChangesAsync();
    return Ok();
}

Middleware Execution Order Configuration

ASP.NET Core utilizes a sequential middleware pipeline architecture. The order of registration in your Program.cs (or Startup.cs in older versions) explicitly determines how incoming HTTP requests are processed. A common, catastrophic configuration mistake is misplacing the authorization and authentication middleware.

If a developer registers routing before authentication, but authorization before routing, the framework fails to enforce the `[Authorize]` attributes on controller endpoints. Attackers can bypass authentication completely and hit sensitive endpoints directly.

// VULNERABLE Program.cs middleware registration order
var app = builder.Build();

app.UseAuthorization(); // Flaw: evaluated before authentication is verified!
app.UseAuthentication();
app.UseRouting();
app.MapControllers();

The Remediation: Enforce the correct order of middleware execution in your bootstrap sequence. Routing must occur first, followed by authentication, then authorization, and finally endpoint mapping.

// SECURE middleware registration order
var app = builder.Build();

app.UseRouting(); // Determine the route
app.UseAuthentication(); // Identify the user
app.UseAuthorization(); // Verify the user's permissions for the route
app.MapControllers(); // Execute the endpoint logic

Broken Object Level Authorization (BOLA / IDOR)

Applying the `[Authorize]` attribute to a C# controller only verifies that the user possesses a valid authentication token. It does absolutely nothing to verify that the user actually owns the specific data they are requesting. This creates Broken Object Level Authorization (BOLA), formerly known as Insecure Direct Object Reference (IDOR).

If an endpoint accepts a database ID in the route path (e.g., `GET /api/invoices/1042`), an attacker will simply authenticate with a low-privilege account and iterate the ID integer (`1043`, `1044`). If the controller fetches the invoice directly using `_context.Invoices.FindAsync(id)` without verifying the owner, the attacker successfully exfiltrates another tenant's financial data.

We manually test every data-retrieval and data-modification endpoint in your API, attempting horizontal privilege escalation across tenant boundaries. You must enforce authorization at the data-access layer by appending a `.Where(i => i.OwnerId == User.GetUserId())` clause to every single database query.

JWT Algorithm Confusion and Validation Bypasses

ASP.NET Core relies heavily on the `Microsoft.AspNetCore.Authentication.JwtBearer` package for API authentication. If the `TokenValidationParameters` are misconfigured, attackers can forge administrative JWTs. We test for algorithm confusion attacks (changing the `alg` header from `RS256` to `HS256` and signing the token with the public key). We also test for missing audience (`ValidAudience`) and missing issuer (`ValidIssuer`) validations.

If you do not explicitly set `ValidateIssuer = true` and `ValidateAudience = true` in your JWT configuration, a token generated for a completely different microservice (or even a staging environment) can be used to authenticate against your production backend.

Data Protection API (DPAPI) Keyring Configurations

ASP.NET Core uses the Data Protection API (DPAPI) natively to encrypt cookies, Anti-Forgery (CSRF) tokens, and session identifiers. In dockerized, load-balanced, or Kubernetes environments (like AKS), the cryptographic keyring is stored locally inside the container's ephemeral filesystem by default.

When containers scale horizontally, or when a node restarts, the DPAPI keys are lost or differ across nodes. This results in intermittent session decryption failures and CSRF validation errors. We audit your infrastructure configuration to ensure your DPAPI keyring is explicitly pointed to persistent, centralized cloud storage (like Azure Key Vault, AWS KMS, or a shared Redis instance) using `AddDataProtection().PersistKeysToAzureBlobStorage(...)`.

Example finding

Over-posting leading to Administrator privilege escalation

During an audit of a fintech dashboard, we intercepted the HTTP PUT request to the `/api/users/profile` endpoint. The endpoint bound the incoming JSON payload directly to the Entity Framework `ApplicationUser` model. By injecting {"roleId": 1} (the integer mapping to the global administrator role) into the payload, the controller overwrote our standard user role in the database. We instantly gained full administrative access to the platform without exploiting a single memory corruption vulnerability.

Running enterprise microservices or monolithic backends on ASP.NET Core? You need a code-level security review.

Book an ASP.NET Core Pentest

Frequently asked questions

What is mass assignment in ASP.NET Core?

Mass assignment occurs when a controller binds client-submitted JSON fields directly to an Entity Framework database model without a binding whitelist or DTO. This allows attackers to modify restricted columns like isAdmin or accountBalance.

How do you audit ASP.NET Core middleware configurations?

We review the Program.cs or Startup.cs files to verify the order of middleware execution. If UseAuthorization is placed before UseRouting or UseAuthentication, the authorization rules can be completely bypassed by unauthenticated users.

Is DPAPI secure for keys protection in ASP.NET Core?

The Data Protection API (DPAPI) is secure if configured correctly. In load-balanced or containerized environments (like Azure Kubernetes Service), developers must explicitly configure a shared keyring storage (like Azure Key Vault or AWS KMS) to prevent decryption mismatch errors during scaling.

Related reading

Blog: .NET and ASP.NET penetration testing · API data leaks · API rate limit enforcement

Services: API security testing · Secure architecture review