Skip to main content

Lack of data validation - Numbers

Need

Implementation of robust data validation for numbers

Context

  • Usage of C# 7.0 for modern language features and enhancements
  • Usage of Microsoft.AspNetCore.Mvc for building web applications with ASP.NET Core
  • Usage of Microsoft.EntityFrameworkCore for data access and object-relational mapping (ORM) in .NET applications

Description

Non compliant code

public class ProductController : Controller
{
[HttpPost]
public IActionResult Create(string name, int price)
{
var product = new Product(name, price);
_context.Products.Add(product);
_context.SaveChanges();

return Ok();
}
}

In the above code, the Create method of the ProductController class is vulnerable due to the lack of data validation. The method accepts a name and a price as parameters and directly uses these to create a new Product object, which is then added to the Products collection in the _context object and saved to the database.

The vulnerability lies in the fact that there is no validation performed on the price parameter. If a negative number, zero, or an unreasonably large number is passed as the price, the method will still proceed to create the Product object and save it to the database. This could lead to incorrect data being stored, which could break the business logic and negatively impact the business.

For example, if a negative price is saved, this could lead to incorrect calculations when determining the total cost of a set of products. Similarly, if an unreasonably large price is saved, this could lead to incorrect calculations that exceed the maximum value that can be stored in an integer, causing an overflow error.

Furthermore, the lack of validation could also open up the possibility for SQL Injection attacks if the price parameter is used in a SQL query.

Thus, it's crucial to add proper data validation to ensure that only valid prices are allowed to be saved to the database.

Steps

  • Implement input validation for the 'name' parameter to ensure it is not empty or null.
  • Implement input validation for the 'price' parameter to ensure it is a valid positive number.
  • Handle validation errors and return appropriate error responses to the client.
  • Consider using data annotations or a validation library to simplify the validation process.
  • Ensure that the validation is performed both on the client-side and server-side to provide a robust defense against malicious input.

Compliant code

using System.ComponentModel.DataAnnotations;

public class ProductModel
{
[Required]
public string Name { get; set; }

[Required]
[Range(1, int.MaxValue, ErrorMessage = "Please enter a value bigger than {1}")]
public int Price { get; set; }
}

public class ProductController : Controller
{
[HttpPost]
public IActionResult Create([FromBody] ProductModel productModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var product = new Product(productModel.Name, productModel.Price);
_context.Products.Add(product);
_context.SaveChanges();

return Ok();
}
}

The code above fixes the vulnerability by adding data validation to the Create method in the ProductController class.

Firstly, a new ProductModel class is created to represent the incoming product data. This class includes two properties: Name and Price. Both properties are decorated with the [Required] attribute to ensure that they are not null or empty. The Price property is also decorated with the [Range] attribute to ensure that it is a positive number.

In the Create method, the [FromBody] attribute is added to the productModel parameter to bind the incoming JSON data to the ProductModel object. Then, the ModelState.IsValid property is checked to see if the incoming data is valid according to the data annotations in the ProductModel class. If the data is not valid, the method returns a BadRequest response with the validation errors.

If the data is valid, a new Product object is created and added to the database. The method then returns an Ok response to indicate that the product was successfully created.

This approach ensures that only valid data is processed by the application, thereby preventing the business logic from being broken by invalid or malicious input.

References