Prototype Pollution in Aspnet
How Prototype Pollution Manifests in Aspnet
Prototype pollution in Aspnet applications occurs when untrusted input can modify JavaScript object prototypes, leading to security vulnerabilities. While Aspnet is primarily a server-side framework, prototype pollution becomes relevant when Aspnet applications interact with JavaScript-heavy frontends or use JavaScript-based APIs.
In Aspnet applications, prototype pollution typically manifests through JSON deserialization of user input. When Aspnet Web API controllers accept JSON payloads and deserialize them into dynamic objects or ExpandoObject instances, malicious payloads can exploit prototype chain manipulation.
// Vulnerable Aspnet Web API endpoint
[HttpPost("api/vulnerable")]
public IActionResult Create([FromBody] dynamic input)
{
var data = input as ExpandoObject;
// Malicious payload: {"__proto__": {"isAdmin": true}}
return Ok(data);
}
The above code is vulnerable because dynamic typing and ExpandoObject bypass Aspnet's normal type safety, allowing prototype pollution payloads to execute. When the JSON deserializer processes {"__proto__": {"isAdmin": true}}, it modifies the base Object prototype, potentially affecting all objects in the application.
Another Aspnet-specific manifestation occurs in model binding scenarios. When using [FromBody] with complex types that include dictionary properties, prototype pollution can occur:
public class UserProfile
{
public Dictionary<string, object> Properties { get; set; }
}
// Malicious payload: {"Properties": {"__proto__": {"isAdmin": true}}}
Model binding in Aspnet Core's JSON.NET deserializer processes these nested objects recursively, potentially allowing prototype pollution to propagate through the object graph.
AspNet Core SignalR applications are particularly vulnerable to prototype pollution when handling dynamic messages. SignalR's JSON-based message protocol can be exploited if client messages are deserialized without proper validation:
public class ChatHub : Hub
{
public async Task SendMessage(dynamic message)
{
// message could contain prototype pollution payload
await Clients.All.SendAsync("ReceiveMessage", message);
}
}
Additionally, Aspnet applications using JavaScript interop (via Blazor or custom JavaScript callbacks) can be vulnerable when server-side C# code processes client-side JavaScript objects that have been polluted.
Aspnet-Specific Detection
Detecting prototype pollution in Aspnet applications requires a multi-layered approach. Static code analysis can identify vulnerable patterns, particularly around dynamic typing and JSON deserialization.
Using middleBrick's API security scanner, you can detect prototype pollution vulnerabilities in your Aspnet endpoints. middleBrick's black-box scanning approach tests unauthenticated endpoints for prototype pollution by sending specially crafted payloads:
# Scan Aspnet API endpoints with middleBrick
middlebrick scan https://yourapi.com/api/vulnerable
middleBrick tests for prototype pollution using payloads that target JavaScript object prototypes, even when scanning Aspnet endpoints. The scanner's Input Validation check specifically looks for unsafe deserialization patterns and prototype chain manipulation attempts.
For runtime detection in Aspnet applications, implement request validation middleware that inspects incoming JSON payloads:
public class PrototypePollutionDetectionMiddleware
{
private readonly RequestDelegate _next;
public PrototypePollutionDetectionMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.HasJsonContentType())
{
var reader = context.Request.BodyReader.AsStream()
.AsBsonReader(); // Custom reader to inspect payload
// Check for prototype pollution patterns
if (ContainsPrototypePollution(reader))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Prototype pollution detected");
return;
}
}
await _next(context);
}
}
Code review should focus on these Aspnet-specific patterns:
- Use of
dynamicorExpandoObjectin API controllers - Complex model binding with dictionary properties
- SignalR hub methods accepting dynamic parameters
- Custom JSON deserialization without validation
middleBrick's scanning provides immediate feedback with severity ratings and specific remediation guidance. For prototype pollution, middleBrick tests with payloads designed to detect prototype chain manipulation and provides Aspnet-specific remediation recommendations based on the detected vulnerability patterns.
Aspnet-Specific Remediation
Remediating prototype pollution in Aspnet applications requires eliminating unsafe deserialization and implementing strict input validation. The most effective approach is to avoid dynamic typing and use strongly-typed models throughout your API.
// Secure approach - strongly typed models
public class UserProfile
{
public string Username { get; set; }
public string Email { get; set; }
public bool IsAdmin { get; set; } // Explicitly defined, not settable via pollution
}
[HttpPost("api/secure")]
public IActionResult Create([FromBody] UserProfile profile)
{
// Model binding ensures only defined properties are set
return Ok(profile);
}
For scenarios requiring dynamic behavior, implement a custom JSON converter that blocks prototype pollution payloads:
public class SafeJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ExpandoObject);
}
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var doc = JsonDocument.ParseValue(ref reader);
if (ContainsPrototypePollution(doc.RootElement))
{
throw new JsonException("Prototype pollution payload detected");
}
return JsonSerializer.Deserialize<ExpandoObject>(ref reader, options);
}
}
Configure Aspnet to use this converter globally:
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new SafeJsonConverter());
});
For SignalR applications, implement strict message contracts:
public class ChatMessage
{
[JsonPropertyName("user")]
public string User { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
public class SecureChatHub : Hub
{
public async Task SendMessage([Required] ChatMessage message)
{
// Strongly typed, validated message
await Clients.All.SendAsync("ReceiveMessage", message);
}
}
Implement request validation middleware to sanitize JSON payloads before deserialization:
public class JsonSanitizationMiddleware
{
private readonly RequestDelegate _next;
public JsonSanitizationMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.HasJsonContentType())
{
var originalBody = context.Request.Body;
var sanitizedBody = new MemoryStream();
await originalBody.CopyToAsync(sanitizedBody);
sanitizedBody.Position = 0;
// Sanitize JSON to remove prototype pollution patterns
var sanitizedJson = SanitizeJson(sanitizedBody);
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(sanitizedJson));
context.Request.Body.Position = 0;
}
await _next(context);
}
}
middleBrick's continuous monitoring (Pro plan) can help verify that your remediation efforts are effective by regularly scanning your API endpoints for prototype pollution vulnerabilities and alerting you if new issues emerge.