What is JSON injection?
Example Attack Payload
{
"username": "attacker",
"email": "[email protected]",
"isAdmin": true, // Sensitive field injection
"__proto__": { "polluted": "yes" } // Prototype pollution attack
}
If your API model-binds this blindly into your entity, attackers can escalate privileges or poison objects.
Risks of Malformed JSON
Denial of Service (DoS): Sending enormous JSON payloads.
Deserialization flaws: Exploiting weak parsers (e.g., type confusion).
Validation bypass: Sending unexpected JSON structures.
How to Protect in ASP.NET Core?
1. Use DTOs Instead of Entities
Never accept raw JSON into entity models. Define Data Transfer Objects (DTOs) with strict fields.
public class RegisterDto
{
[Required, StringLength(50)]
public string Username { get; set; }
[Required, EmailAddress]
public string Email { get; set; }
[Required, StringLength(100)]
public string Password { get; set; }
}
Controller
[HttpPost("register")]
public IActionResult Register([FromBody] RegisterDto dto)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
// Safe mapping
var user = new User
{
Username = dto.Username,
Email = dto.Email,
IsAdmin = false // Explicitly controlled
};
return Ok(user);
}
Prevents attackers from injecting extra JSON properties, such as isAdmin.
2. Reject Unknown Properties
By default, System. Text.Json ignores unknown fields. Force it to fail on unknown JSON properties.
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Disallow;
options.JsonSerializerOptions.AllowTrailingCommas = false;
options.JsonSerializerOptions.UnknownTypeHandling = System.Text.Json.Serialization.JsonUnknownTypeHandling.Fail;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
});
Or, in Newtonsoft.Json.
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Error;
});
Any unexpected JSON field will cause a 400 Bad Request.
3. Input Validation
Use Data Annotations or FluentValidation to validate JSON payloads.
if (!ModelState.IsValid)
return BadRequest(ModelState);
Ensures malformed JSON (wrong type, missing field) gets rejected.
4. Limit Request Size (Prevent DoS)
Attackers may send gigantic JSON payloads to crash your server. Set max request body size.
app.Use(async (context, next) =>
{
context.Request.Headers.ContentLength = Math.Min(context.Request.ContentLength ?? 0, 10_000); // 10 KB
await next();
});
Or in Kestrel
builder.WebHost.ConfigureKestrel(options =>
{
options.Limits.MaxRequestBodySize = 10 * 1024; // 10 KB
});
Protects against payload flooding.
5. Sanitize JSON String Fields
Attackers may inject <script> or SQL-like payloads inside JSON strings. Use HtmlSanitizer or encoding before saving.
var sanitizer = new HtmlSanitizer();
dto.Username = sanitizer.Sanitize(dto.Username);
Prevents XSS when storing/displaying JSON fields.
6. Strong Content-Type Validation
Reject requests that are not application/json.
if (!context.Request.ContentType?.Contains("application/json") ?? true)
{
context.Response.StatusCode = StatusCodes.Status415UnsupportedMediaType;
return;
}
Stops attackers from sneaking payloads with wrong MIME types.
7. Use JsonDocument for Strict Parsing
If you donβt trust the payload at all, parse manually.
using var doc = JsonDocument.Parse(jsonString, new JsonDocumentOptions
{
AllowTrailingCommas = false,
CommentHandling = JsonCommentHandling.Disallow
});
if (!doc.RootElement.TryGetProperty("username", out var username))
return BadRequest("Missing username");
Complete control over parsing logic.
8. Audit & Logging
Log rejected payloads with correlation IDs.
_logger.LogWarning("Invalid JSON payload received: {Payload}", jsonString);
Helps detect attack attempts.
Best Practices Checklist
Use DTOs (never bind entities).
Fail on unknown JSON properties.
Validate input with Data Annotations/FluentValidation.
Set max request body size to prevent DoS.
Sanitize string fields for XSS safety.
Enforce application/json Content-Type.
Parse manually ( JsonDocument ) for untrusted payloads.
Log and monitor invalid payload attempts.
Conclusion
ASP.NET Core provides strong defenses, but developers must explicitly enable strict JSON parsing and validation.
By using DTOs, rejecting unknown fields, sanitizing input, and setting request limits, you protect your API from.