Securing Authentication

Implementing a secure authentication solution involves attempting to simultaneously meet several key security objectives, and in many cases trade off against other objectives such as functionality, usability, and total cost. In some cases “more” security can actually be counterproductive — for example, forcing users to set very long passwords and change them frequently will often lead users to write their passwords down. Because of the enormous variety of possible authentication vulnerabilities, and the potentially complex defenses that an application may need to deploy in order to mitigate against all of them, many application designers and developers choose to accept certain threats as a given and concentrate their efforts on preventing the most serious attacks. Factors to consider in striking an appropriate balance include:

■ The criticality of security given the functionality offered by the application.
■ The degree to which users will tolerate and work with different types of authentication controls.
■ The cost of supporting a less user-friendly system.
■ The financial cost of competing alternatives in relation to the revenue likely to be generated by the application or the value of the assets it is protecting.

Use Strong Credentials

■ Suitable minimum password quality requirements should be enforced. These may include rules regarding: minimum length; the appearance of alphabetical, numeric, and typographical characters; the appearance of both uppercase and lowercase characters; the avoidance of dictionary words, names, and other common passwords; the prevention of a password being set to the username; and the prevention of a similarity or match with previously set passwords. As with most security measures, different password quality requirements may be appropriate for different categories of user.

■ Usernames should be unique.

■ Any system-generated usernames and passwords should be created with sufficient entropy that they cannot feasibly be sequenced or predicted even by an attacker who gains access to a large sample of successively generated instances.

■ Users should be permitted to set sufficiently strong passwords — for example, long passwords should be allowed, and a wide range of characters should be allowed.

Handle Credentials Secretively

■ All credentials should be created, stored, and transmitted in a manner that does not lead to unauthorized disclosure.

■ All client-server communications should be protected using a well-established cryptographic technology, such as SSL. Custom solutions for protecting data in transit are neither necessary nor desirable.

■ If it is considered preferable to use HTTP for the unauthenticated areas of the application, ensure that the login form itself is loaded using HTTPS, rather than switching to HTTPS at the point of the login submission.

■ Only POST requests should be used for transmitting credentials to the server. Credentials should never be placed in URL parameters or cookies (even ephemeral ones). Credentials should never be transmitted back to the client, even in parameters to a redirect.

■ All server-side application components should store credentials in a manner that does not allow their original values to be easily recovered even by an attacker who gains full access to all the relevant data within the application’s database. The usual means of achieving this objective is to use a strong hash function appropriately salted to reduce the effectiveness of precomputed offline attacks.

■ Client-side “remember me” functionality should in general only remember non secret items such as usernames. In less security-critical applications, it may be considered appropriate to allow users to opt in to a facility to remember passwords. In this situation, no clear-text credentials should be stored on the client (the password should be stored reversibly encrypted using a key known only to the server), and users should be warned about the risks from an attacker with physical access to their computer or who compromises their computer remotely. Particular attention should be paid to eliminating cross-site scripting vulnerabilities within the application that may be used to steal stored credentials.

■ A password change facility should be implemented and users should be obliged to change their password periodically.

■ Where credentials for new accounts are distributed to users out-of- band, these should be sent as securely as possible, be time-limited, and require the user to change them on first login, and the user should be told to destroy the communication after first use.

■ Where applicable, consider capturing some of the user’s login information (for example, single letters from a memorable word) using drop down menus rather than text fields. This will prevent any keyloggers installed on the user’s computer from capturing all of the data they submit.

Validate Credentials Properly

■ Passwords should be validated in full — that is, in a case-sensitive way, without filtering or modifying any characters, and without truncating the password.

■ The application should be aggressive in defending itself against unexpected events occurring during login processing. For example, depending on the development language in use, the application should use catch-all exception handlers around all API calls. These should explicitly delete all session and method-local data being used to control the state of the login processing and should explicitly invalidate the current session, thereby causing a forced logout by the server even if authentication is somehow bypassed.

■ All authentication logic should be closely code-reviewed, both as pseudo-code and as actual application source code, to identify logic errors such as fail-open conditions.

■ If functionality to support user impersonation is implemented, this should be strictly controlled to ensure that it cannot be misused to gain unauthorized access. Because of the criticality of the functionality, it is often worthwhile to remove this functionality entirely from the public-facing application, and implement it only for internal administrative users, whose use of impersonation should be tightly controlled and audited.

■ Multistage logins should be strictly controlled to prevent an attacker from interfering with the transitions and relationships between the stages:

    ■ All data about progress through the stages and the results of previous validation tasks should be held in the server-side session object and should never be transmitted to or read from the client.
■ No items of information should be submitted more than once by the user, and there should be no means for the user to modify data that has already been collected and/or validated. Where an item of data such as a username is used at multiple stages, this should be stored in a session variable when first collected, and referenced from there
■ The first task carried out at every stage should be to verify that all prior stages have been correctly completed. If this is not the case, the authentication attempt should immediately be marked as bad.
■ To prevent information leakage about which stage of the login failed (which would enable an attacker to target each stage in turn), the application should always proceed through all stages of the login, even if the user has failed to complete earlier stages correctly, and even if the original username was invalid. After proceeding through all of the stages, the application should present a generic “login failed” message at the conclusion of the final stage, without providing any information about where the failure occurred.

■ Where a login process includes a randomly varying question, ensure that an attacker is not able to effectively choose his own question:
■ Always employ a multistage process in which users identify them- selves at an initial stage, and the randomly varying question is presented to them at a later stage.
■ When a given user has been presented with a given varying question, store that question within their persistent user profile, and ensure that the same user is presented with the same question on each attempted login until they successfully answer it.
■ When a randomly varying challenge is presented to the user, store the question that has been asked within a server-side session variable, rather than a hidden field in an HTML form, and validate the subsequent answer against that saved question.

Prevent Information Leakage

■ The various authentication mechanisms used by the application should not disclose any information about authentication parameters, either through overt messages or through inference from other aspects of the application’s behavior. An attacker should have no means of determining which piece of the various items submitted has caused a problem.

■ A single code component should be responsible for responding to all failed login attempts, with a generic message. This avoids a subtle vulnerability that can occur when a supposedly uninformative message returned from different code paths can actually be discriminated by an attacker, due to typographical differences in the message, different HTTP status codes, other information hidden in HTML, and the like.

Prevent Brute-Force Attacks

■ Measures need to be enforced within all of the various challenges implemented by the authentication functionality in order to prevent attacks that attempt to meet those challenges using automation. This includes the login itself, as well as functions to change password, to recover from a forgotten password situation, and the like.

■ Using unpredictable usernames and preventing their enumeration presents a significant obstacle to completely blind brute-force attacks, and requires an attacker to have somehow discovered one or more specific usernames before mounting an attack.

Prevent Misuse of the Password Change Function

■ A password change function should always be implemented, to allow periodic password expiration (if required) and to allow users to change passwords if they wish to for any reason. As a key security mechanism, this needs to be very well defended against misuse.
■ The function should only be accessible from within an authenticated session.
■ There should be no facility to provide a username, either explicitly or via a hidden form field or cookie — users have no legitimate need to attempt to change other people’s passwords.
■ As a defense-in-depth measure, the function should be protected from unauthorized access gained via some other security defect in the application — such as a session hijacking vulnerability, cross-site scripting, or even an unattended terminal. To this end, users should be required to reenter their existing password.
■ The new password should be entered twice to prevent mistakes, and the application should compare the “new password” and “confirm new password” fields as its first step and return an informative error if they do not match.
■ The function should prevent the various attacks that can be made against the main login mechanism: a single generic error message should be used to notify users of any error in existing credentials, and the function should be temporarily suspended following a small number of failed attempts to change password.
■ Users should be notified out-of-band (e.g., via email) that their pass word has been changed, but the message should not contain either their old or new credentials.

NEXT is..Attacking Session Management.,.,,.,.,.,.,,.,.,.