There are two versions of a Model Binder (CartModelBinder) class shown below, one or both are vulnerable.
Your job is to find out how to exploit them :)
Ideally you should provide your answer/results/proof using UnitTests :)
Note 1: The vulnerability shown in this post is a variation of real-world vulnerability that I helped to find a couple weeks ago (on an UK-based financial services company).
Note 2: I’m yet to to look/review/see a large MVC application that doesn’t have similar vulnerabilities (on both ASP.NET MVC or Spring MVC)
Note 3: the code is from the http://sportsstoremvc3.codeplex.com/ sample application, which is used as an ‘real-world application’ example by the Pro ASP.NET MVC 4 book (the code was compiled using .NET 4.0 and executed using the ASP.NET MVC 3.0 and ASP.NET MVC 4.0 versions).
Code to Review:
Let’s say that you have an ASP.NET MVC 4.0 (or 3.0) project with this configuration:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes (RouteTable.Routes); ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder()); DependencyResolver.SetResolver(new NinjectDependencyResolver()); }
With the CartModelBinder (used to create instances of the Cart Object) looking like this:
public class CartModelBinder : DefaultModelBinder { private const string sessionKey = "Cart"; protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) { // get the Cart from the session Cart cart = (Cart)controllerContext.HttpContext.Session[sessionKey]; // create the Cart if there wasn't one in the session data if (cart == null) { cart = new Cart(); controllerContext.HttpContext.Session[sessionKey] = cart; } // return the cart return cart; } }
With these Cart, CartLine and Product Model classes:
public class Cart { private List<CartLine> lineCollection = new List<CartLine>(); public IEnumerable<CartLine> Lines { get { return lineCollection; } } } public class CartLine { public Product Product { get; set; } public int Quantity { get; set; } } public class Product { [HiddenInput(DisplayValue = false)] public int ProductID { get; set; } [Required(ErrorMessage = "Please enter a product name")] public string Name { get; set; } [DataType(DataType.MultilineText)] [Required(ErrorMessage = "Please enter a description")] public string Description { get; set; } [Required] [Range(0.01, double.MaxValue, ErrorMessage = "Please enter a positive price")] public decimal Price { get; set; } //[HiddenInput(DisplayValue = false)] public int CategoryID { get; set; } public virtual Category Category { get; set; } }
And finally, with these controllers:
public RedirectToRouteResult AddToCart(Cart cart, int productId, string returnUrl) { Product product = repository.Products .FirstOrDefault(p => p.ProductID == productId); if (product != null) { cart.AddItem(product, 1); } return RedirectToAction("Index", new { returnUrl }); } public PartialViewResult Summary(Cart cart) { return PartialView(cart); } public ViewResult Index(Cart cart,string returnUrl) { return View(new CartIndexViewModel { Cart = cart, ReturnUrl = returnUrl }); }
Can you spot any security vulnerability(ies)?
What about if we change the CartModelBinder to use the IModelBinder (and BindModel) instead of DefaultModelBinder (and CreateModel)?
public class CartModelBinder : IModelBinder { private const string sessionKey = "Cart"; public object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext) { // get the Cart from the session Cart cart = (Cart)controllerContext.HttpContext.Session[sessionKey]; // create the Cart if there wasn't one in the session data if (cart == null) { cart = new Cart(); controllerContext.HttpContext.Session[sessionKey] = cart; } // return the cart return cart; } }
Anything changed? (from a security point of view, since the app works ok with both versions)
Can you spot any security vulnerability with this 2nd version of the CartModelBinder?
Or are both vulnerable?
:)
Wrapping up: Here is the question being asked in this post:
-
What is are the security implications of these two variations of an CartModelBinder (which both provide the same business-logic functionality)
Related Threads:
- Security vulnerability created by ASP.NET MVC ModelBinder (SO Question)
- http://www.reddit.com/r/dotnet/comments/1iiq67/can_you_spot_the_security/
- http://www.reddit.com/r/netsec/comments/1iiq7j/can_you_spot_the_security/
Some references and related articles:
External:
- http://msdn.microsoft.com/en-us/library/system.web.mvc.imodelbinder(v=vs.108).aspx
- http://msdn.microsoft.com/en-us/library/system.web.mvc.defaultmodelbinder(v=vs.98).aspx
- https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/DefaultModelBinder.cs
- http://stackoverflow.com/questions/3183931/how-do-i-invoke-updatemodel-from-within-a-custom-modelbinder-mvc
- http://stackoverflow.com/questions/3774287/asp-net-mvc-controller-updatemodel-not-updating
- http://stackoverflow.com/questions/1550520/best-practices-when-implementing-imodelbinder
- http://odetocode.com/blogs/scott/archive/2009/04/27/6-tips-for-asp-net-mvc-model-binding.aspx (check out tip #3)
- http://lostechies.com/jimmybogard/2009/03/18/a-better-model-binder/
- http://www.dalsoft.co.uk/blog/index.php/2010/05/21/mvc-model-binders/
- http://lostechies.com/jimmybogard/2013/07/17/how-we-do-mvc-4-years-later/ and http://stackoverflow.com/questions/7099587/mvc3-should-i-design-my-model-to-be-tightly-coupled-to-my-view (on ‘1:1 ratio between view model classes and view’ concept)
- http://www.codeproject.com/Articles/471784/Exploiting-Microsoft-MVC-vulnerabilities-using-OWA
From this blog
- Exploiting Microsoft MVC vulnerabilities using OWASP O2 Platform
- Why ASP.NET MVC is 'insecure by design' , just like Spring MVC (and why SAST can help)
- ASP.NET MVC – XSS and AutoBind Vulns in MVC Example app (from 2008)
- Current O2 support for analyzing Spring MVC
- "Two Security Vulnerabilities in the Spring Framework’s MVC" pdf (from 2008)