ASP.NET Event Validation and “Invalid Callback Or Postback Argument” : Part I

Tuesday, March 21, 2006

ASP.NET 2.0 added a feature called event validation. Event validation checks the incoming values in a POST to ensure the values are known, good values. If the runtime sees a value it doesn’t know about, it throws an exception.

Invalid postback or callback argument. Event validation is enabled using <pages enableeventvalidation="true" /> in configuration or <%@ page enableeventvalidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

The error message is a bit wierd and could use some editing, but if someone is trying to attack the application by spoofing a postback, the event validation exception is a good thing. Event validation can help prevent injection attacks from malicious users who are trying to POST data that doesn’t belong.

If we see this exception during the normal execution of an application, the exception is a bad thing. Let’s look at one scenario where the exception can occur after a legitimate postback, and talk about the implementation of event validation. A future post will discuss possible solutions.

Cause

Imagine we’ve been given the task of writing a web form with a DropDownList, and the DropDownList contains three selections.

<h3>Pick Your Favorite Recipe</h3>
<
asp:DropDownList runat="server" ID="_recipeList">
    <asp:ListItem Value="1">
        Amy's Wasabi Encrusted Tuna
    
</asp:ListItem>
    <asp:ListItem Value="2">
        Big Al's Five Bean Burrito
    
</asp:ListItem>
    <asp:ListItem Value="3">
        Scott's Chocolate Carmel Cheesecake Cookies
    
</asp:ListItem>
</
asp:DropDownList>  

Now, it’s a fairly common scenario for client script to populate the contents of a drop down based upon the value of some other control on the page. For example, a list of states may appear after the user selects a specific country. Let’s simulate that scenario by registering some JavaScript which adds a 4th option to the list.

protected void Page_Load(object sender, EventArgs e)
{
   ClientScript.RegisterStartupScript(
         GetType(),
        
"AddToList",
         script.Replace(
"{_recipeListID}", _recipeList.ClientID),
        
true
      );
}

string script =
  
@"      
     var d = document.getElementById('{_recipeListID}');
     d.options[3] = new Option('George\'s Recipe For Disaster', '4');
   "
;

As long as the user selects recipe 1, 2, or 3, the form will postback without errors. If the user selects option 4, George's Recipe For Disaster, the runtime throws an event validation exception. Disaster indeed!

When ASP.NET rendered the DropDownList it recorded all the possible postback values for the control, It does so by looping through the 3 available ListItems and recording each value. When I say “recorded”, I mean for each item in the list the runtime takes a hash of the control’s UniqueID property, and a hash of the ListItem’s Value property, and XORs the two hash values together. The result of this computation is kept in a list with other allowable hashed values, and the list persists itself as a hidden field in the page.

<input type="hidden"
       name="__EVENTVALIDATION"
       id="__EVENTVALIDATION"
       value="/wEWBQKGg9abDQKd9sHMBgKc9s........"
/>

If the user selects George's Recipe, the browser posts back with a value of “4” for the DropDownList. The runtime will perform the same calculation described earlier: hash(_recipieList.UniqueID XOR hash(“4”)). The runtime will try to find the result of this calculation in the list of allowable values de-serialized from the __EVENTVALIDATION field. The runtime won’t find this value, and will sound the alarm by throwing an exception.

To summarize: the runtime threw an exception because the browser posted a value of “4” for the DropDownList. The runtime thinks the only allowable values are “1”, “2”, and “3”. We added the value “4” as an option using client-side script, so ASP.NET did not know it was legal. ASP.NET calculates the allowable postback values at the last possible moment (inside the Render method of the control).

Just for reference, the following controls support event validation. I’ll provide details on how to know if a control validates events in the next post.

HtmlAnchor HtmlButton HtmlInputButton
HtmlInputCheckBox HtmlInputHidden HtmlInputImage
HtmlInputText HtmlInputPassword HtmlInputRadioButton
HtmlInputReset HtmlInputSubmit HtmlSelect
HtmlTextArea BulletedList Button
Calendar CheckBox Table
ChildTable WizardChildTable DataControlButton
ImageButton DataControlImageButton LinkButton
DataControlLinkButton DataControlPagerLinkButton DataGridLinkButton
DetailsView DropDownList FormView
GridView HiddenField ImageMap
LayoutTable ListBox Menu
PagerTable RadioButton RadioButtonList
TextBox TreeView WizardDefaultInnerTable
CatalogZone ConnectionsZone EditorZone
WebPartZone ZoneButton ZoneLinkButton

Comments
Rick Strahl Tuesday, March 21, 2006
Thanks for posting some insight on EventValidation. I've been meaning to do a little more research on what it actually does - you've done it for me.

I've found that this stuff really gets in the way if you're building AJAX applications and dynamically adding data to controls - especially lists.

While I can see the use of this option I think it really shouldn't be on by default because I doubt this is critical in most situations. The problem is that it's one of those problems you might not catch in typical testing and an error that you won't catch until runtime and JUST the right scenario...

scott Wednesday, March 22, 2006
Rick: I'm glad yoy liked the post. I guess this was part of the 'secure by default' mantra. I wish there was a way to turn off validation on a control by control basis - I think that would be a good tradeoff.
Phil Morris Thursday, April 13, 2006
I was wondering why, after recently migrating my website to VS 2005 this error was occuring on a couple of my webpages. But in both cases there is no javascript that modifies possible post back values. But I do have smartnavigation on, and I do allow the user to select options that change the page. In one case I build a table of information, and allow the user to apply filters so that the table contents change. In the second case I have a number of listboxes, the contents of which change based on user selections.

I'm going to set smartnavigation to false in both cases, and see if the error persists. I'd wager not, in which case there are obviously limitations on the use of smartnavigation.
Tim Bailey Sunday, April 23, 2006
Hi,

I am having a problem with this error, I (or any other developer at the company) has never seen it, but it our biggest bug. After doing some searching and general messing about I found that if I run a slowdown proxy (NetLimiter or similar) and simulate a dialup connection, I can make the error happen. It seems to be when you have a master page with some controls at the top, the page is loading slowly, the top controls are visible (login stuff) the user then enters their details before the rest of the page is complete and submits it. This means that the __EventValidation form field is not present and the exception occurs.

Any ideas on how to prevent this in this situation (our biggest error), I am reluctant to turn it off but I may have to...

TIA

Tim
Eric Golpe Monday, April 24, 2006
Once again Scott, a very valuable article. I took a base master page with 4 ContentPlaceHolders, and loaded a GridView in the cphMainPH, it populates the data, but on trying to sort or page the Grid, voila I get the invalid postback argument. I tried EnableEventValidation="false" in the @Pages of the content page, and now I get my FAVORITE .net 2.0 exception "Invalid inherit blah blah blah Page or UserControl"

This is why I love security "by design".
Weilin Wednesday, April 26, 2006
This error generates an unhandled exception and returns an unfriendly error message.

Is there any way to catch this exception in the page and continue the normal control flow without returning this message to the user?
scott Thursday, April 27, 2006
Weilin: You'll have to disable event validation for the page, I don't know of a way to process the exception.
绵羊.net Thursday, December 7, 2006
I didn't use any scripts in my page,but this error still occurs.How to deal with it
Wray Smallwood Wednesday, December 13, 2006
Here's code to fix it.

protected void Page_Render(object sender, EventArgs e)
{ Page.ClientScript.RegisterForEventValidation("your_control_that_causes_it");
}
JJ Thursday, January 11, 2007
Where is a link to Part II?
Shivanand Thursday, January 25, 2007
I m new to asp.net 2.0 and facing the eventvalidation problem. Ps tell me how to overcome this problem.
gravatar jimmy franks Wednesday, February 17, 2010
If you like to live dangerously, add
the "enableEventValidation" attribute to the <pages> elenmetn of web.config:

<pages enableEventValidation="false">
....
</pages>
Ranjith Tuesday, March 2, 2010
Very good Explanation. Thanks much
gravatar deepak Wednesday, August 25, 2010
Is there any way to disable validation for dropdownlist? i am having same problem as you described. i am changing the dropdown items at client side which is populated at server side on first request.
gravatar deepak Wednesday, August 25, 2010
i replaced dropdownlist with <select runat=server>, it worked!.. thanks
gravatar DnshPly9 Tuesday, November 30, 2010
That is such a good information.
Well Explained
Thanks
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!