Securing Web Application Session Management

Hopefully, the litany of ways attackers can mess with your sessions and session state didn’t leave you feeling hopeless about security, because there are at least as many ways you can mitigate those kinds of attacks. Here are the best practices for web applications to follow in order to protect session IDs and session state.

Session Management Best Practices

There are a number of best practices that can be implemented to defend against and mitigate the variety of attacks that can occur against sessions.

Enforcing Absolute Session Timeouts

To paraphrase the immortal words of Brian May, who wants sessions to live forever? Hackers, that’s who. Hackers would be delighted to have sessions never expire, because then any stolen session ID would become a permanent key to unlock your web application. The solution is obvious: Establish a maximum session lifetime, and terminate any session that reaches that limit. This creates some potential hassle for legitimate users, but having to periodically reauthenticate is not overly burdensome in practice. If you’re storing session state at the server, you can alleviate the inconvenience of forcing users to start from scratch with their tasks by restoring their session state when they reauthenticate and receive a new session ID. Basically, just destroy the expired session ID, but keep the session state around for later.

Enforcing absolute session timeouts greatly reduces the window of time in which an attacker can exploit a stolen session ID. Set your timeout to something that’s appropriate for the normal use cases your web application is designed for. A good rule of thumb is that high-security applications should limit session IDs to one or two hours, while for web applications with less stringent security requirements, a four-hour limit is good. Adjust these values based on the level of risk you’re willing to accept.

While you can (and should) specify an expiration timestamp on the session ID cookie itself, remember that you can’t trust the web client to honor that. You must also enforce session timeouts on the server. The following Set-Cookie directive shows how to specify a timeout value (in this and similar examples in this section, you will replace the cookie name and value with appropriate values for your application):

image

Enforcing Idle Session Timeouts

Ideally, a session ID would be destroyed as soon as the user is done interacting with the application. But, from the application server’s perspective, it can’t always know when that is. If the user explicitly logs out (see the section “Logging Out”), then it’s obvious; but if they don’t, you can’t be sure that they’re actually finished with whatever they’re doing. However, if they’re idle for a sufficiently long period of time, you can make a reasonably educated guess that they’re done. Again, evaluate your own application’s specific needs, but the best practice for high-security web applications is an idle timeout of no more than 10 minutes, and a 20-minute timeout for normal applications. Idle session timeouts must be enforced by the web application; it can either have a periodic task that sweeps the session ID table to clear out idle sessions, or it can wait for a session ID value to reappear, calculate the time since the last use, and reject if necessary.

Limiting Session Concurrency

The idea here is to limit how many active sessions a single user can have at one time. This doesn’t actually affect session IDs (because a single session ID should never be reused from one session or web client to another), but it does potentially stop an attacker from reusing stolen authentication credentials.

You might think, “why should anyone need more than one session at a time?” And indeed, that’s the most secure concurrency limit. But the reasonable limit for your application will depend on the nature of the application. For a webmail site such as Gmail, it may make perfect sense to let a single user have three sessions active at once: one is left open on their home computer, one is opened from their computer at work, and one is accessed from their smartphone. Again, consider what makes sense for your application.

Mandating Secure Cookies

One of the attributes you can set on the cookie that holds your application’s encrypted session ID is the “Secure” flag, which mandates that the web client uses encrypted communications (SSL and HTTPS) when sending the cookie back to the server along with each request. We have by now drilled home the message that you can’t trust the client to behave properly, but the Secure cookie flag is one instance where the browser enforces the behavior. Or rather, this is a case where you can expect that attackers will follow the rules because if they don’t, it’s an automatic sign that something is wrong and you should immediately invalidate the session ID. You should still check for this condition and fail in a secure manner as always, but in this particular case there’s nothing for an attacker to gain by not honoring the Secure cookie flag. The following Set-Cookie directive shows how to specify the Secure flag:

image

Using the HttpOnly Flag

Setting the HttpOnly flag on a cookie instructs the client that the cookie is only to be used in communications over the HTTP protocol. This effectively denies access to the cookie to any client-side code such as JavaScript. You can’t trust a malicious client not to send the cookie over some other transport, but that’s not the point. The point is that by setting this flag, honest users with honest browsers will be protected from having their cookies stolen via cross-site scripting (XSS) attacks, which rely on client-side code. The following Set-Cookie directive shows how to specify the HttpOnly flag:

image

Using Cryptographically Random Session IDs

Earlier, we looked at the dangers of predictable session IDs, and stated that session ID values should be unpredictable. Fortunately, it is relatively easy to do this. Just use a cryptographically secure random number generator (CSPRNG) to create them. Session ID values are nothing more than meaningless tokens anyway, useful only for their uniqueness, for which a sufficiently random number or a globally unique identifier (GUID) works just fine. If you’re using random numbers, however, remember the lesson of Jetty: random number sequences can be predictable, and not all random number generators are equal.

Destroying Invalidated Session IDs

Timeouts, expirations, unauthorized reuse—there are lots of reasons why a session ID can become invalid. Here are several best practices to follow for how to properly dispose of a session ID.

image Invalidate the session ID on the server. This should be the first thing. Generally, this just means removing that session ID from whatever internal mechanism (an in-memory list, a database table) the application server is using to track the set of valid session IDs. Just delete it. This should be trivial, as most application servers and modern web development frameworks include APIs that allow you to easily manage your application’s sessions.

image Immediately destroy any related client-side cookie values. If the server is still in a position to send a response to the web client, send a response that includes commands to delete the session ID cookie and any cookies containing session state information. Do this by including a Set-Cookie directive in the response with an expiration time set in the past. However, a malicious web client will ignore these.

image Delete cookies when the browser closes. Again, this is more of a protection issue for honest users than anything else. An honest web browser will delete any “session cookies” when the browser closes. Session cookies are defined as cookies that have been set to expire when the session is terminated.

You might be wondering why it is recommended to delete the session ID from both the client and the server. The reason for taking it off the server is straightforward: An attacker can’t use a stolen session ID if the server disavows all knowledge of it. But why go to the bother of destroying those cookies at the client as well? Because an attacker can’t steal something that isn’t there.

Using Encrypted Cookies

Another message that should be hammered home by now: encrypt any data you store in cookies on the web client. Hopefully, your web application does not need to pass data to the client for storage at all, and can instead use server-side storage mechanisms as discussed earlier in this chapter. But there are circumstances in which it may make sense to pass state information to and from a client. In these scenarios, you must make sure that the state cannot be tampered with by an attacker, and the only way to guarantee that is to use cryptography. One way to use cryptography is to simply encrypt any data that you’re sending with a key that is not accessible to the client, so the client cannot decrypt it.

Most data encrypted with nonmalleable algorithms can’t be modified without invalidating the decryption. A nonmalleable encryption algorithm is one in which modifications to any part of an encrypted message completely invalidate the whole message. This severely curtails what an attacker can do with any cookies he or she does manage to steal. If you want to get really paranoid, why not encrypt the names of your client-side cookies too? Your web commerce application will be able to decrypt a cookie like:

image

into a meaningful sequence such as:

image

But an attacker isn’t going to have any idea what that cookie is even for, and if they try to alter the cookie, you’ll know it immediately because the decryption will yield corrupted data.

The other way to protect your session data is to use a hash-based message code (see the sidebar “Into Action,” later in this chapter), which combines the data with a secret key as a means of preventing tampering attacks. This provides for data integrity, but does not offer the same level of data confidentiality as full encryption.

Logging Out

One of the best session ID management practices you can make is simply to provide an explicit logout facility in your web application’s UI. Make it easy for users to log out with a single click. Doing so creates an explicit request to the application, which removes all doubt that a user is done with the session, allowing the server to immediately dispose of the session ID. This is the best way to minimize the window of time in which an attacker can potentially reuse a stolen session ID. Make the logout button easy to find, too.

Regenerating Session IDs on Authentication

Never reuse a session ID. Just don’t. Every time a unique visitor accesses the web application or a user authenticates, create a new session ID for that user. If every session uses a different session ID value, then session fixation attacks will fail. Of course, session fixation attacks should fail for a whole host of other reasons too, but why make it easy for an attacker? Just generate new session IDs for each unique user and on every authentication.

Into Action

The simplest best practice for securing session state information is simply not to send it to the client at all.

image Keep all session state information internal to the web application. Ideally, session state information won’t even leave the web application’s runtime process space. Keeping state information in memory provides optimal performance, but does present scalability issues for high-volume applications. This is the primary reason some web sites with enormous user bases allow session data to be stored on the client in an encrypted form, as discussed in the earlier section “Using Encrypted Cookies.” Storing session state in the application’s trusted data store (which itself has layers of security protection, as discussed earlier) is also a fine way to go.

image Another best practice is, if state information ever does have to leave the web application’s process space, encrypt it. Whether you’re putting the data in a client-side cookie, rendering it into a URL parameter as part of an HTTP response, or putting it into a form field, encrypt it. Don’t let unencrypted session state leave the physical RAM allocated to the web server’s runtime process. This can be more resource-intensive but may be appropriate for high-security environments.

image A third good idea is to use a Hash-based Message Authentication Code (HMAC) to verify the integrity of state information you receive from the client. HMAC is a specific algorithm for generating a message “digest,” a kind of digital fingerprint corresponding to a set of data. These digests are guaranteed with very high probability not to be the same for two different sets of data, and they are guaranteed to be very distinct even between the fingerprints for two nearly identical sets of data. HMAC requires the use of a secret key, which is used as part of the process of computing the digests. If your application needs to send session state information on a round trip to and from the web client, you can use HMAC as a mechanism for verifying that the data wasn’t tampered with along the way. For more information on HMAC, see http://tools.ietf.org/html/rfc2104.

We’ve Covered

Authorization fundamentals

image Define authorization (authZ) and how it works

image Discuss examples of authorization in web applications

image Cover the goals of authorization with web applications

image Understand authorization as both policy definition and policy enforcement

Detailed examination of the authorization process

image Define subjects and resources and show examples of each

image Discuss the need to set permissions and where to set them in a web application

image Review access control model types such as discretionary access control (DAC), mandatory access control (MAC), role-based access control (RBAC), and hybrid systems

Types of permission systems and where they’re applied

image Understand how read, write, and execute permissions are applied under different circumstances

image Discuss horizontal authorization layers such as web clients, web servers, application servers, and back-end databases

image Examine vertical authorization layers including the user, application, middleware, operating system, and hardware

Implementing authorization and best practices

image Discuss the different types of authorization that can be applied in the vertical and horizontal layers of a web application

image Detail how to develop a custom authorization mechanism using the 3×3 model

Attacks against authorization

image Examine client-side attacks and how attackers use them

image Understand how TOCTTOU attacks work

image Review common attacks such as forceful browsing, parameter tampering, HTTP header manipulation, and CSRF

Session management fundamentals

image Understand the reasons behind using sessions and session state

image Catalog the different types of session state along with their pros and cons

image Learn how to securely manage session state

Attacks against session management

image Cover different types of session management attacks such as tampering and theft

image Review the variety of interception and hijacking attacks that can occur.

image Understand the threat of CSRF.

Session management best practices

image Know why idle and absolute session timeouts along with the ability for a user to logout are important to securing sessions

image Properly configure how your application will handle session concurrency and session invalidation

image Use cookies securely and set the right flags such as HttpOnly to mitigate the impact of other attacks

image Make sure that encryption is properly used when it is applied to session state management

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

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