Session Management Fundamentals

So far we have mentioned sessions and session management several times, without explicitly defining what those things are and what you’re supposed to do about them. Time to fix that. We’ll divvy the subject up into the what, why, and how of sessions and session management.

What’s a Session?

A session, in its broad theoretical sense, is simply a means for tracking a single user’s interactions with the web application. HTTP is a stateless protocol, which is fine for static web sites that don’t care who anybody is, but which doesn’t work for interactive web applications. A modern web application needs a mechanism for identifying the stream of requests generated by each individual user amid the requests from other users who are connected to the application at the same time. Sessions provide that, and are very much like the web equivalent of issuing an employee an RFID badge so they don’t have to sign in every time they need access to something.

In practice, a session is nothing more than some kind of persistent token that the user’s web client can present along with each request, as a way of asserting “Hey, it’s me. Remember me? I authenticated myself a little while ago.” Typically, this session token takes the form of a special value given to a designated cookie that the web application sets in the user’s web client. But as we’ve seen many times by now, you can’t trust anything stored on the client unless you’ve encrypted it first. Encrypted data is safe because it is opaque to human eyes, and indeed, even to the eyes of any other computer that doesn’t possess the appropriate decryption key. A secure session ID will therefore look like random data. Perhaps something like this:

image

Not much to look at, is it? Which is exactly the point. The harder you make it for an attacker to guess the value, the harder it is for them to impersonate an active session with your web application. An attacker is free to try guessing a legitimate session ID, but because the number of possible values is so large, the attacker’s chances of success are vanishingly small. Guessing is not impossible, but it does become an infeasible means of attack.

ImageNote

Cookie names and values are associated with the web site that issued them, so web application designers do not have to worry about cookie name clashes with other sites’ cookies. That is, www.WebsiteA.cxx and www.WebsiteB.cxx can both use a cookie named “SessionID” without interfering with one another’s values.

Many web applications issue a session ID at the time an unknown user performs the application’s authentication procedure, but some do so before authentication. There are times when this is sensible, or even necessary. For example, e-commerce sites often issue a session ID in order to track an anonymous user’s shopping cart, in order to let a person shop before authenticating. Of course, the user would still have to authenticate before completing the purchase.

In such cases, the web application should issue a new session ID when the user does finally authenticate; otherwise, you’re technically reusing the same session ID for two different user sessions: one for “guest,” and one for a known user. Never reuse a session ID. It also means that you are essentially letting the web client dictate to you the session ID value to use for a subsequent authenticated user session; that can potentially open you up to session fixation attacks (see the section “Session Fixation” later in this chapter).

If your application has no need to track user behavior prior to authentication, it is safer to defer generating and issuing session IDs until a user has successfully completed the authentication procedure. Regardless of when it happens, session IDs are issued to web clients in the form of a Set-Cookie header in the HTTP response.

What Is Session State?

Again, HTTP is a stateless protocol. Session IDs help enormously by at least allowing a web application to tell different users apart, but they don’t do the whole job. For many real-world scenarios, the application also needs to track various pieces of application-specific information on a per-user basis across a session. For example, online commerce sites make ubiquitous use of the “shopping cart” metaphor to keep track of what the user wants to buy, even as the user navigates around between web pages for different products. The contents of the shopping cart—the list of items the user has put into it, plus any quantity information, plus any coupon codes the user has entered, and so on—constitute session state.

Session state can persist across requests in many ways. Indeed, different web development frameworks have their own idiosyncratic mechanisms for handling this. Check the documentation for your framework to see if its state management facilities suit your needs. Some of the common state persistence strategies include:

image Cookies The contents of the shopping cart can be held in one or more client-side cookie values. Pros: Cookies are easy to implement. Cons: Cookies are wholly insecure, unless encrypted; they are limited to 4KB of data, which is sometimes not enough; they are transmitted with every request, even when not necessary for a particular request, which can cause performance issues.

image Form fields and URL query parameters Alternatively, the contents of the shopping cart could be persisted between requests as a set of hidden form fields, or could be encoded as URL parameters. Neither mechanism is secure, as malicious users can easily change these values before submitting subsequent requests. URL parameters also pose implementation challenges due to length. While the HTTP protocol does not define a maximum length for a URL, and a web application could theoretically encode as much data as necessary in such parameters, this strategy runs afoul of real-world URL length limits present in the implementations of many browsers, web servers, and web application frameworks.

image Web Storage Sometimes called “HTML5 Local Storage,” Web Storage is the proper name of the specification for a new storage model introduced with HTML5. It provides for local (that is, client-side) persistent storage facilities, designed mainly with the aim of overcoming the shortcomings of cookies. Web Storage is a client-side storage facility that provides for structured data (beyond key/value pairs), is persistent, is not automatically transmitted with every request, and in many ways functions like a client-side file system that the web application can read and write from. Web Storage is an improvement, but still cannot overcome the venerable cookie’s most glaring security issue: You can’t trust the client. Encryption is still required for secure use of Web Storage. For more information, check out http://dev.w3.org/html5/webstorage/.

image Flash Local Shared Objects (LSOs) LSOs are a feature of the Adobe Flash Player system. Much like cookies and Web Storage, LSOs provide a persistence model for Flash applications. The similarities are sufficient that LSOs are sometimes referred to as “Flash cookies,” and indeed, LSOs share many of the same security issues as ordinary cookies. You can read more about LSOs at the Adobe.com web site: http://www.adobe.com/products/flashplayer/articles/lso/.

image Silverlight Isolated Storage Microsoft’s Silverlight platform, which in many ways fills a software niche similar to that of Adobe Flash Player, has its own persistence mechanism called Isolated Storage. Isolated Storage is a robust and flexible mechanism for both client-side and server-side storage. Client-side storage, as with the other mechanisms explored here, should not be considered secure unless data is encrypted, and the Silverlight platform provides facilities for encrypting and digitally signing data stored in Isolated Storage.

image Server-side storage If none of the already mentioned session-state persistence strategies meet your needs, you can always rely on storing session state on the server, which is usually a reliably secure location. Most modern application server implementations and web development frameworks provide facilities for session state management. Look in the documentation for your application server or development framework for “session state” or “session attributes”; these are essentially name/value pairs associated with a user’s session ID. Because each user has a session ID, the ID makes a convenient primary index for looking up these name/value pairs. Other options for server-side storage involve back-end data stores such as databases, but this is less common today because it involves undertaking the design and engineering effort of building a state management system. Why do that when most modern frameworks already provide that functionality? Server-side storage is by far the most secure option for session state, as the state information itself is managed by the application residing on the server, which protects it from tampering attacks by the client. To go back to the shopping cart example, when the user clicks “add to cart” on a product page, the entirety of that action is handled inside the server. The server gets the product information, and the server adds a new session attribute that is associated with the session ID to track the user’s action. At no point does the untrustworthy web client have an opportunity to intervene in that process. When it comes time to display the contents of the shopping cart for the user, say during the checkout process, the web application pulls the information from the secure, server-side session attribute data store to generate a static, read-only HTML view of the cart contents.

How to Manage Session State?

Understanding what sessions and session IDs are, and what session state is, should make it fairly clear how these things are managed. Again, while there are many ways that you can handle the transmission of session IDs and the management of session state, if you’re concerned about security, you should let the untrustworthiness of the web client be your guide:

image Keep as much as you can on the server. Ideally, keep all session state information at the server end of the web client.

image Transmit as little as possible to the client. Ideally, don’t transmit anything other than an opaque session ID.

image Encrypt anything that is sent to the web client for storage and that needs to come back unmodified, using an encryption key that is not available to the client, because of course the client should never be able to decrypt the encrypted data.

image Rely on nonmalleable cryptographic algorithms as a means to detect tampering; let decryption failures trigger immediate invalidation of the session. Fail the request in some secure manner.

Why Do We Need Session Management?

We need sessions and session management because HTTP is a stateless protocol. HTTP was originally designed with static web sites in mind, or at the very least, for nothing more in mind than read-only database applications. If the user isn’t allowed to change anything, then it doesn’t matter who the user is. As history shows, the web quickly outgrew that limiting constraint, and the need for user identification and session state became evident. Along with users came the need for different classes of users, with different permissions, and thus a need for authorization and secure mechanisms for allowing authorized users to access protected resources.

The modern Web requires session management to identify users both before and after they have been authenticated. Web applications also require it as a means for keying into server-side session state storage (the application server needs to know which records in the session state data store correspond to which users). And we need session management because sessions—when correctly implemented—provide a means for ongoing authentication. Rather than requiring a user to provide a name and password with every single request for protected resources, the web browser’s ability to automatically supply the session ID serves that same purpose.

To fulfill these purposes, the web application must ensure the confidentiality and integrity of the session ID values themselves, as well as the confidentiality and integrity of session state information. Both of these are achieved through the proper application of cryptography: encryption of the transport medium itself (HTTPS), and the use of cryptographically random functions for generating session ID values.

Attacks Against Sessions

Attackers have invented many ways to attack sessions. The point of attacking sessions is usually to impersonate a user in order to gain access to the application, or to manipulate insecurely implemented sessions in order to access parts of a web application the user doesn’t have permission for.

Tampering

Also referred to as “cookie poisoning,” the technique of tampering involves an attacker modifying the client-side session ID or other data (such as that stored in cookies, form fields, or URL query strings) in order to bypass an authorization check. This attack relies on session state being stored in cookies, Web Storage, or any of the other client-side data storage mechanisms discussed earlier. For example, if that data contains expressions of the user’s permission levels, and the application trusts the values returned by the client, then the attacker can trivially change the values of the session state in order to lie to the application as to what the user’s permission levels are.

Pop quiz: How many of the best practices discussed so far in this chapter are violated in order to enable a tampering attack to succeed?

Theft

Theft is probably the broadest category of session attack. It involves stealing the session ID value through various means such that the attacker can use that session ID for themselves later. Stealing someone’s session ID is like stealing their ID badge. It provides a way for the attacker to impersonate the victim.

There are many ways to steal a session ID. Fortunately, the mitigations against session ID theft are all fairly generic, and apply regardless of the specific type of theft an attacker is attempting to perform. These mitigations are listed in the “Session Management Best Practices” section, later in this chapter.

One means of session theft is via a cross-site scripting (XSS) attack, which relies on tricking the user’s browser into executing a malicious client-side script. Result: the client’s browser runs a piece of JavaScript code that transmits the contents of the browser’s cookies to the attacker. If one of those cookies contains a session ID, the attacker accesses your web site, replaces their session ID value with the stolen one, and accesses the web application using the victim’s identity.

Session IDs can also be intercepted by an attacker who has access to the network segments between a victim and your web application. For example, if Joe and Dan work in the adjoining cubicles at their office, and their computers are on the same IP subnet, then it may be possible for Dan’s computer to see all the traffic coming from and going to Joe’s computer. By using packet sniffer software, Dan can eavesdrop and log all of Joe’s Internet traffic, at which point it becomes trivial for Dan to steal Joe’s session ID. Of course, this type of theft assumes that the underlying transport is not encrypted—that is, Joe’s web browser and the web application are communicating over HTTP rather than HTTPS.

An eavesdropper need not be on the same IP subnet as the victim; IP packets normally take many hops and cross many network boundaries before finally reaching the web application’s front-end web server. Anyone with access to any of those segments along the way can potentially eavesdrop on the traffic between your web application and the victim.

SSL and HTTPS

Interception attacks rely on the ability to make sense of the traffic that is intercepted. Think about having a conversation with a dinner companion in a restaurant. If the two of you are speaking loudly enough, people at nearby tables will be able to eavesdrop on your conversation quite easily. If those people speak the same language as you and your dinner companion, they can potentially gain useful information from what they overhear. But if you are speaking in a language the attacker does not speak, and one the attacker can’t have translated quickly enough to make use of the information, then he’s out of luck.

The Secure Sockets Layer (SSL) and HTTPS (HTTP over SSL) protocols do this very thing to protect the traffic between a web application and the web client, except that, rather than translating the traffic into a foreign language, they can allow you to encrypt the traffic. The protocol also allows you to detect tampering, authentication the server you’re talking to, and authenticate the client too! All of these features go a long way toward adding security to your application. There are misconceptions about SSL and HTTPS that persist even today—namely, that they’re difficult, that they impose significant overhead that will slow down your server, and that they’re expensive.

It is true that using SSL and HTTPS does involve a bit of additional configuration and setup work when deploying the web application. However, all modern web application frameworks have built-in support for this. Unless you’re building a web application from the ground up, enabling encrypted communications is likely to be a matter of obtaining a set of credentials and making a few minor changes to configuration files.

It is also true that the act of encrypting and decrypting all traffic does impose a computational overhead on your application’s server. That may have been burdensome in the past, but on modern server hardware the overhead is truly negligible. Indeed, even very large-scale web applications such as Facebook.com use HTTPS connections to protect their users (see the earlier section “Client-Side Attack”), and chances are Facebook has more users and more simultaneous sessions to deal with than your application will. Your application is likely to lose more time to network latency between itself and the web client (or even between itself and its back-end database) than it will to encryption and decryption overhead.

It is not true, however, that encryption is expensive. For SSL, there is a modest cost involved with obtaining credentials, and for renewing the credentials on a periodic basis. However, this cost is not large, and is certainly orders of magnitude smaller than the cost of designing and developing the web application in the first place.

ImageNote

Some web applications use SSL to protect the application’s authentication page, because this prevents the user’s password from traveling in the clear and thus protects the password from eavesdropping attacks, but then they don’t use SSL to encrypt the rest of the application’s traffic. This largely renders the password irrelevant, however, because the attacker can still snoop on the unencrypted traffic in order to steal the session ID and impersonate the user that way. If you’re going to use SSL at all, you really want to use it for your whole application.

URL rewriting is the practice of dynamically resorting to using URL parameters to store session ID values when cookies are not available. This can happen if a user’s web browser does not support cookies, or if the user has disabled cookie support. In such cases, there is little alternative except to use URL parameters to transmit the session ID value to the client, so that it may be returned in subsequent requests. For example, a web commerce application that detects this situation may dynamically rewrite the URLs it sends in responses to the client from parameter-free versions such as this:

image

to pararameterized URLs such as this:

image

This works, in terms of restoring functionality for users whose web browsers don’t support cookies, but it comes at a cost of exposing the session ID to all the forms of theft discussed earlier, including the Firesheep attack. The user’s web client likely has the parameterized URL in its browsing history, where it may be stolen by a cross-site scripting attack. If the user is connecting to the web application through an intermediate web proxy, the proxy’s URL cache will contain the original URL. Because the URL contains the session ID as a URL parameter, it is stored in more places than if it were being stored in a cookie, which is less likely to be cached.

If your application needs to use URL rewriting—that is, it isn’t acceptable to deny access entirely to web browsers that do not support cookies—you can mitigate against session ID theft by implementing the best practices discussed in the section “Session Management Best Practices.”

Predictability

Since your web application will be issuing session IDs to users, you must answer the question of how to generate those IDs. A naive answer would be to simply use the database to add a new row to a session table, and use the row’s ID number (which is guaranteed to be unique relative to all other rows in the table) as the session ID value.

This is a terrible idea. Session ID values should be unpredictable.

Never use an ID number generation method that yields a set of values in a predictable sequence, say, by adding 1 each time. If attackers figure this out—and they will—they can precompute the next 100 or 1000 or however many session IDs they want. Then they can periodically try making requests against your app with those precomputed session IDs until some real user comes along, authenticates, and gets assigned one of those same ID values. Session ID predictability is so bad that it’s like letting the attacker impersonate users before they even log on to the application, then nailing them once they arrive.

Jetty: Session Predictability in the Real World

In November, 2006, it was discovered that Jetty, the Java HTTP Servlet Server component, contained a session ID predictability flaw. The Jetty developers tried to get it right; they used the Java platform’s java.util.Random class as the basis for generating their session IDs. Jetty generated two random numbers and concatenated their bits together to form 64-bit session IDs. Unfortunately, because of the way java.util.Random generates its sequence of outputs, anyone in possession of two consecutive outputs of the random number generator can calculate what the random number generator’s internal state is, and thus run the algorithm forward to predict as many future outputs as desired. All an attacker would need to do is capture a session ID, split it in half, and use those two values as the basis for calculating the internal state of the Jetty servlet’s random number generator. By doing so they could more easily predict the session ID values for subsequent users, and then hijack their sessions. For a fuller description of this security vulnerability, check out: http://www.securityfocus.com/archive/1/archive/1/459164/100/0/threaded.

Session Fixation

Session fixation occurs when an attacker is able to prepopulate a victim’s web browser with a session ID value. For example, imagine a web-based e-mail service, one that issues a session ID as soon as a user connects. Anywhere that someone else might gain access to a victim web browser before the victim connects—say, at a free Internet kiosk set up during an industry trade show—the attacker could load the login page for the application and record the session ID value. Then all the attacker needs to do is wait for another user to come along and authenticate to that e-mail system. At that point, the session ID value becomes valid and the attacker can use it like any other stolen session ID in order to impersonate the user and gain access to the victim’s e-mail. The obvious mitigation against session fixation attacks is either to defer issuing a session ID until after authentication, or else to invalidate the old session ID and a new one immediately upon authentication, as discussed earlier in this chapter. Again, never reuse a session ID value.

Session Hijacking

Session hijacking simply refers to the moment when an attacker actually uses a stolen or fixated session ID in order to impersonate a legitimate user. A session hijack is the successful exploitation of a security flaw, and typically results not only in the attacker impersonating the victim, but preventing the user from using that session as well.

Sidejacking

Sidejacking is a bit of web security jargon with no clear definition. Some people use it synonymously with “session hijacking.” Some people use it to mean session hijacking when the session ID was stolen by means of packet sniffing. Some people use it to mean the use of a hijacked session concurrently with the original user, who is still logged on and actively using the application. This latter definition only applies to systems in which a successful session hijack does not prevent the victim from also using that same session. Nevertheless, if anyone mentions sidejacking to you, stop them and make them explain what they mean first.

Cross-Site Request Forgery

We explored cross-site request forgery (CSRF) earlier, in the context of forceful browsing. The point of CSRF is not for the attacker to conduct a whole session with the web application, but merely to cause the victim’s browser to take a single desired action within the application. However, CSRF still counts as an attack against a session because, as was mentioned, it exploits the trust that a web application has for a web client on the basis of the session value that the client holds. Essentially, an CSRF attack is a very short-duration hijacking of a legitimate session.

Note, however, that for an CSRF attack to work, the web browser must be fooled into making a request for a URL. Usually this is done by embedding an image tag or other HTML element that browsers are designed to load automatically. The attacker cannot usually predict with any certainty when the victim might actually take the bait (if ever). This implies that if the attack is successful, it is likely to be hijacking a session that is still being used, or else has been idle for a long period of time and should have been forcibly expired long ago. Aggressive session expiration policies, or even common-sense ones, can do much to mitigate CSRF attacks.

Attacks Against Session State

Sessions and session state go hand in hand. The whole reason to track sessions is because there is some kind of per-user state information that needs to follow along with the user’s use of the web application. Consequently, we must also examine potential attacks against state information. There are two principal concerns: data tampering and data hijacking.

Tampering, just like it sounds, occurs when an attacker is able to alter elements within the session state. This allows the attacker to lie (and lie convincingly) to the web application, as we saw with the example of level 1 manager Dan giving himself a fat holiday bonus.

Hijacking occurs when an attacker is able to steal the contents of the session state. What the hijacker might do with that data later depends on the nature of the data. But one can imagine all sorts of sensitive information being kept in session state. For example, consider what is likely to be kept in session state while a user is checking out and paying for items on an e-commerce web site. It would be a bad time to have your session state hijacked, at the very moment it contains your name, your home address, your home phone number, your credit card number, card expiration date, and card verification number. That’s basically enough information for an attacker to commit wholesale identity theft against the victim, not just to mess with their purchases on that one e-commerce site.

By now, the mitigation for attacks against session state should be obvious: if you store that information at the client, encrypt it without providing the client any means to decrypt it. Better yet, don’t store it at the client at all; store it in server-side session attributes or your application’s database, and present read-only views to the client.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset