11

From what I understand, "model binding" is where a website based on ASP.NET MVC or Ruby on Rails (there are others...) takes parameters in HTTP's GET statement and passes them as variables to code within the site.

Since GitHub (a popular FOSS site for programmers) was hacked through a model binding exploit, I'd like to know what general practices are needed to close this hole. Specifically

  • What is the model binding exploit?

  • Are all MVC frameworks affected?

  • Is this something the developer must address... or can a web proxy/filter correct this?

  • Is there any security tooling that assists in identifying or diagnosing this problem in a given site?

makerofthings7
  • 50,090
  • 54
  • 250
  • 536
  • Related: http://security.stackexchange.com/questions/21100/added-security-risks-that-come-with-3-tier-software-architecture – Polynomial Feb 06 '13 at 12:17

2 Answers2

5

Model Binding is quite a nice feature and may add a plus to the overall security if it is properly used.

Here is how it works (the code and the features apply to ASP.NET MVC but may be the same in Ruby): Suppose you have a form in a web page:

<form action="/SendData">

  Email: <input type="text" name="email" id="email"><br>
  Address:<input type="text" name="address" id="address"><br>

  <input type="submit" value="Submit">

</form>

You write a class like this:

class Contact{
   String Email{get;set;} 
   String Address{get;set;} 
}

With model binding the function that deals with the user request can be:

public ActionResult SendData(Contact contact){
        //do something with contact.Email and contact.Address
}

As you can see, model binding automatically puts the data it received in the HTML request in an object of the type Contact.

Furthermore, you can define validation functions, by using DataAnnotations.

class Contact{
   [Required(ErrorMessage="Input email please!")]
   [RegularExpression("^some_regex"),ErrorMessage ="Error"]
   String Email{get;set;} 
   [Required(ErrorMEssage="Input address please!")]
   String Address{get;set;} 
}

and check it like this:

public ActionResult SendData(Contact contact){
    if(ModelState.IsValid)
    {
        //do something with contact.Email and contact.Address
    }
}

As you can see, it easy to add validation and some common mistakes(like badly written SQL Queries may be avoided).

Now to explain the problem that lead to the GitHub hack (mass binding):

What happens if you have properties in your class that do not appear in the form:

<form action="/SendData">

  Email: <input type="text" name="email" id="email"><br>
  <input type="submit" value="Submit">

</form>

If an attacker also sends a variable with the name address, the framework will automatically bind it, without knowing that in the original form there was no such input.

In the GitHub case, the developers probably used an Object that had a property that differentiated between administrators and normal users(isAdmin for example). By sending this parameter in the login form (or another page), together with the user and password, the attacker could have gained access to administrative functionality.

There are several ways to solve this issue( blacklist binding, whitelist binding), but I recommend using Interfaces and Classes that only contain the properties from the form (or have the other attributed marked as read-only ).

Whitelist binding example:

public ActionResult SendData(
[Bind(Include="Email")]Contact contact)
{
    //...
}

Regarding the affected frameworks, probably most of them are affected (Ruby and ASP are), but this is not a vulnerability itself, it's only bad programming. As long as the programmers address this functionality properly, everything should be OK.

I don't think that an automated tool could detect this kind of problems, but a thorough code review should solve it.

Dinu
  • 3,166
  • 14
  • 25
  • Is it correct to call the class the "model class" or "viewmodel class", and it is this class that requires the careful matching of fields with the form as you describe? – makerofthings7 Feb 07 '13 at 04:09
  • Yes, that is correct , the binding is made to a model or a viewmodel. – Dinu Feb 07 '13 at 05:44
  • Seems like this security problem gets harder to find with a ORM or Entity Framework is involved. Based on [this article](http://www.diaryofaninja.com/blog/2012/03/11/what-aspnet-mvc-developers-can-learn-from-githubrsquos-security-woes) I think I'm seeing an ORM such as Linq2SQL or EF create hidden properties that the model binder can still bind to. – makerofthings7 Feb 08 '13 at 01:54
  • What kind of hidden properties are you referring to? I have read the article and I haven't seen such a mention. Even if what you are saying is happening, a whitelist approach would solve the problem. – Dinu Feb 08 '13 at 08:28
  • 1
    I misspoke when I said hidden. I was thinking about properties that are auto generated in an ORM model that the developer may "forget about"... namely the Foreign Key objects. It seems this FK object was part of the Github hack. You're right whitelisting should fix that. Wonder if SPROCs, Views, etc, could also be exploited. – makerofthings7 Feb 10 '13 at 15:52
  • This is an interesting topic, it should be further investigated. I'll try to check the behavior as soon as I have some spare time for it. – Dinu Feb 10 '13 at 17:48
1

As an update to Dinu's comments, the models in many PHP frameworks suffer from this same kind of thing. There's very few that offer "restricted properties" that cannot be set from the load. Most of them just assume you know what you're doing when you "load()" the values into them and assign the properties accordingly - again, sloppy coding practices.

Laravel 4 is one that I've seen that offers the restrictions to help prevent mass assignment issues.

enygma
  • 141
  • 3