Storing Passwords in ASP.NET Viewstate


Web is inherently stateless since the HTTP protocol is stateless. The Web server treats every HTTP page request as an independent request.

Download HTTP Debugger



Copyright Notice: No part of this article may be reproduced, translated, stored in a retrieval system, or transmitted in any form or by any means without prior written permission from the HTTPDebugger.com

Read more articles    |    Send your feedback about this article

o to another page. Developers' skills are used to maintain the state of all or a portion of a Web page. In the past, cookies or the query string were often used to achieve this goal. A development platform like ASP.NET provides other ways to maintain state. One such method is storing information such as passwords in view state. This methods solves the problem of preserving the state but it's a double edged sword, storing information like passwords in view state is not secure. In this article we would discuss how view state stores passwords, how its unsafe and how we can solve this problem.

First we would try to understand what view state is and when/how it stores information. ViewState does not hold the controls, rather it holds the values of the form controls and their corresponding ID's that would otherwise be lost due to a post back because they do not post with the form. ViewState is not used to hold session data or to transmit data between pages. ViewState does not recreate the dynamically created controls of a page. It does not restore the values to the controls after a post back operation. Taken aback? Yes, it is true. Even when the ViewState for a control is disabled, still the value would be retained after a post back of the page occurs, for input controls like TextBox or DropDownList. So then, what is ViewState? ViewState represents the state of a page when it was last processed on the web server. It holds the values of a control that has been dynamically changed. All server controls have a property called ViewState. If this is enabled, the ViewState for the control is also enabled. Where and how is ViewState stored? When the page is first created all controls are serialized to the ViewState, which is rendered as a hidden form field named ViewState. This hidden field corresponds to the server side object known as the ViewState. ViewState for a page is stored as key-value pairs using the System.Web.UI.StateBag object. When a post back occurs, the page de-serializes the ViewState and recreates all controls. The ViewState for the controls in a page is stored as Base64 encoded strings in name - value pairs. When a page is reloaded two methods pertaining to ViewState are called, namely the LoadViewState method and SaveViewState method. The following is the content of the ViewState hidden field as generated for a page in my system.

By default, all pages have view state enabled. The actual data is stored in a hidden field on the form - take a look at a page's source, and you'll quickly find the field hosting the data. The data is not encrypted, so it does present security risks; however, it is Base64 encoded, which doesn't make it easily read by the naked eye.

Like session state, view state may be disabled on the page level via the EnableViewState attribute of the page directive. Likewise, most individual controls have the same property available. It may be disabled for the entire site in the web.config file.

Like the other state objects, the Dictionary approach is used, as the following C# snippet demonstrates:

ViewState["CurrentCount"] = 2;

This entry is maintained for the life of the page; it is gone when the page is no longer loaded. The size of the hidden field used to maintain view state can become large, so disable it whenever it is not needed.

Problems With Viewstate

ViewState has lots of advantages and as well as disadvantages, so you need to weigh carefully before making the decision to use it. As I told you early, view state doesn't require any server resources for its operation. It is passed to the client during every postback as an hidden element. Since it is added with every page, it adds few Kbytes to the page. This effects the loading of the page in the client. Other main problem with ViewState is, since it is passed as plain text to the client. Anybody can tamper this value, because of this you shouldn't store any important data in the ViewState.

Solution

To reduce the chance of someone intercepting the information stored in the ViewState, it is good design to encrypt the ViewState. You could do this in previous releases of ASP.NET, but the support for encryption has been improved in ASP.NET 2.0, allowing you to set this on a page-by-page basis.

In the previous release of ASP.NET, the page developer could turn encryption on and off at the application level through a web.config setting. When validation was set to 3DES, ViewState was encrypted before being rendered in the page.

<configuration>
  <system.web>
      <machineKey validation="3DES" />
  </system.web>
</configuration>

In ASP.NET 2.0 the support for controlling and utilizing encryption has been expanded. Encryption settings can now be controlled separately for each page. In addition, the controls on the page can request that encryption be used for the ViewState, but even this request can be overridden by the page setting. The 'ViewStateEncryptionMode' enumeration has three values: 'Auto', 'Always', and 'Never'. The default value is 'Auto'.

ViewStateEncryptionMode.Auto
In this mode, ASP.NET will encrypt the ViewState for a page if any control on the page requests it. Note that this means all of the ViewState is encrypted, not just the ViewState for the control that requests it. A large part of the performance cost associated with encryption is in the overhead. So encrypting the whole ViewState is faster than doing separate encryption operations if more than one control makes the request.

ViewStateEncryptionMode.Never
As you would expect, in this mode ASP.NET will not encrypt the ViewState, even if the application is set for encryption and controls on the page have requested it. If you know that no data involved in the page needs to be encrypted, then it may be safe to set the mode to Never. However, at this point it is rare for the documentation about a control to disclose what is being saved in ViewState, so you will want to be careful if there is a chance that sensitive data could be exposed.

ViewStateEncryptionMode.Always
In this mode, ASP.NET does not wait for a control in the page to request encryption. ViewState is always encrypted. When working with sensitive data, it is a good practice to utilize encryption.

The mode is a property on page, but is set using either a page directive or in the web.config file for the application.

<%@Page ViewStateEncryptionMode="Always" %>

Or

<configuration>
  <system.web>
      <pages ViewStateEncryptionMode="Always" />
    </system.web>
</configuration>

It is simple for someone writing a custom control to request ViewState encryption. The name of the Page method to call is RegisterRequiresViewStateEncryption.

protected override void OnInit(EventArgs e) {
  base.OnInit(e);
  if(Page != null) {
    Page.RegisterRequiresViewStateEncryption();
  } }

Control developers should be aware of the overhead and potential perf implications of using encryption, and should not take the decision to request encryption lightly. Notice that we refer to it as a request, even though the API name sounds like it is a mandate. If the control developers somehow know that the data being stored in ViewState must be encrypted, they could add code to throw an exception in the case that the page developer turns encryption off.

protected override void SaveViewState() {
  if(Page != null) {
    if(Page.ViewStateEncryptionMode == ViewStateEncryptionMode.Never) {
      throw new Exception("ViewStateEncryptionMode.Never not allowed when using the SensitiveDataList control.");
    }
  }
}

Download HTTP Debugger



Copyright Notice: No part of this article may be reproduced, translated, stored in a retrieval system, or transmitted in any form or by any means without prior written permission from the HTTPDebugger.com

Read more articles    |    Send your feedback about this article