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 agood 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.
<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.
{
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.
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 |