HIGH prototype pollutionaspnetbasic auth

Prototype Pollution in Aspnet with Basic Auth

Prototype Pollution in Aspnet with Basic Auth — how this specific combination creates or exposes the vulnerability

Prototype pollution in ASP.NET applications becomes particularly concerning when combined with Basic Authentication, because the authentication mechanism does not prevent malicious input from reaching object construction and model-binding code. In ASP.NET, model binders copy incoming data into .NET objects, and if the application merges user-supplied data into prototypes or static dictionaries, an attacker can inject properties that affect object behavior across requests.

When Basic Authentication is used, credentials are transmitted in the Authorization header as a base64-encoded string. While this does not inherently expose the system to prototype pollution, it creates a steady stream of authenticated requests that may include untrusted JSON or form data. If the application deserializes attacker-controlled JSON (for example, to update configuration or user settings) and uses JsonConvert.PopulateObject or similar methods that merge data into existing objects, injected properties such as __proto__, constructor.prototype, or other special keys can modify the prototype chain for constructors used elsewhere in the app domain.

Consider an endpoint that updates user preferences using model binding and merges data into a shared options object. A crafted request with a polluted property can change default behavior for other users or escalate issues across components, especially if the polluted object is cached or reused. Since Basic Authentication does not validate or sanitize the request body, the polluted properties reach the server-side logic where object creation occurs. This combination allows an attacker to influence property resolution, potentially affecting reflection-based logic, serialization settings, or conditional checks that rely on inherited prototypes.

Real-world attack patterns include exploiting known .NET deserialization gadgets (e.g., via System.Web.Script.Serialization or libraries that use JavaScriptSerializer) where prototype-like behavior can be abused to override equality checks or trigger unexpected code paths. While ASP.NET does not expose browser-style prototypes directly, the term refers to the modification of shared object templates that influence multiple instances. When these gadgets are reachable through authenticated endpoints using Basic Auth, the risk increases because authenticated sessions may have broader permissions, and the polluted state can persist beyond a single request.

Tools like middleBrick detect this risk by correlating authentication mechanisms with data flow into model binders and deserialization routines. Using its 12 parallel security checks, it identifies dangerous sinks such as ObjectMapper usage, unchecked JSON merges, and missing input validation on authenticated routes. The scanner also examines OpenAPI/Swagger specs (including $ref resolution) to map where authenticated operations accept untrusted payloads, highlighting findings with severity and remediation guidance tied to frameworks such as OWASP API Top 10 and PCI-DSS.

Basic Auth-Specific Remediation in Aspnet — concrete code fixes

To mitigate prototype pollution in ASP.NET when using Basic Authentication, focus on preventing untrusted data from reaching object population logic and validating all inputs before deserialization. Avoid using methods that merge raw JSON directly into existing objects, and prefer immutable or explicitly mapped models. Below are concrete code examples that demonstrate secure practices.

First, configure Basic Authentication without allowing automatic model binding to merge data into shared objects. Use explicit DTOs and validate input before processing.

using Microsoft.AspNetCore.Authentication.Basic;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Encodings.Web;
using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
    .AddBasic(options =>
    {
        options.DisplayName = "Secure";
        options.Events = new BasicAuthenticationEvents
        {
            OnValidatePrincipal = context =>
            {
                var username = context.UserName;
                var password = context.Password;
                // Validate credentials securely, avoid prototype pollution sources
                if (username == "admin" && password == "SecurePass123")
                {
                    context.Principal = new System.Security.Claims.ClaimsPrincipal(
                        new System.Security.Principal.GenericIdentity(username));
                }
                return Task.CompletedTask;
            }
        };
    });
builder.Services.AddAuthorization();

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();

app.MapPost("/update-settings", (UserSettingsDto dto) =>
{
    // Apply settings using explicit mapping, avoid merging into shared prototypes
    return Results.Ok(new { Message = "Settings updated" });
}).RequireAuthorization();

app.Run();

public class UserSettingsDto
{
    public string Theme { get; set; }
    public int PageSize { get; set; }
}

Second, if you must accept JSON input, use strict deserialization settings that ignore modification of prototypes and avoid PopulateObject. Prefer creating new objects instead of merging.

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
    // Prevent handling of special member names that could cause pollution
    AllowTrailingCommas = false
};
var cleanObject = JsonSerializer.Deserialize<UserSettingsDto>(jsonString, options);
// Apply cleanObject without merging into shared instances

Third, add input validation to reject keys commonly used in prototype pollution attacks, such as __proto__, constructor, and prototype, at the API gateway or model binder level.

app.Use(async (context, next) =>
{
    if (context.Request.Body is { } body)
    {
        using var reader = new StreamReader(body, leaveOpen: true);
        var text = await reader.ReadToEndAsync();
        if (text.Contains("__proto__") || text.Contains("constructor.prototype"))
        {
            context.Response.StatusCode = 400;
            await context.Response.WriteAsync("Invalid input");
            return;
        }
        // Restore stream for model binding
        body.Position = 0;
    }
    await next();
});

By combining explicit authentication, strict deserialization, and input validation, you reduce the risk of prototype pollution in endpoints protected by Basic Authentication. middleBrick’s scans can verify that these controls are in place by analyzing the authentication setup, request flows, and OpenAPI/Swagger definitions, providing prioritized findings and remediation guidance without claiming to fix or block issues directly.

Frequently Asked Questions

Does middleBrick fix prototype pollution findings automatically?
No. middleBrick detects and reports prototype pollution risks with severity and remediation guidance. It does not automatically fix, patch, block, or remediate issues.
Can middleBrick scan authenticated API endpoints using Basic Auth?
middleBasket scans the unauthenticated attack surface by default. To include authenticated areas, ensure endpoints are reachable without additional credentials or use scans that respect your authentication setup where applicable.