HIGH prototype pollutionaspnethmac signatures

Prototype Pollution in Aspnet with Hmac Signatures

Prototype Pollution in Aspnet with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Prototype pollution in ASP.NET applications becomes particularly concerning when HMAC signatures are used to validate request integrity but are applied after object binding. In this scenario, an attacker can supply crafted JSON or form data containing properties such as __proto__, constructor.prototype, or other property paths that modify the prototype chain of shared JavaScript objects when the data is later rendered in client-side templates or deserialized in a Node.js-like environment within the stack. If the server uses model binding to populate a DTO and then re-serializes or passes that data to a JavaScript runtime, the polluted prototype can affect object behavior across requests.

HMAC signatures are commonly used to ensure that request payloads have not been tampered with. However, if the server computes the HMAC over the raw request body and then performs model binding or deserialization that is vulnerable to prototype pollution, an attacker can modify properties that do not affect the semantic meaning of the payload from the server’s perspective, while the signature remains valid. For example, adding __proto__.isAdmin to JSON does not change the byte-level HMAC if the server signs the exact request body, yet the deserialized object may now carry a poisoned prototype when later merged with other objects or used in client-side rendering. This creates a bypass where integrity checks pass, but the runtime behavior of downstream JavaScript logic is altered.

In ASP.NET, this often occurs when developers use FromBody to bind JSON into C# objects and then pass those objects to libraries or services that eventually serialize data back to a browser context. If the server does not explicitly whitelist allowed properties or validate input against a strict schema, prototype pollution can manifest indirectly — for instance, when the polluted object is included in error messages, logs, or responses that are consumed by client-side JavaScript. The HMAC signature does not protect against this because the server-side validation of the signature does not inspect the semantic impact of bound properties on object inheritance.

Real-world patterns that can trigger this include using Newtonsoft.Json with TypeNameHandling enabled, or using polymorphic deserialization without strict type constraints. Attackers may submit payloads like {"__proto__": {"role": "admin"}, "data": "legitimate"} and rely on the server’s processing logic to propagate the polluted prototype into shared objects. Even if the server discards the polluted field before computing the HMAC, some implementations may compute the signature over the post-processed object graph, creating subtle inconsistencies between what is signed and what is validated.

To detect this during scanning, middleBrick runs checks that examine object binding behavior, input validation strictness, and whether HMAC verification is performed before or after deserialization. The tool does not fix the code, but its findings highlight the need to treat HMAC-protected payloads as untrusted until validated against a strict schema, reinforcing the principle that integrity checks do not imply safety from prototype pollution.

Hmac Signatures-Specific Remediation in Aspnet — concrete code fixes

Remediation centers on ensuring that HMAC verification occurs before any deserialization that could trigger prototype pollution and that incoming data is validated against an explicit allowlist. The following approaches are recommended for ASP.NET applications using HMAC signatures.

  • Verify the HMAC over the raw request body before model binding, and reject the request if the signature does not match. Do not compute the HMAC after binding or after any mutation of the object graph.
  • Use strict JSON deserialization settings that disable type inference and polymorphic deserialization. Prefer System.Text.Json with JsonSerializerOptions that explicitly disallow metadata types.
  • Apply a property allowlist during model binding or immediately after deserialization to strip or reject unexpected properties such as __proto__, constructor, and prototype.

Example 1: HMAC verification before model binding using System.Text.Json

using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("[controller]")]
public class DataController : ControllerBase
{
    private const string Secret = "your-256-bit-secret";

    [HttpPost("submit")]
    public IActionResult Submit()
    {
        using var reader = new StreamReader(Request.Body);
        string rawBody = reader.ReadToEnd();

        if (!Request.Headers.TryGetValue("X-API-Signature", out var signatureHeader))
        {
            return Unauthorized();
        }

        string expectedSignature = ComputeHmacSha256(rawBody, Secret);
        if (!CryptographicOperations.FixedTimeEquals(
                Encoding.UTF8.GetBytes(expectedSignature),
                Encoding.UTF8.GetBytes(signatureHeader)))
        {
            return Unauthorized();
        }

        var options = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true,
            // Disallow metadata types and type hints that could enable polymorphism
        };

        // Only deserialize after signature verification
        var payload = JsonSerializer.Deserialize<MyData>(rawBody, options);
        if (payload == null)
        {
            return BadRequest("Invalid payload");
        }

        // Further validation: reject known pollution properties
        if (rawBody.Contains("__proto__") || rawBody.Contains("constructor"))
        {
            return BadRequest("Invalid properties detected");
        }

        return Ok(payload);
    }

    private static string ComputeHmacSha256(string data, string key)
    {
        using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
        byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
        return Convert.ToBase64String(hash);
    }
}

public class MyData
{
    public string Data { get; set; }
}

Example 2: Using a model validator to reject prototype pollution properties

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;

public class NoPrototypePollutionAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null) return ValidationResult.Success;
        var json = value as string;
        if (json == null) return new ValidationResult("Invalid format");
        if (json.Contains("__proto__") || json.Contains("constructor") || json.Contains("prototype"))
        {
            return new ValidationResult("Prototype pollution properties are not allowed");
        }
        return ValidationResult.Success;
    }
}

public class MyData
{
    [NoPrototypePollution]
    public string Payload { get; set; }
}

These examples ensure that HMAC verification is performed on the original request body and that any attempt to introduce prototype pollution properties is caught before the data is used in downstream processing. middleBrick scans can help identify whether HMAC verification is performed after deserialization and whether input validation is insufficient, providing prioritized findings with remediation guidance.

Frequently Asked Questions

Can HMAC-signed requests still be vulnerable if the server deserializes after signature verification?
Yes. If the server deserializes or binds models after computing the HMAC over the raw body, an attacker can inject properties like __proto__ that alter runtime behavior without breaking the signature. Always verify HMAC first, then validate and bind with strict schemas that reject prototype pollution properties.
Does middleBrick fix prototype pollution issues automatically?
No. middleBike detects and reports findings, including prototype pollution risks in ASP.NET APIs with Hmac signatures, along with remediation guidance. It does not modify code or block requests.