Testing for Cookie and Session Token Manipulation

Brief Summary
In this test we want to check that cookies and other session tokens are created in a secure and unpredictable way. An attacker that is able to predict and forge a weak cookie can easily hijack sessions of legitimate users.

Description of the Issue
Cookies are used to implement session management and are described in detail in RFC 2965. In a nutshell, when a user accesses an application which needs to keep track of the actions and identity of that user across multiple requests, a cookie (or more than one) is generated by the server and sent to the client. The client will then send the cookie back to the server in all following connections until the cookie expires or is destroyed. The data stored in the cookie can provide to the server a large spectrum of information about who the user is, what actions he has performed so far, what his preferences are, etc. therefore providing a state to a stateless protocol like HTTP.

A typical example is provided by an online shopping cart. Throughout the session of a user, the application must keep track of his identity, his profile, the products that he has chosen to buy, the quantity, the individual prices, the discounts, etc. Cookies are an efficient way to store and pass this information back and forth (other methods are URL parameters and hidden fields).

Due to the importance of the data that they store, cookies are therefore vital in the overall security of the application. Being able to tamper with cookies may result in hijacking the sessions of legitimate users, gaining higher privileges in an active session, and in general influencing the operations of the application in an unauthorized way. In this test we have to check whether the cookies issued to clients can resist a wide range of attacks aimed to interfere with the sessions of legitimate users and with the application itself. The overall goal is to be able to forge a cookie that will be considered valid by the application and that will provide some kind of unauthorized access (session hijacking, privilege escalation, ...). Usually the main steps of the attack pattern are the following:
 * cookie collection: collection of a sufficient number of cookie samples;
 * cookie reverse engineering: analysis of the cookie generation algorithm;
 * cookie manipulation: forging of a valid cookie in order to perform the attack. This last step might require a large number of attempts, depending on how the cookie is created (cookie brute-force attack).

Another pattern of attack consists of overflowing a cookie. Strictly speaking, this attack has a different nature, since here we are not trying to recreate a perfectly valid cookie. Instead, our goal is to overflow a memory area, thereby interfering with the correct behavior of the application and possibly injecting (and remotely executing) malicious code.

Black Box Testing and Examples
All interaction between the Client and Application should be tested at least against the following criteria:
 * Are all Set-Cookie directives tagged as Secure?
 * Do any Cookie operations take place over unencrypted transport?
 * Can the Cookie be forced over unencrypted transport?
 * If so, how does the application maintain security?
 * Are any Cookies persistent?
 * What Expires= times are used on persistent cookies, and are they reasonable?
 * Are cookies that are expected to be transient configured as such?
 * What HTTP/1.1 Cache-Control settings are used to protect Cookies?
 * What HTTP/1.0 Cache-Control settings are used to protect Cookies?

Cookie collection

The first step required in order to manipulate the cookie is obviously to understand how the application creates and manages cookies. For this task, we have to try to answer the following questions:

Surf the application. Note when cookies are created. Make a list of received cookies, the page that sets them (with the set-cookie directive), the domain for which they are valid, their value, and their characteristics. Surfing the application, find which cookies remain constant and which get modified. What events modify the cookie ? Find out which parts of the application need a cookie. Access a page, then try again without the cookie, or with a modified value of it. Try to map which cookies are used where.
 * How many cookies are used by the application ?
 * Which parts of the the application generate and/or modify the cookie ?
 * Which parts of the application require this cookie in order to be accessed and utilized?

A spreadsheet mapping each cookie to the corresponding application parts and the related information can be a valuable output of this phase.

Cookie reverse engineering

Now that we have enumerated the cookies and have a general idea of their use, it is time to have a deeper look at cookies that seem interesting. Which cookies are we interested in? A cookie, in order to provide a secure method of session management, must combine several characteristics, each of which is aimed to protect the cookie from a different class of attacks. These characteristics are summarized below:
 * 1) Unpredictability: a cookie must contain some amount of hard-to-guess data. The harder it is to forge a valid cookie, the harder is to break into legitimate user's session. If an attacker can guess the cookie used in an active session of a legitimate user, he/she will be able to fully impersonate that user (session hijacking). In order to make a cookie unpredictable, random values and/or cryptography can be used.
 * 2) Tamper resistance: a cookie must resist malicious attempts of modification. If we receive a cookie like IsAdmin=No, it is trivial to modify it to get administrative rights, unless the application performs a double check (for instance appending to the cookie an encrypted hash of its value)
 * 3) Expiration: a critical cookie must be valid only for an appropriate period of time and must be deleted from disk/memory afterwards in order to avoid the risk of being replayed. This does not apply to cookies that store non-critical data that needs to be remembered across sessions (e.g.: site look-and-feel)
 * 4) “Secure” flag: a cookie whose value is critical for the integrity of the session should have this flag enabled in order to allow its transmission only in an encrypted channel to deter eavesdropping.

The approach here is to collect a sufficient number of instances of a cookie and start looking for patterns in their value. The exact meaning of “sufficient” can vary from a handful of samples if the cookie generation method is very easy to break to several thousands if we need to proceed with some mathematical analysis (e.g.: chi-squares, attractors, ..., see later).

It is important to pay particular attention to the workflow of the application, as the state of a session can have a heavy impact on collected cookies: a cookie collected before being authenticated can be very different from a cookie obtained after the authentication.

Another aspect to keep into consideration is time: always record the exact time when a cookie has been obtained, when there is the possibility that time plays a role in the value of the cookie (the server could use a timestamp as part of the cookie value). The time recorded could be the local time or the server's timestamp included in the HTTP response (or both).

Analyzing the collected values, try to figure out all variables that could have influenced the cookie value and try to vary them one at the time. Passing to the server modified versions of the same cookie can be very helpful in understanding how the application reads and processes the cookie.

Examples of checks to be performed at this stage include:
 * What character set is used in the cookie ? Has the cookie a numeric value ? Alphanumeric ? Hexadecimal ? What happens inserting in a cookie characters that do not belong to the expected charset ?
 * Is the cookie composed of different sub-parts carrying different pieces of information ? How are the different parts separated ? With which delimiters ? Some parts of the cookie could have a higher variance, others might be constant, others could assume only a limited set of values. Breaking down the cookie to its base components is the first and fundamental step. An example of an easy-to-spot structured cookie is the following:

ID=5a0acfc7ffeb919:CR=1:TM=1120514521:LM=1120514521:S=j3am5KzC4v01ba3q

In this example we see 5 different fields, carrying different types of data:

ID – hexadecimal CR – small integer TM and LM – large integer. (And curiously they hold the same value. Worth to see what happens modifying one of them) S – alphanumeric

Even when no delimiters are used, having enough samples can help. As an example, let's look at the following series:

0123456789abcdef

Gray Box testing and example
If you can access to session management schema implementation, you can check for the following: The sessionID or Cookie issued to the client should not be easily predictable (don't use linear algorithm based on predictable variables or client IPArddr). The use of cryptographic algorithms with key lenght of 256 bits is encouraged (like AES). SessionID will be at least 50 characters length. Session token should have a defined time-out (it depends on the criticality of the application managed data)
 * Random Session Token
 * Token length
 * Session Time-out
 * Cookie configuration, as described here: Testing_for_cookies_attributes