Browse All Articles
> Why you shouldn't use Html.beginForm + UpdateModel on ASP.NET MVC
I've found this issue almost accidentally, however it seems so clear and logical to me that I'm surprised that there's no specific information on the matter (at least at first glance).
Is not unusual to see people using the beginForm helper on ASP.NET MVC applications, this is true to the point that the creation of a Create/Edit View on VS includes it on your code by default.
This helper just builds a <form> tag saving you some repetitive typing, it gets your current http petition and builds an action and a method for the form. To this point maybe there's nothing that triggers your alarms, however there is. The default method uses your current url, wich can be manipulated directly on the browser by the user, to build the action of the form; this way a malicious user can inject extra parameters on your server call.
Ok, what's the problem? My model classes and controller will deal only with those parameters I define, so...
Well, actually is highly possible that you're using one of the most popular utilities of MVC framework on your form controllers: UpdateModel. This method map the fields on your form action directly into your business model whenever it's possible. It's a huge advantage when dealing with complex and big data structures, as it saves a lot of repetitive coding, however, if your business model has a field that's not published through the form but comes on the HttPost, UpdateModel will recognize it and update the data.
Let's try to put it all together on an actual example:
Suppose you have an application where users can edit some of the data in their profile but cannot update some specific data unless they are have a higher role. Say, for example, that they cannot update their email address.
When you build the editing profile form, you build the restricted fields only if the user on session has the higher role.
Unfortunately, if your form is built with Html.beginForm(), a savvy user can alter the url of the form from something like http://yourApp/Profiles/Edit/
<ProfileId> to http://yourApp/Profiles/Edit/
On loading the altered url, if you look at the source code, you'll see that the generated form is:
l.com" method="post" />
Of course, when your form submits the email parameter will be caught by UpdateModel and included into your business model data update.
This example could seem fairly benign, however the exploit possibilities are far larger.
As an immediate fix I recommend to build <form> tags manually. They are critical enough that they should not be coded automatically. However maybe there are intermediate solutions to this. I have to do some research with beforeUpdate overloads and see if there are any that allows you a strict control of the action parameter.
I hope this brief article helps you to make your applications a bit more secure.