Solved: “Validation of viewstate MAC failed”

You may come across this error message when you get around in pages of your ASP.NET website:

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.

Background

ASP.NET uses view-state variable to rebuild pages after post-backs. The text of your buttons and the value of the form fields are the examples that this variable stores.

In order to prevent tempering attacks that try to play around with view-state data to force your webpage behave unexpectedly, web server validates the view-state data between page redirections. If the data doesn’t match, you receive the error message above.

Solution

The issue of unmatched view-state data could be related to server configuration or session cookie. Here are the most common root causes:

  • Web server and application pool configuration related issues. Read details in this Microsoft Support article
  • If you are using ViewStateUserKey to prevent Cross-site Request Forgery (CSRF) attacks, make sure the value you assign to this variable is the same in all pages. The most common usage is that assigning session ID or username to ViewStateUserKey. Your website might be losing the session between page redirections. Check these two StackOverflow topics for details: Link 1link 2
  • Redirecting the page right after setting session variables may be the issue. You should avoid using Response.Redirect in this case. Details
  • Antivirus software might be causing the issue. Add scanning exceptions for IIS and your application’s folders. Details

How to Create a Report of Browser Versions from IIS Logs?

You may wonder what type of browsers your visitors have. The best way to collect this information is using an analytics service such as Google Analytics.

What if you don’t use any analytics service but still want to collect browser stats? Your only option is that digging into web server logs.  However, it’s not easy because web server logs provide user-agent data. It doesn’t provide direct browser information.

Here is how IIS logs look like:

How to Get Browser Info from IIS Data?

Follow these steps to convert raw IIS log to meaningful browser stats:

  1. Copy IIS logs to a folder (IIS logs are typically in C:\inetpub\logs\LogFiles)
  2. Install and run Log Parser Studio
  3. Click “Log” icon. Select the folder of your log files
  4. In “Library” tab, double click “IIS: User-Agent Report
  5. Click “Execute” icon (red exclamation mark). Now you have user-agent stats
  6. In order to map user-agent information to specific browser version, you can use one of these free parser tools: One, two, three
  7. Finally, use an Office product like Excel or an online service such as Canva to visualize your data

You will need to parse user-agent strings one by one.

Is there a way to parse all them at once?

Yes! Some of these parser tools provide API. You can develop a small application to query this API and parse a batch of user-agent strings at once.

How to remove server data from response headers of your ASP.NET application?

The less you give to hackers, the safer your web application is. Hiding the product, technology, and version information of your server is one big step towards narrowing the attack surface of your application.

By default, IIS server will reveal this data to everyone who has access to your application:

Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET

This data can be viewed by a proxy such as Fiddler.

Server details
Server details

You can remove these headers by add a few lines into web.config and Global.asax files. You don’t need to do any configuration changes in IIS if you are using IIS 7 or an upper version.
.

Remove “Server” header

Add this method into Global.asax:

protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
     HttpContext.Current.Response.Headers.Remove("Server");
}

Add this line into Application_Start in Global.asax:

PreSendRequestHeaders += Application_PreSendRequestHeaders;

.
Remove “X-AspNet-Version” header

Add this line into web.config:

<system.web>
     <httpRuntime enableVersionHeader="false" />
...
</system.web>

.
Remove “X-Powered-By” header

Add this line into web.config:

<system.webServer>
     <httpProtocol>
          <customHeaders>
               <remove name="X-Powered-By" />
           </customHeaders>
      </httpProtocol>
       ...
</system.webServer>

.
References