Archive for the 'Application Security' Category

Mar 19 2009

When ASP.NET EventValidation Doesn’t Work

Published by Brian Holyfield under Application Security

As a developer or security tester, it is important to know how built-in security mechanisms like EventValidation work. Starting with version 2.0 of the .NET Framework, Microsoft introduced the concept of “EventValidation” for validating PostBack data. The principal behind EventValidation is fairly simple — if the framework sees certain values within a PostBack that it doesn’t know about, it throws an exception. The official explanation from MSDN is included below:

The event validation mechanism reduces the risk of unauthorized postback requests and callbacks. When the EnableEventValidation property is set to true, ASP.NET allows only the events that can be raised by the control during a postback request or callback.

– MSDN

From a security point of view, this sounds like a great feature. EventValidation actually does go a long way in protecting many non-editable application inputs (such as drop-down lists, etc) from parameter manipulation attacks.

Unfortunately there is very little documentation on how EventValidation works underneath the hood (you can find one attempt at an explanation here). One thing I have noticed is that there are some inconsistencies in how EventValidation gets enforced. Specifically, there are certain scenarios that seemingly *should* result in a validation exception but do not. Let’s look at a few…

The First Scenario

In the first scenario, we have an account maintenance page that allows users to view and potentially update their account information. Updates are submitted by pressing the “Update” image button on the account maintenance page. This button is a standard ASP.NET ImageButton control as shown by the code below:

<asp:ImageButton ID="ImageButton1" runat="server" OnClick="ImageButton1_Click" ImageUrl="/images/UpdateProfile.gif" />

As you can see, the image button triggers the ImageButton1_Click method within the codebehind when clicked, which will process the update. Based on application business rules, users within certain groups are not permitted to update their profile. As such, the developer took the following route to disable this feature:

if (HttpContext.Current.User.IsInRole("GUEST"))

{

  ImageButton1.Enabled = false;

  ImageButton1.ImageUrl = "/images/UpdateProfileDisabled.gif";

}

As you can see, if the user is in the “Guest” role, the button will be disabled and a grayed out image button will be displayed instead. For reference, the HTML generated by this code is shown below:

<input type="image" name="ImageButton1" id="Image1" disabled="disabled" src="/images/UpdateProfile.gif"/>

At this point, some of you are undoubtedly thinking about a possible attack here. The ImageButton control is disabled, but if the logic within the associated OnClick method (ImageButton1_Click) doesn’t perform the same role check, then the user can still submit a request to update their profile by forcing the request (even though the button has been disabled). Those of you familiar with how HTML works know that simply removing the disabled=”disabled” portion of the HTML INPUT tag shown above will enable the button within the browser. Once the enabled button is clicked, the ImageButton1_Click method will be invoked.

This is clearly bad coding on the part of the developer, however that is not the interesting part here. Based on the concept behind EventValidation, you would think that this scenario should throw an exception. In fact, if the control were a LinkButton instead of an ImageButton, a validation exception would be thrown. So why doesn’t EventValidation catch this? I’m not 100% certain but my guess is that it’s because a LinkButton controls use the EventTarget parameter to pass in the “clicked” control name whereas with an ImageButton, the actual control name is passed as the name of an input parameter (along with its .x and .y coordinates) and the EventTarget is left blank.

Another Scenario

Now let’s look at another scenario. This time the page uses the OnTextChanged event of a TextBox control to determine whether the value was modified and, if so, will update the database with the new value. As you can see from the excerpt below, the TBUserName_TextChanged method will be called when the TextBox value is changed.

<asp:TextBox ID="TBUserName" runat="server" OnTextChanged="TBUserName_TextChanged" />

Like the previous scenario, the developer uses a similar technique to prevent users outside of the “Administrators” role from updating their user name. If the user is not in the “Admins” role, the text box will be disabled within the browser so that the user will not be permitted to update the value.

if (!HttpContext.Current.User.IsInRole("ADMINS"))

{

  TBUserName.Enabled = false;

}

Once again, the method associated with the OnTextChanged event (TBUserName_TextChanged) needs to also perform the same role check to prevent a malicious user from bypassing the “disabled” HTML attribute. This is another scenario where EventValidation should seemingly prevent such an attack from working since the control is not enabled, however it doesn’t.

Other Notable Points

Both of the scenarios outlined here will not be exploitable if the controls have their respective .Visible attributes set to false. Forcing a request that uses a non-visible control (one where .Visible is explicitly set to “false”) will generally always trigger an EventValidation exception. However, as you can see from the above two examples this is not always the case when only the .Enabled attribute is set to false.

A few other points of interest that I noticed with respect to the above scenarios:

  • EventValidation DOES prevent users from submitting a LinkButton button when .Enabled is set to “false”
  • The OnTextChanged event will not be raised when the .ReadOnly attribute on a TextBox control is set to “false”

So to summarize, Event Validation is a great feature of ASP.NET that can potentially thwart exploits where the developer may be incidentally relying on client-side controls (like the Browser) to prevent users from performing certain actions. Unfortunately, however, there is some inconsistency on how controls are treated when they are “Disabled” rather than not “Visible”.

The funny part is that based on the terminology alone, when asked if it is generally more secure to “Disable” something versus make it “Not Visible”, almost all security folks would recommend disabling. Ironic isn’t it?

One response so far

Mar 17 2009

Source Boston IIS7 Slides Posted

Published by Brian Holyfield under Application Security, Tools

My slides from the Source Boston conference last week have been posted for public consumption. The talk discussed some of the cool new built-in features of IIS7, like the Integrated Request Pipeline and Request Filtering. Additionally, it covered the new modular architecture of IIS7 and discussed custom modules (like SPF) and various other new add-on modules that the Microsoft IIS team has released for free.

Those of you not familiar with various extensions that the IIS team has released over the past several months should check out IIS.NET. My two favorites are the URL Rewriter for IIS7 (think mod_rewrite for IIS) and Dynamic IP Restrictions Extension, an add-on that dynamically blocks IP addresses that violate connection threshold and timing limits (great for slowing down CGI and App Scans).

Overall, the conference was great…hats off to Stacy and the crew for a job well done. They will be posting videos of the talks on the Source Conference site over the next few weeks, so certainly worth keeping an eye out.

No responses yet

Feb 05 2009

.NET StockTrader from MSDN: The new WebGoat?

Published by Brian Holyfield under Application Security

As an application security consultant, I always like to have a vulnerable sample application handy for demonstrating web application attacks to clients. The irony is that other than contrived vulnerable sample applications, like FoundStone’s Hacme Applications or OWASP WebGoat, good vulnerable demo applications are actually hard to find.

Luckily the folks at Microsoft recently developed a new sample application, .NET StockTrader, that fills this gap nicely. The best thing about .NET StockTrader is that it was not intentionally designed to be an insecure application. It is worth mentioning that the primary purpose of the .NET StockTrader application is to showcase the performance and interoperability of .NET Enterprise Application Server technologies like Windows Communication Foundation (WCF) and NOT a model for web application security. That being said, for Microsoft to publish a sample application of any kind that has such obvious security bugs is interesting and would seem to be an oversight.

For those interested in seeing a live demo of the application, you can find a live instance of .NET StockTrader on one of our GDS Demo Sites. The items below just scratch the surface of this application as they were all quickly identified within about 10 minutes of playing around with the application. While there are surely more issues to be found, here are some highlights:

Failure to Restrict Authenticated URLs

Not surprisingly, the .NET StockTrader application uses ASP.NET Forms Authentication for restricting access to protected pages. Unfortunately, only the pages directly linked from the main navigation bar have been defined as protected resources within the web.config. What does this mean? Well, pages such as /PortfolioBySymbol.aspx (used to display your portfolio holdings) can be directly browsed without providing proper authentication credentials. You’ll notice that a NullReferenceException gets thrown when accessing this page anonymously. This is not by design, but due to the fact that the page attempts to read the ASP.NET forms authentication cookie and it’s missing. Luckily the NullReferenceException saves the day here, but still a very sloppy configuration error (not to mention a code-level failure to anticipate and safely handle scenarios where the ASP.NET Forms Authentication cookie is empty).

Password Disclosure

This issue highlights two major problems with the application. As an authenticated user, try browsing to the Account Profile page. Aside from the normal account profile data one would expect to find here, something will probably jump out at you (at least if you are a security person). There are two form fields, appropriately marked “Password” and “Confirm Password”, which are pre-populated. The problem here is that the actual user’s password is rendered back within two form fields. Even though the browser masks the values from plain-sight, they can easily be revealed by viewing the HTML source (aka Right-Click -> View Source). As I hinted at before, there are actually two issues here. The second problem is that these passwords are actually stored in plain-text within the back-end database table used for storing profile data. As you can see, things are starting to get ugly.

Cross-Site Request Forgery

The next issue is a classic Cross-Site Request Forgery (aka a one-click attack). These attacks are certainly common, but this one is especially ugly as you will see in a moment. Keep in mind that the premise for this sample application is an on-line stock trading web application, like eTrade. Unfortunately, the page used to execute all BUY and SELL transactions passes all of its parameter via a single GET request similar to the following:

/Order.aspx?action=buy&symbol=s:0&quantity=122

The reason this is especially dangerous is that it can even be exploited through a malicious IMG or other HTML tag as shown below, so forcing a POST request is not necessary for exploit:

<IMG SRC="/Order.aspx?action=buy&symbol=s:0&quantity=122" HEIGHT="0" WIDTH="0" />

FormsAuthenticationToken Manipulation

Now this one is arguably the worst of the lot. As I mentioned towards the beginning of the post, the .NET StockTrader application uses ASP.NET forms authentication. What I didn’t mention was that the Authentication section of the web.config actually has cookie protection disabled (aka protection=”None”). As you can imagine, this makes it trivial for anyone to decode the ASP.NET Forms Authentication Token and manipulate its contents to impersonate any, yes any, user. Ironically this is one of those issues that does not immediately jump out at you if just viewing the cookie since the Forms Authentication Token is always HEX encoded irrespective of the protection setting . Let’s take a look at an example:

signinform=BC970F782904ECCF027500690064003A0039000000316F04304A80C90100318975484C80C90100002F000000

The one thing that does jump out is the unusually short length of the encoded string and the abundance of NULL (00) values. Run this string through a HEX decoder and you can quickly see the wheels come off (Hint: 75 69 64 3A 39 == U I D : 9)

Arbitrary URL Redirection

Last but not least, I’ll point out a less severe but equally interesting URL that caught my eye when browsing the application:

/StockTrade.aspx?action=sell&return=Portfolio.aspx&holdingid=5434

Any time you see a URL or file name being passed to the application there is usually something fishy going on. As it turns out, the “return” query string value on this page is directly assigned to the .PostBackUrl property of a LinkButton control on the page. The result is an arbitrary URL redirection exploit when the user clicks the link button. Ironically this bug is also dangerously close to being a Cross-Site Scripting (XSS) bug, however there appears to be some built-in escaping taking place thanks to the .NET framework (although I am sure with some further testing this could be turned into an exploitable XSS bug).

So What?

I think we all would agree that the insecure code examples and sloppy configuration settings highlighted above are pretty common and easily fixed, however that’s no excuse for Microsoft publishing a sample application riddled with flaws (even if it isn’t intended to be a showcase for application security). As many of us know, developers often rely on sample code and reference applications like the ones published on MSDN when writing code, so mistakes like these could easily make their way into a real-world scenario. Pretty scary.

Ironically, ALL of these issues can be mitigated with Secure Parameter Filter (SPF) for IIS, which can be seen live in action protecting the same sample application at http://trade-spf.gdsdemo.com. Also, for those interested in continuing the bug hunt, the .NET StockTrader sample application can be downloaded for free from MSDN.

2 responses so far

Next »