Secure Session Tokens
Of the many ways an attacker can exploit Web applications, exploiting a user’s cookies is the method most often used in the worst attacks. Typical examples of this type of attack include Cross-Site Scripting and Session Fixation.
The most valuable cookie of all is one that stores the user’s session token value, which allows a user to access authenticated areas of a website. A session token value is set as a cookie in the user’s browser during the login process of most Web applications. This same session value is also generally saved as a session variable on the host server.
When the user’s browser sends a request to a specific host name, each of its associated cookies are included in the request to the host server. The application then compares the value of both the cookie storing the session token and the stored session variable. If they match, the user is authenticated to the application. However, if the cookie storing the session token value is stolen while the session is active on the server, it is “Game Over” for the user.
Specific Problems Related to Attacks on User Cookies
A few basic problems allow exploitation of weaknesses and subsequent attacks on the user’s authentication cookie. These problems typically relate to four characteristics of a cookie: strength, predictability, regeneration, and expiration. While fixing such problems may be inadequately for defending against attacks such as Cross-Site Scripting, it will make attacks such as Session Fixation and Credential/Session Prediction more difficult and will help mitigate weaknesses such as Insufficient Session Expiration.
Below is a WhiteHat Security cookie storing a session token value generated by an imaginary PHP application:
No. 1 Strength
The strength of a session token depends on the number of character spaces it has. Just as a strong password uses more characters and a greater variety of characters, so a strong session token will include those same characteristics.
An example of a weak session token:
A session token with a low number of character spaces can be brute forced, which lets an attacker cycle through possible session tokens and discover the ones that are currently authenticated. Again, the best session tokens have a very high number of characters, usually at least 20 to 25 [more characters are even better!], as well as requiring numbers and case sensitivity. Using special characters also increases the strength of a cookie.
An example of a much stronger session token:
No. 2 Predictability
Strength alone is insufficient to keep a session token secure. For example, the greater the predictability of a session token, the weaker its strength.
An example of a strong session token based on low predictability:
Secure Session Tokens
When brute force is successful in compromising session tokens, patterns in their value often become easily evident:
Upon discovering this sequence, all an attacker needs to do to steal a user’s accounts is base his attack on the subsequent session tokens as they are created when the user logs in.
No. 3 Regeneration
While the importance of session token regeneration may not be immediately obvious, it is a necessary component for averting Session Fixation attacks. The WASC Threat Classification describes session fixation as “…an attack technique that forces a user’s session ID to an explicit value.” Cross-Site Scripting is usually the method used to carry out a Session Fixation attack, by either setting a cookie value for that user or stealing a session token value prior to the user logging in. Then, when the user logs in with the pre-determined session token value, the attacker can send requests to the server just as if he were that user.
The best defense against a Session Fixation attack is to “regenerate,” i.e., assign a new session token value every time a user logs in. Note, however, that if the token is changed from the pre-login value, the session can no longer be fixed.
An example of an HTTP server response setting a new cookie value for PHPSESSID post-login:
HTTP/1.1 200 OK
Cache-Control: max-age=0, no-cache, no-store
Date: Tue, 05 Apr 2011 21:46:23 GMT
Set-Cookie: PHPSESSID=NeknoCIkHzetzu9hvnwW; path=/; Secure; Expires=Tue, 05 Apr 2011 22:16:23 GMT
No. 4 Expiration
When both the server and the user’s browser have an authenticated session token, there must be a way to force session tokens to both Invalidate and Expire. Otherwise, when session tokens remain active for extended periods of time, the attack surface of cookie-stealing techniques will increase.
To assure that session tokens expire, cookie values must first include some type of timed Expiration setting. Users who keep their authenticated sessions open for extended periods of time are then forced to log back into the application after they reach that established time limit. This lowers the chance that if a hacker steals a cookie, it would work immediately − compared to working six hours later. This problem creates high-risk situations especially when individuals use public computers. For example, say that a user accesses his banking information on a publicly accessible computer, and then fails to log out of the application; two hours later a second person using that same computer can gain access to the previous user’s banking information because the session token is still valid.
Secondly, applications that feature authenticated areas must also use Sign Out or Log Out links to force Invalidation of the session token value. This forced Invalidation allows users to terminate their own session. So, even if their cookies are stolen, the value will no longer work post-log out. Note, however, that removing cookies from only the browser during log out is insufficient to prevent an attack. Instead, the authenticated session on the server must also be killed in order to ensure that no requests using stolen session token values will be accepted.
A Note about SSL
I the application utilizes a Secure Socket Layer (e.g., HTTPS), then it is also a best practice to mark the session token value stored in a user’s cookies as “Secure.”
An Example of Setting the Secure Flag in Java Server Pages:
When the browser is parsing HTML in the source code, and sees a request for a new resource, the secure flag will ensure that the cookie storing the session token value is used only for requests sent via a Secure Socket Layer.
An Example in HTML Where the Browser Will Request an Image:
<img src=”http://www.example.com/images/image_01.jpg” id=”img1″ />
But! Once a token is flagged as Secure, the browser will detect any token that’s sent over HTTP rather than HTTPS, and then omit any cookie containing a sensitive value.