When a user connects to your application you can force them to provide logon credentials. If the user successfully authenticates they wouldn’t expect to provide these credentials again unless the logon times out or they are executing a privileged action. Session management allows your application to only require the users to authenticate once and also confirm that the user executing a given action is the user who provided the original credentials. To an attacker any weaknesses in the session management layer of your application can be an easy way to bypass the hard work we have done so far in the first four principles.
Attacks against sessions are often focused on obtaining a valid session value through either exploiting your users or taking advantage of weaknesses in the session management functionality itself. Knowledge of the methods used by attackers isn’t required if you secure your sessions based on the advice in this principle.
The session values used in your application should follow similar principles to the secure password requirements we outlined earlier. The session ID’s used to identify individual authenticated users should be of a sufficient length to prevent brute force attacks. This length is going to be determined by the sensitivity of the data or resource you are trying to protect. We do have to stress that session ID length isn’t enough to provide protection by itself; you also need to have a high amount of entropy per character in the session ID. The entropy of each character position must be considered in your creation of sessions ID’s with higher entropy per character being more secure. A session ID should be constructed from a large character set without any obvious patterns in the ID’s. A pattern such as character positions 1, 4 and 5 always containing the letter C would be easily identified by automated tools and will reduce the computation time required to brute force genuine ID’s.
If the above steps have been followed each user should have a strong session ID that cannot be predicted easily by attackers. We now need to ensure that these ID’s are secured both on the application server and whilst they are in transit. The storage location for the session ID’s should be a secure location and not in world readable locations, refer to the principle of least privilege we have outlined earlier for guidance on how to secure access to this location. The next point we need to secure is the transmission of the session ID’s and a simple answer exists for this. If the session ID is transmitted via HTTP it can be easily intercepted and re-used by an attacker, by using HTTPS instead you can protect the session ID in transit.
At this point we should have a session ID that is resistant to prediction, brute force and interception attacks but we do have a few more protection measures to implement before we can be comfortable with the security surrounding our session management. There are many examples of applications verifying whether a session ID exists but not checking whether this is a genuine ID. If the application performs this minimal level of session ID checking an attacker can perform session fixation attacks against your users. You should always mandate that session ID’s are only accepted if they are generated by your application server and overwrite those values which are present in requests but not provided by your application.
The final two session protection mechanisms you need to provide are timeouts on sessions and changes of session ID’s when users carry out sensitive actions. We have already discussed the requirement for timeouts of user logons and the same protection must be in place for sessions. You will need to identify the maximum age of any given session ID as well as a timeout for sessions. There is often the requirement to re-authenticate users during a session, for example an online bank application would re-authenticate the user prior to transferring funds. This second authentication should also prompt the creation of a second session ID and the destruction of the original ID.