codesecurely.org

My ramblings on the world, my life, my work and oh yeah security!
Welcome to codesecurely.org Sign in | Help

User & Session Management

Abstract

Unlike, for the most part in the physical world, in the virtual world two mechanisms play a key role in the security of a software system: user management and session management. This two security functions are often heavily intertwined and can be the difference between Fort Knox and Swiss cheese. Hence both developers and reviewers are well advised to spend a significant amount of time designing, developing and reviewing code that implements one or more of these functions.

Introduction

In previous issues we have covered the categories of Configuration Management and Data Protection in Storage and Transit from our security frame described in the Security Code Reviews article. Based on that security frame we now move to the next category of security issues namely User and Session Management. Like most other principles of security, again tried and tested techniques, patterns and practices do exist for these security mechanisms and application development teams should utilize these as far as possible refraining from building and rolling out their own implementations. This category is also significant since it represents the mechanism that is perhaps most heavily dependent on the underlying architecture and framework. Consequently, legacy and other technical reasons often govern the choices available for developers.

 

Unfortunately, having performed hundreds of application and code reviews, the categories of authentication, authorization, user and session management also represent the bulk of the issues that we discover in real-world applications. In our experience the fundamental cause of this problem is the fact that all too often these critical security functions are left for individual developers to deal with and are never a focus area during the design and other earlier phases in the application development lifecycle. This lack of attention can result in the practitioners making assumptions and as a result inconsistencies and perhaps even vulnerabilities being introduced into the application. Moreover, the lack of basic developer security awareness, the need to provide a “quick and dirty” solution and the absence of a detailed application threat model often results in implementations that utilize weak mechanisms for authentication and the other security functions. Such mechanisms in turn are easily broken compromising the entire application.

User Management

Like authentication and authorization above, user management is a key cornerstone in the security of a system and perhaps even the organization. User management is also an important consideration since it encompasses significant privacy issues. What makes it even more challenging is the scope of considerations that come into play when building a strong and secure user management scheme – from password resets and account lockouts to password storage and anti-phishing mechanisms. User management thus in many ways can be thought of as a hybrid category encompassing data protection, authentication and authorization and perhaps even session management. In the next few sections of this article we will tackle a number of the key issues with regards to user management.

 

In the last few years user management security has really come to the fore because of widespread phishing attacks. The graphic below[1] illustrates the magnitude of the problem. Gartner[2] estimates that between May 2004 and May 2005 approximately 2.4 million users in the United States were victims of phishing attacks resulting in losses of approximately $929 million to users and about $2 billion to the companies whose customers became victims. 

Phishing 

While phishing really is a social engineering and authentication problem, a number of the solutions proposed to it fall into the realm of user management. Consider for instance SiteKey[3] from Bank of America. This is an additional step added to the usual forms based authentication system on Bank of America’s online services. A user is expected to select an image the first time they setup their SiteKey and then only type their password if the site displays the correct image on future visits. Thus, the user can know if they are visiting a legitimate site or a malicious phishing site. While this is not an entirely full proof mechanism it does help make a phishing attack marginally more difficult to exploit.

 

Another massive area of concern with regards to user management is privacy. A number of applications default to using private data such as users’ social security numbers as their login credentials. This is generally regarded as a bad practice since it increases the distribution of such private information and also increases the attack surface. For instance, a user’s social security number might show up in the log files since all logons and logoffs are being audited. Similarly with regards to password hints for instance, storing some categories of information may not be permitted under local laws. Consider the quintessential “mother’s maiden name” question. In a number of countries storing information about a non-customer – the customer’s mother in this case – is not permitted and hence such a question would be in violation of the law. Similarly, systems that store passwords in the clear where they are accessible to database administrators, developers and other employees of the service provider are also in violation of a number of government and industry compliance regulations such as HIPAA and PCI.

 

In general with regards to passwords, complexity must be required and encouraged. As an illustrative example consider for instance a system that uses a 4 character password and only allows upper case A – Z as valid characters. This implies there exist a total of 264 or 456,976 valid and unique passwords. Now consider if we simply used 6 character passwords the number of unique passwords jumps significantly to approximately 309 million. Similarly, if we allowed both upper and lower case letters, the 10 numerics and a variety of special characters for a total of approximately 95 printable characters on a typical keyboard we end up with about 81.5 million unique password combination if we used 4 character passwords and 6.6 x 1015 combinations if you use 8 character passwords. These numbers while not important by themselves illustrate how a small increase in complexity can result in enormous benefits from a security perspective making an exhaustive search of the password space i.e. attempting every valid password combination a computationally infeasible task for most practical purposes. However, like most things in security, developers should be aware of the usability tradeoffs of large and complex passwords. While we definitely want a secure system, we don’t want one where the users are forced to call the helpdesk for password resets every time they need to access the application. Typically password complexity is balanced by enforcing password expiry i.e. forcing a user to change the password in some finite time. The thinking behind this is that the password only needs to be secure enough to withstand an attack until it expires and the user has changed it. Typical time periods vary between 45 to 90 days in most systems. When expiry is enforced, the system must also ensure password history is enforced to prevent users from repeatedly reusing the same password or variations of it.

 

To deal specifically with the threat of repeated password attempts most systems also implement an account lockout mechanism. This is an area where one needs to be careful. For instance, consider a system that permanently locks out a user account after three failed attempts and then requires manual intervention to have the account unlocked. An attacker who is not looking to gain illegitimate access but to only cause your organization financial or reputation loss may simply proceed to lock every account thus causing tremendous manual burden as well as a denial of service condition. In general to deal with this situation, firstly administrative accounts should never be locked out. Secondly, consider a phased lock out approach wherein the account is only temporarily locked out (for say 15 minutes) after the first set of failed attempts and this temporary lock out duration is increased for each additional set of bad attempts. This approach not only deters the attacker since making bad attempts is a time consuming task, it also prevents the attacker from misusing the lockout mechanism to cause a denial of service.

 

Another important security consideration when it comes to password based systems and attacks against such systems is the error message displayed to the user. In general, error messages must avoid providing the user with any information that can then be leveraged in an attack against the system. For instance, consider a login form that responds with the message: “Invalid password for username bob”. The fundamental problem with this error message is that it lets the attacker know that he / she is using a valid username and now only needs to guess the password. Instead a good error message would say something along the lines of: “Invalid username or password”. It should be noted that this problem does not show up only on login forms but also on password reset forms and new user signups. Error messages and the security impact they have will be covered in detail in a later article.

 

While account lockout mechanisms can help against online password attacks, developers have to still attempt to protect against offline guessing threats. For instance, consider if an attacker obtains access to the application’s user data store. An important consideration in this case is whether the passwords in this data store are maintained in the clear. In general the recommended approach is to use salted hashes for password storage. As explained in an earlier article hash functions by definition are one way and hence the use of a strong hash function like SHA-1 prevents someone from obtaining the password by simply knowing the hash. However, even with this protection passwords can be obtained by launching a dictionary or brute force attack. Such an attack computes the hash for a candidate password and then compares that hash against what is in the user data store. If the two match the attacker knows that the candidate password is the true password for that specific user account. Moreover, in such a case, the attacker can pre-compute hashes into what are often called rainbow tables[4]. Thus what essentially was meant to be a time complexity problem for the attacker has been converted into a space complexity one and given how cheap hard disk space is today, it clearly is not much of a deterrent.  Such rainbow tables are easily available at many locations on the Internet. To mitigate some of the risk associated with this as well as to ensure that two users with the same password don’t end up with the same password hash, a source of randomness called a salt is often introduced into the hashing algorithm. This salt, which is unique for each user and created when the password is changed or created, must be stored with the user account information so it can be used for password verification. In this case the password hash is computed by concatenating the true password with the salt value.

 

Password resets can be another potential mine field for an application. The most commonly used scheme lets the user provide a secret answer to one or more questions. Unfortunately however, all too often the questions have easily guessable answers. For instance, if an attacker knows the user is from Boston and the question is “What is your favorite sports team?”, it is fairly likely that the “secret” answer is going to be the Boston Red Sox, the Celtics or perhaps the New England Patriots. With this in mind, applications should use hard to guess questions. A number of banking applications we have reviewed use bank transaction history as the secret answer. For instance, you might be asked what was the last ATM transaction you performed. Mechanisms that simply take the username and display the hint should always be avoided.

 

Irrespective of what mechanism for password resets is used, the password should never be displayed on the screen. Instead a one time link to reset the password or a one time password should be sent to the user preferably over a secure or out-of-band channel such as a phone call. The account must also be flagged to require a change of password the next time the user logs in. As passwords (if stored as described above), cannot be recovered even by the system, the system will need to generate a new and random password. A cryptographically secure source of randomness such as /dev/random on UNIX systems maybe used for this purpose. On Windows machines the RNGCryptoServiceProvider class or the CryptGenRandom CryptoAPI maybe similarly used.

 

Finally, like with most security actions, all activity must be logged and then audited. However, developers must be careful to not log clear text passwords or social security numbers for instance. The application should also let the user know via email whenever any user management activity is performed on his / her account. For instance, if the user’s account is locked out due to failed password attempts then an email must be sent to the user. Thus, if the user did not perform these failed attempts he / she can always bring it to the notice of the corporate security department for further investigation.

 

In the .NET 2.0 release, Microsoft has provided a set of features known as Membership[5] as well as security controls for login, password resets and other user management functions. These allow ASP.NET developers to provide out of the box user management based on a provider architecture. This provider architecture by default supports both Microsoft SQL Server and Microsoft Active Directory. This feature is tremendously configurable allowing for setting up of password complexity rules, definition of password reset mechanisms and password storage formats purely through declarative programming in the web.config file and without writing much code. Moreover it is also extensible to support custom providers and when combined with the health monitoring feature that is also new to .NET 2.0 provides for a number of the best practices described in this article.

 

Session Management

The final member of this quartet of security mechanisms is session management. Application developers especially those creating web applications must pay special attention to this important mechanism. This includes aspects such as the security of the security tokens and session inactivity timeouts. Session hijacking through session identifier or cookie stealing is a common flaw that plagues a number of web applications. Essentially an attacker simply obtains the session identifier value and then crafts a request that contains that ID. When that request reaches the server, the application will simply look up its session data store and determine that the user was logged in and will therefore provide access to all the resources that are available to that user. As a result, an attacker could potentially get unauthorized access to another user’s data.

 

Designers and developers should leverage the underlying frameworks (whether J2EE or ASP/ASP.NET) session management capabilities as far as possible. These capabilities typically manifest themselves via a session ID. Infrastructure supplied session IDs have the advantage of being sufficiently random (for instance the ASP.NET session ID has 120 bits of entropy) so that an attacker cannot attempt a guessing or brute force attack. The application must never rely on just the username submitted with a request when determining the session to which the request belongs to. Session IDs issued by the application frameworks also typically have a relatively short and configurable lifetime and thus can prevent the “permanently logged in” effect.

 

If an application cannot avoid creating its own session management mechanism, for instance if the underlying application server does not support sessions, then the following guidelines can be helpful. Cookies should be the preferred mechanism for storing the session identifier. Cookieless sessions while technically possible are far more difficult to secure since some of the security flags described below are not available. Hence, all of the onus for security would then fall onto the application developer.

 

When using cookies, developers must clearly define the cookie path, expiration date and time as well as ensure that the cookie is not persistent. After a maximum of thirty minutes of inactivity, the user must be forced to re-login so as to decrease the attack surface. Further cookies must have the secure flag turned on. This ensures that the browser will never transmit this cookie in a clear text request. Another common mistake that developers often make is to not issue a fresh session ID when the application switches from an insecure protocol (HTTP - used typically before a user logs in to the application) to a secure protocol (HTTPS - after log in). Thus an attacker who has obtained a cookie by sniffing traffic can wait for the legitimate user to log in and then use that cookie to impersonate him / her.

 

Session IDs when generated must have sufficient entropy so that an attacker cannot guess a valid session ID value and thus hijack that specific session. It is typically recommended that all application defined session identifiers or cookies must have at least 128 bits of entropy. This typically equates to 16 or more ASCII characters. Further, such session identifiers must not contain sensitive information such as passwords or easily guessable parts such as the username or sequential user ID numbers from a database. While not required a number of common implementations such as the one available in ASP.NET by default also sign and encrypt the session identifier thus protecting its content.

 

When the user is logged out, the session must be invalidated both on the server side and the client side. This is typically done by deleting the session entry from the server session data store as well as by clearing the cookie in the client application or browser and in the history.

 

Finally, since cross site scripting (XSS) represents one of the most common vectors for stealing session identifiers today. While mitigation against XSS is the topic of a future article on data validation a defense in depth session management strategy can help mitigate some of the risk. The HttpOnly cookie attribute prevents access to the cookie through client side JavaScript. While this is currently supported only in Microsoft Internet Explorer 6.0 above, it can help prevent a malicious script from obtaining the session identifier from the document.cookie HTML DOM object.

 

Conclusion

The mechanisms of authentication, authorization, user management and session management are in most applications responsible for the most security. Consequently they also bear the brunt of most attacks. However, we hope that just like the others in this series of articles have shown, this article again reemphasizes that building security into your applications is not difficult or impossible. Instead all it needs is adherence to best practices and focus from the early stages in an application’s development lifecycle. Especially with these four, security cannot be slapped on at the end. These represent the core of the application’s architecture and therefore must be part of the design from day one.

 

Summary

Strong authentication helps protect a system at all of its entry points. Authorization then helps to protect the system once the user is inside it i.e. has authenticated. Session management allows users to have a clean and productive user experience while still keeping security paramount. In some sense session management can be thought of as repeated authentication. Finally, user management is what brings all of this together and has both administrative functions as well as end-user operations. The bond that ties all of these together is the principle. While these four sound remarkably simple and while infrastructure support for them is increasing dramatically, they are also perhaps the single biggest source of security vulnerabilities in most applications.

About This Page

Title: User & Session Management
Moderated By:
Created: 02-25-2007, 21:23
Modified: 02-25-2007, 23:27
Last Modified By: rudolph
Revision Number: 5

Common Tasks

Powered by Community Server (Personal Edition), by Telligent Systems