Understand How the ASP.NET Cookieless Feature Works

 

Manu Vasandani
Development Lead, Web Platform & Tools

December 2005

Applies to:
   ASP.NET 2.0
   Cookieless feature

Summary: There are many reasons that cookies may not be provided to your ASP.NET application—the user may have disabled them, or the browser may not support their use. This article outlines how the Cookieless feature can still provide cookie-like support to those users. (4 printed pages)

Contents

Introduction
Which Features Use Cookieless in ASP.NET 2.0
Configuration Settings
Limitations
Security Concerns

Introduction

ASP.NET 2.0 introduces better support for devices that do not support cookies. This article attempts to demystify and explain in detail the inner working of how the ASP.NET core attempts to support cookies on such devices. Understanding how the system works is essential to grasp the (severe) limitations of this feature, and how to build Web applications that do not expose security holes through this feature. In a nutshell, this feature works in a fairly straightforward fashion: it takes the data that would normally go into the cookie, and stuffs it into the URL instead.

This article is structured in the following manner:

  1. First, we look at the features that provide "cookieless" support.
  2. Next, we look at the configuration settings that let you control this feature, and describe what the core engine does for each of these settings.
  3. Lastly, we go through the limitations of this feature and discuss the security concerns that you need to keep in mind when using this feature.

Which Features Use Cookieless in ASP.NET 2.0

In earlier versions of ASP.NET (V1.0 and V1.1), the Session State feature was the only one that used the Cookieless feature. In V1.1 (and V1.0), the URL would look something like this:

http://MySite.com/MyWebApplication/(XXXXXXXXXXX)/home.aspx
                        ^^^^^^^^^^^
               Session ID

In V2.0, Anonymous Identification and Forms Authentication also use this feature. The URL may now look like this:

http://MySite.com/MyWebApplication/(A(XXXX)S(XXXX)F(XXXX))/home.aspx

Breaking it down:

  1. A(XXXX): This is the Anonymous-ID. It is used to identify the (anonymous) user accessing your application. The string may or may-not be encrypted, depending on your configuration settings in the <anonymousIdentification> section.
  2. S(XXXX): This is the Session-ID (same as V1.1).
  3. F(XXXX): This is the Forms Authentication ticket.

Configuration Settings

For each of the above features (Forms Authentication, Anonymous Identification, and Session State), you can control if and when the cookiesless feature will be used, and when the cookieless feature will be used instead. The configuration setting controlling this is:

cookieless="UseCookies | UseUri | UseDeviceProfile | AutoDetect"
  1. "UseCookies": As this name implies, the cookieless feature will never be used.
  2. "UseUri": The cookieless feature will always be used.
  3. "UseDeviceProfile": Depending on the browser making the request, the cookieless feature may or may not be used. If ASP.NET recognizes that the browser does not support cookies, then the cookieless feature will be used. Technically speaking, the two Boolean variables Request.Browser.Cookies and Request.Browser.SupportsRedirectWithCookie must both be true for ASP.NET to assume that cookies are supported by the browser.
  4. "AutoDetect": In this setting, ASP.NET attempts to detect whether the browser supports cookies or not. The algorithm is a little complex, and I'll lay it out in pseudo code. (The algorithm is subject to change in future builds).
// Step 1: If the Browser configuration tells us definitively 
//         that cookies are not supported, then report that and
//         exit immediately
if (  !Request.Browser.Cookies ||       
      !Request.Browser.SupportsRedirectWithCookie)
   Report_cookies_are_NOT_supported_and_exit;
// Step 2: Check if we have already detected that Cookies are not 
//         supported. This is detected by looking for the string
//        "/(X(1))/" in the URL
If (URL-contains-"/(X(1))/")
   Report_cookies_are_NOT_supported_and_exit;
// Step 3: Check if client sent any (request) cookies
if (Request.Headers["Cookie"] is not null or empty)
   Report_cookies_are_supported_and_exit;
// Step 4: Check if this is a response to a challenge (sent in Step 5)
//         If this is a response to a challenge and no cookies were 
//         sent (Step 3), then cookies are not supported
If (Request.QueryString contains our AutoDetect challenge variable)
Begin
   Insert "/(X(1))/" into the URI
   Report_cookies_are_NOT_supported_and_exit;
End
// Step 5: We can't detect if cookies are supported or not. So, send a 
//         challenge to the client. We do this by sending a cookie, as
//         well as setting a query string variable, and then doing a 
//         redirect back to this page. On the next request, if cookie
//         comes back, then Step 3 will report that "cookies are 
//         supported". On the other hand, if the next request does not
//         have any cookies, then Step 4 will report "cookies not
//         supported".
SetAutoDetectionCookie();
Redirect(ThisPage + Our_auto_detect_challenge_variable);

Limitations

The principal limitation of this feature is the limited amount of data that can be stored in the URL. This feature is not targeted at common browsers such as IE, since these do support cookies and do not require this feature. The browsers that do not support cookies are the ones found on mobile devices (such as phones), and these browsers typically severely limit the size of the URL they support. So, be careful when you use this feature—try to make sure that the cookieless string generated by your application is small.

A second limitation on the size comes on the Windows 2003 platform. A (configurable) setting on the Windows Networking layer requires that each segment of the URL be less than 256 chars in length. Since the entire cookieless string goes into 1 segment, it must be less than 256 chars. (A segment of the URL is the portion of the URL between two forward slashes ('/')).

Security Concerns

Anytime you use cookies, there are several attacks you have to be aware of. These attacks also apply to storing this cookie data in the URL (that is, using this feature). One of the most important attacks is the "Cookie replay attack." With this type of attack, the attacker captures the user's authentication cookie using monitoring software and replays it to the application to gain access under a false identity. Countermeasures to prevent cookie replay include:

  • Use an encrypted communication channel provided by SSL whenever an authentication cookie is transmitted.
  • Use a cookie timeout to a value that forces authentication after a relatively short time interval. Although this doesn't prevent replay attacks, it reduces the time interval in which the attacker can replay a request without being forced to re-authenticate because the session has timed out.

One big issue that is unique to the cookieless feature (not present when using cookies), is the vulnerability linked to users sending URLs to other users (via Email and IM, for example). When this feature is turned on, for, say, FormsAuthentication, and the user emails his (or her) URL to some other user, the second user will automatically log on to the server with the credentials of the first user. One countermeasure is to reduce the time-window in which this can happen, by reducing the cookie timeout for forms authentication (as described previously in point (b)).

© Microsoft Corporation. All rights reserved.