Download the code for this article: CuttingEdge0302.exe (39KB)
I n ASP.NET pages, the view state represents the state of the page when it was last processed on the server. It''''s used to build a call context and retain values across two successive requests for the same page. By default, the state is persisted on the client using a hidden field added to the page and is restored on the server before the page request is processed. The view state travels back and forth with the page itself, but does not represent or contain any information that''''s relevant to client-side page display. In this column, I''''ll take a tour of the view state implementation in ASP.NET and show how to keep your Web pages fit and trim and a bit more secure.
View State Pros and Cons View state has pros and cons that you might want to weigh carefully before making a decision to use it. First, view state does not require any server state resources and is simple to implement. View state, though, does require computational effort on the server and the cost of sending the extra data over the wire. Since it''''s a physical part of the page, it''''s fast to retrieve and use; for this same reason, though, it can become a weakness that can be exploited. Because the view state is packed with the page, it inevitably adds a few extra kilobytes of data to the payload. A complex, real-world page—especially one that does not optimize and restrict the use of the view state—can easily find 10KB of extra stuff packed in the HTML code sent to the browser. Because it''''s composed of plain text, the view state could be tampered with. Although programmers are not supposed to store sensitive data in the view state (credit card numbers, passwords, or connection strings, for example), it goes without saying that the view state can be used to carry out attacks on the server. View state is not a security hole per se, but just like query strings and other hidden fields you may have used in the past, it''''s a potential vehicle for malicious code. Since the view state is encoded, protected, and validated, it does provide more security features than other hidden fields that you may use for your own programming purposes. View state is one of the most important features of ASP.NET, not so much because of its technical relevance, but more because it makes the magic of the Web Forms model possible. However, if used carelessly, view state can easily become a burden.
The StateBag Class StateBag implements the view state and manages the information that ASP.NET pages and embedded controls persist across successive posts of the same page instance. The class works like a dictionary object and implements the IStateManager interface. The Page and the Control base classes expose the view state through the ViewState property. So you can add or remove items from StateBag as you would with any dictionary object:
ViewState["FontSize"] = value;
You should start writing to the view state only after the Init event is fired for a page request. You can read from the view state during any stage of the page lifecycle, but not after the page enters rendering mode—that is, after the PreRender event is fired. Figure 1 lists the properties and the methods defined for StateBag. Each item in the StateBag class is represented by a StateItem object. An instance of the object is implicitly created when you set the Item indexer property with a value or when you call the Add method. Items added to the StateBag object are tracked until the view state is saved to the storage medium using the page''''s SaveViewState method. If a state item hasn''''t been saved, IsDirty property will be True. The IsItemDirty method represents an indirect way to call into the IsDirty method of a StateItem object. The contents of the StateBag collection are first serialized to a string, then Base64 encoded, and finally assigned to a hidden field in the page that is served to the client. The view state for the page is a cumulative property that results from the contents of the ViewState property of the page plus the view state of all the controls hosted in the page.
Security Issues Architecturally speaking, the importance of the view state cannot be denied since it is key to setting up the automatic state management feature of ASP.NET. A couple of hot issues surround its use, however. Most of the frequently asked questions about it are related to security and performance. Let''''s tackle security first. Many developers are hesitant to use view state because it''''s stored in a hidden field and left on the client where it has the potential for compromise. As Figure 2 shows, the information can be read by viewing the source of the page. While this action alone is not a threat to the application, having the view state on the client is a potential security issue because it is information that all ASP.NET pages contain and transmit to the Web server for processing.
Figure 2 ViewState is Visible in Source
Although freely accessible in a hidden field called __VIEWSTATE, the view state information is not clear text. By default, a machine-specific authentication code is calculated on the data and appended to the view state string. The resulting text is then Base64 encoded only, but not encrypted. If data confidentiality is desired, however, then SSL is the only solution since it protects not only view state, but all the data that travels to and from the page. Decoding view state is still possible, but a number of steps must be accomplished; not only must several undocumented and internal structures be disassembled, but a number of circumstances must also occur. In addition, consider that a tampered view state is normally detected on the server and a security exception is thrown. Finally, and most important of all, the view state contains data, not code. Unless you explicitly lessen the default security settings for the page, there''''s not much a hacker can do to modify the view state. If you change the default security settings, though, you should be careful about the view state. A hacker could modify the data that represents the state of the page. This is not a bug per se and opens holes for attacks only if the basic rules of data validation and data checking are not enforced. But this, you understand, is a more general problem when you''''re trying to write secure code. The view state internal implementation is quite complex and layered enough to discourage attacks. Encryption is the most important element in protecting view state information. In order to make the view state more secure, the ASP.NET @Page directive supports an attribute called EnableViewStateMac whose only purpose is detecting any possible attempt at corrupting original data. (The "Mac" in EnableViewStateMac stands for machine authentication check and, despite what some documentation claims, it is enabled by default.) When serialized, and if EnableViewStateMac is set to True, the view state is appended with a validator hash string based on the algorithm and the key defined in the <machineKey> section of the machine.config file. By default, the encryption algorithm is SHA1 and the encryption and decryption keys are auto-generated and stored in the Web server machine''''s Local Security Authority (LSA) subsystem. The LSA is a protected component of Windows NT®, Windows® 2000, and Windows XP. It provides security services and maintains information about all aspects of local security on a system. If EnableViewStateMac is True, then when the page posts back the encrypted view state is algorithmically checked to verify that it has not been tampered with on the client. The net effect is that you might be able to read the contents of the view state, but to replace it you need the encryption key, which is in the Web server''''s LSA. The EnableViewStateMac directive attribute corresponds to a protected page member with the same name. The EnableViewStateMac property defaults to True. The following excerpt comes from the source code that the ASP.NET runtime generates for a running .aspx page. (You can obtain it by adding the debug=true attribute to the @Page directive and searching for the source code in the temporary system folder of your ASP.NET application.)
If you''''re particularly concerned about attacks through the view state, simply make sure that EnableViewStateMac is on. You should look carefully at your own view state. If you maintain the default settings you should be OK. Later, after discussing performance issues, I''''ll return to security. At that time I''''ll discuss a possible alternative implementation of the view state that addresses both security concerns and bandwidth overhead.
Performance Issues Keeping the default view state settings is fine from a security perspective, but not in terms of performance. The view state can reach a considerable size, especia