Article ID: 2915218 - View products that this article applies to.
What is view state?View state is information that is round-tripped between WebForms (.aspx) pages in an ASP.NET application. The HTML markup for the __VIEWSTATE field resembles the following:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="..." />
One example of an item that might be stored in the __VIEWSTATE field is the text of a Button control. If a user clicks the button, the Button_Click event handler will be able to extract the Button's text from the view state field. See the ASP.NET View State Overview
(http://msdn.microsoft.com/en-us/library/bb386448(v=vs.100).aspx)topic on the Microsoft Developer Network (MSDN) website for a much more detailed overview of the ASP.NET view state.
Because the __VIEWSTATE field contains important information that is used to reconstruct the page on postback, make sure that an attacker cannot to tamper with this field. If an attacker submitted a malicious __VIEWSTATE payload, the attacker could potentially trick the application into performing an action that it otherwise would not have performed.
To prevent this kind of tampering attack, the __VIEWSTATE field is protected by a message authentication code (MAC). ASP.NET validates the MAC that is submitted together with the __VIEWSTATE payload when a postback occurs. The key that is used to calculate the MAC is specified in the application's <machineKey> element
(http://msdn.microsoft.com/en-us/library/system.web.configuration.machinekeysection.aspx)in the Web.config file. Because the attacker cannot guess the contents of the <machineKey> element, the attacker cannot provide a valid MAC if the attacker tries to tamper with the __VIEWSTATE payload. ASP.NET will detect that a valid MAC hasn't been provided, and ASP.NET will reject the malicious request.
What causes MAC validation errors?A MAC validation error will resemble the following example:
Server Error in '/' Application.
Validation of viewstate MAC failed. If this application is hosted by a web farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Web.HttpException: Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
Source Error: [No relevant source lines]
Source File: ... Line: 0
[ViewStateException: Invalid viewstate.
Client IP: ::1
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
[HttpException (0x80004005): Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
See http://go.microsoft.com/fwlink/?LinkID=314055 for more information.]
System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError) +190
System.Web.UI.ViewStateException.ThrowMacValidationError(Exception inner, String persistedState) +46
System.Web.UI.ObjectStateFormatter.Deserialize(String inputString, Purpose purpose) +861
System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter2.Deserialize(String serializedState, Purpose purpose) +51
System.Web.UI.Util.DeserializeWithAssert(IStateFormatter2 formatter, String serializedState, Purpose purpose) +67
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +7959
System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +429
System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +48
System.Web.UI.Page.ProcessRequest(HttpContext context) +234
ASP.mypage_aspx.ProcessRequest(HttpContext context) in ...:0
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +140
Cause 1: The web application is running in a farm (multi-server environment)ASP.NET automatically generates a cryptographic key for each application and stores the key in the HKCU registry hive. This auto-generated key is used if there is no explicit <machineKey> element in the application’s configuration. However, because this auto-generated key is local to the computer that created the key, this scenario causes a problem for applications that run in a farm. Each server in the farm will generate its own local key, and none of the servers in the farm will agree on which key to use. The result is that, if one server generates a __VIEWSTATE payload that a different server consumes, the consumer will experience a MAC validation failure.
Cause 2: The worker process uses the IIS 7.0 application pool identityInternet Information Services (IIS) 7.0 (Windows Vista, Windows Server 2008) introduced application pool identity
(http://www.iis.net/learn/manage/configuring-security/application-pool-identities), a new isolation mechanism that helps provide increased security for servers that run ASP.NET applications. However, sites that are running under the application pool identity do not have access to the HKCU registry. This is where the ASP.NET runtime stores its auto-generated <machineKey> keys. The result is that ASP.NET cannot persist the auto-generated key when the application pool is reset. Therefore, every time w3wp.exe is reset, a new temporary key is generated.
Note This is not an issue in IIS 7.5 (Windows 7, Windows Server 2008 R2) and later versions. On these versions of IIS, ASP.NET can persist its auto-generated keys in a different location that survives application pool resets.
Cause 3: The application pool is configured by using LoadUserProfile=falseIf the application pool is running with a custom identity, IIS may not have loaded the user profile for the identity. This has the side effect of making the HKCU registry unavailable for ASP.NET to persist the auto-generated <machineKey>. Therefore, a new auto-generated key will be created every time that the application restarts. See the User Profile
(http://www.iis.net/learn/manage/configuring-security/application-pool-identities)section on the Microsoft website for more information.
Cause 4: The Page.ViewStateUserKey property has an incorrect valueSoftware developers can decide to use the Page.ViewStateUserKey property to add cross-site request forgery protection to the __VIEWSTATE field. If you use the Page.ViewStateUserKey property, it is typically set to a value such as the current user’s username or the user's session identifier. The project templates for WebForms applications in Microsoft Visual Studio 2012 and later versions contain samples that use this property. See the Page.ViewStateUserKey Property
(http://msdn.microsoft.com/en-us/library/system.web.ui.page.viewstateuserkey.aspx)topic on the Microsoft Developer Network (MSDN) website for more information.
If the ViewStateUserKey property is specified, its value is burned into __VIEWSTATE at generation time. When the __VIEWSTATE field is consumed, the server checks the current Page's ViewStateUserKey property and validates it against the value that was used to generate the __VIEWSTATE field. If the values do not match, the request is rejected as potentially malicious.
An example of a ViewStateUserKey-related failure would be a client who has two tabs open in the browser. The client is logged in as User A, and in the first tab, a Page is rendered with a __VIEWSTATE whose ViewStateUserKey property contains "User A." In the second tab, the client logs out and then logs back in as User B. The client goes back to the first tab and submits the form. The ViewStateUserKey property might contain "User B" (because that is what the client's authentication cookie says). However, the __VIEWSTATE field that the client submitted contains "User A." This mismatch causes the failure.
Appendix A: How to generate a <machineKey> element
There are many web sites that will generate a <machineKey> element for you with the click of a button. Never use a <machineKey> element that you obtained from one of these sites. It is impossible to know whether these keys were created securely or if they are being recorded to a secret database. You should only ever use <machineKey> configuration elements that you created yourself.
To generate a <machineKey> element yourself, you can use the following Windows PowerShell
For ASP.NET 4.0 applications, you can just call Generate-MachineKey without parameters to generate a <machineKey> element as follows:
ASP.NET 2.0 and 3.5 applications do not support HMACSHA256. Instead, you can specify SHA1 to generate a compatible <machineKey> element as follows:
As soon as you have a <machineKey> element, you can put it in the Web.config file. The <machineKey> element is only valid in the Web.config file at the root of your application and is not valid at the subfolder level.
For a full list of supported algorithms, run help Generate-MachineKey from the Windows PowerShell prompt.
Appendix B: Provisioning the registry to persist auto-generated keysBy default, because ASP.NETs auto-generated keys are persisted in the HKCU registry, these keys may be lost if the user profile hasn’t been loaded into the IIS worker process and then the application pool recycles. This scenario could affect shared hosting providers that are running application pools as standard Windows user accounts.
To work around this situation, ASP.NET enables persisting the auto-generated keys in the HKLM registry instead of the HKCU registry. This is typically performed by using the aspnet_regiis utility (see instructions in the "Resolution 2a: Use the aspnet_regiis utility" section). However, for administrators who do not want to run this utility, the following Windows PowerShell
(http://technet.microsoft.com/en-us/library/hh847837.aspx)script may be used instead:
The following example shows how to provision the appropriate HKLM registry entries for an application pool that runs as the user, firstname.lastname@example.org (this is the UPN of the Windows user account). This application pool is a 32-bit application pool that is running the CLR v2.0 (ASP.NET 2.0 or 3.5).
If the application pool instead is a 64-bit application pool that is running CLR v4.0 (ASP.NET 4.0 or 4.5), the command is as follows:
Even though the auto-generated keys are stored in HKLM, the registry subkey that holds each user account’s secret cryptographic material is added to an access control list (ACL) so that the cryptographic material cannot be read by other user accounts.
Appendix C: Encrypting the <machineKey> element in configuration filesServer administrators may not want highly sensitive information such as the <machineKey> key material to bein plaintext form in configuration files. If this is the case, administrators may decide to take advantage of a .NET Framework feature known as "protected configuration." This feature lets you encrypt certain sections of the .config files. If the contents of these configuration files are ever disclosed, these sections' contents will still remain secret.
You can find a brief overview of protected configuration
(http://msdn.microsoft.com/en-us/library/hh8x3tas(v=vs.100).aspx)on the MSDN website. It also contains a tutorial about how to protect the <connectionStrings> and <machineKey> elements of the Web.config file.
Article ID: 2915218 - Last Review: June 20, 2014 - Revision: 2.0