Difference between revisions of "Guide to Authentication"

From OWASP
Jump to: navigation, search
(Authentication)
(Authentication)
Line 1,256: Line 1,256:
  
 
  '''protected.cfm'''
 
  '''protected.cfm'''
 
+
[[Category:FIXME|I am not sure why this isn't formatting as a heading]]
  
 
  <pre>
 
  <pre>
Line 1,295: Line 1,295:
  
 
  '''Login.cfm'''
 
  '''Login.cfm'''
 
+
[[Category:FIXME|I am not sure why this isn't formatting as a heading]]
  
 
<pre>
 
<pre>

Revision as of 12:31, 27 August 2008

Development Guide Table of Contents

Contents


Objective

To provide secure authentication services to web applications, by:

  • Tying a system identity to an individual user by the use of a credential
  • Providing reasonable authentication controls as per the application’s risk
  • Denying access to attackers who use various methods to attack the authentication system

Environments Affected

All.

Relevant COBIT Topics

DS5 – All sections should be reviewed. This section covers nearly all COBIT detailed control objectives.

Best Practices

  • Authentication is only as strong as your user management processes, and in particular the user issuance and evidence of identity policies. The stronger the requirement for non-repudiation, the more expensive the process is.
  • Use the most appropriate form of authentication suitable for your asset classification. For example, username and password is suitable for low value systems such as blogs and forums, SMS challenge response is suitable for low value e-commerce systems (in 2005), whilst transaction signing is suitable for high value systems such as high value e-commerce (all e-commerce sites should consider it by 2007), banking and trading systems.
  • Re-authenticate the user for high value transactions and access to protected areas (such as changing from user to administrative level access)
  • Authenticate the transaction, not the user. Phishers rely on poorly implemented user authentication schemes. User authentication is valuable, but the real business value comes not from authenticating users because usernames and passwords can be stolen. Real security value stems from identifying fraudulent transactions. Unfortunately this can be significantly more complex.
  • Passwords are trivially broken and are unsuitable for high value systems. Therefore, the controls should reflect this. Passwords shorter than 16 characters are very susceptible to brute force attacks, so set your password policy to be reasonable:
  1. Train your users as to suitable password construction
  2. Allow your users to write down their passwords as long as they keep them safe
  3. Encourage users to use pass phrases instead of passwords
  4. Relax password expiry requirements upon the strength of the password chosen – passwords between 8 and 16 that cannot be easily cracked should have an expiry of no less than 30 days, and pass phrases above 16 characters probably do not need a hard expiry limit, but a gentle reminder after, for example, 90 days instead.

Common web authentication techniques

Basic and Digest authentication

Nearly all web and application servers support the use of Basic and Digest authentication. This requires the web browser to put up a dialog box to take the user’s name and password, and send them through to the web server, which then processes them against its own user database, or in the case of IIS, against Active Directory.

  • Basic authentication sends the credential in the clear. It should not be used unless in combination with SSL. All communication must be done over HTTPS during the user’s session because obfuscated credentials are sent with every request.
  • HTTP 1.0 Digest authentication only obfuscates the password using easily-reversible Base64 encoding. It should not be used.
  • HTTP 1.1 Digest authentication uses a challenge response mechanism, which is reasonably safe for low value applications.

The primary reason against the use of Basic or Digest authentication is due to:

  • Insecure transmission of credentials
  • Both require SSL to provide any form of confidentiality and integrity
  • The user interface is reasonably ugly and can be confusing to some users and thus bad for usability
  • Does not provide a great deal of control to the end application. These authentication mechanisms are typically handled by the web server before requests reach the application in question. Linking these authentication mechanisms to arbitrary user data stores such as a custom database can be difficult and require writing web server pugins in languages such as C or Perl rather than the application implementation language.

This is not to say that Basic or Digest authentication is not useful. It can be used to shield development sites against casual use or to protect low value administrative interfaces, but other than that, this form of authentication is not recommended.

Forms based authentication

Forms based authentication provides the web application designer the most control over the user interface and user data store, and thus it is widely used. It is available and well-supported for both J2EE and ASP.NET platforms.

Forms based authentication requires the application to do a fair amount of work to implement authentication and authorization. Rarely do web applications get it right. The sections on how to determine if you are vulnerable have upwards of 15 specific controls to check, and this is the minimum required to authenticate with some safety.

If at all possible, if you choose to use forms based authentication, try to re-use a trusted access control component rather than writing your own.

Forms based authentication suffers from:

  • Replay attacks
  • Man in the middle attacks
  • Clear text credentials if not used over HTTPS
  • Luring attacks
  • Weak password controls

And many other attacks as documented in the “How to determine if you are vulnerable”

It is vital that you protect login interchanges using SSL, and implement as many controls as possible. A primary issue for web application designers is the cost to implement these controls when the value of the data being protected is not high. A balance needs to be struck to ensure that security concerns do not outweigh a complex authentication scheme.

Integrated authentication

Integrated authentication is most commonly seen in intranet applications using Microsoft IIS web server and ASP.NET applications. Most other web servers do not offer this choice. Although it can be secure – on a par with client-side certificate authentication due to the use of Kerberos-based Active Directory integration (which means no credentials need to be stored by the application or typed by the user), it is not common on Internet facing applications due to its Window- and Active Directory-centric nature.

If you are developing an intranet application and your development environment supports integrated authentication, you should use it. It means less work for you to develop authentication and authorization controls, one less credential for users to remember, and you can re-use pre-existing authentication and authorization infrastructure.

Certificate based authentication

Certificate based authentication is widely implemented in many web and application servers. The web site issues certificates (or attempts to trust externally issued certificates). The public certificates are loaded into the web server’s authentication database, and compared with an offering from incoming browser sessions. If the certificates match up, the user is authenticated.

The quality of authentication is directly related to the quality of the public key infrastructure used to issue certificates. A certificate issued to anyone who asks for them is not as trustworthy as certificates issued after seeing three forms of photo identification (such as passport, driver’s license or national identification card).

There are some drawbacks to certificate-based logon:

  • Many users share PCs and they need to have bring their certificates along with them. This is non-trivial if the user had the application install the certificate for them – most users are completely unaware of how to export and import certificates
  • The management of certificates on a browser is non-trivial in many instances
  • Certificate revocation with self-issued certificates is almost impossible in extranet environments
  • Trust of “private” certificate servers requires end-user trust decisions, such as importing root CA certificates. End users are typically not qualified to make this trust decision
  • The cost of certificates and their part in the business model of public certificate companies is not related to the cost of provision, and thus it is expensive to maintain a public certificate database with a large number of users

Coupled with the poor management of many CA’s, particularly regarding certificate renewal, the implementation of certificate-based logon schemes has often failed. A good example is Telstra’s online billing service. At one stage, only digital certificates were acceptable. Now, this requirement is being relaxed.

Strong Authentication

Strong authentication (such as tokens, certificates, etc) can provide a higher level of security than username and passwords alone. The generalized form of strong authentication is “something you know, something you hold”. Therefore, anything that requires a secret (the “something you know”) and authenticator like a token, USB fob, or certificate (the “something you hold”) is a stronger control than username and passwords (which is just “something you know”) or biometrics (“something you are”).

When to use strong authentication

Certain applications should use strong authentication:

  • For high value transactions (note that the definition of a high-value transaction may well be determined in part by the cost of implementing so-called strong authentication)
  • Where privacy is a strong or legally compelled consideration (such as health records, government records, etc)
  • Where audit trails are legally mandated and require a strong association between a person and the audit trail, such as banking applications
  • Administrative access for high value or high risk systems

What does high risk mean?

Every organization has a certain threshold for risk, which can range from complete ignorance of risk all the way through to paranoia.

For example, forum software discussing gardening most likely does not require strong authentication, whereas administrative access to a financial application processing millions of dollars of transactions daily should be mandated to use strong authentication.

Biometrics are not strong authentication … by themselves

Biometrics can be the “something you hold”, but they do not replace the “something you know”. You should always use biometrics along with username and passwords, as otherwise, it significantly weakens the trust in the authentication mechanism.

Biometrics are not as strong as other forms of strong authentication for remotely accessible web applications because:

The devices are in the control of the attacker – and most low end biometric devices are not tamperproof nor do they have strong replay protection

  • Remote enrollment cannot be trusted – users might substitute others, enroll a glass eye, or a picture out of a magazine.
  • The biometric features being measured cannot be revoked – you only have two eyes, ten fingers and one face. This is a deadly combination for high value systems – attackers have previously shown they will cut off fingers to obtain a car. Biometrics are thus too risky for high value systems.
  • The biometric features being measured do not change; USB keys with inbuilt crypto engines and other fobs have a pseudo-random output that changes every 30 seconds. Distinguishing features such as loops and whirls do not.
  • There are high false positive rates compared to the cost of the authentication mechanism. With other forms of strong authentication, there are no false accepts.
  • Most consumer biometric devices are easily spoofed or subject to replay attacks. The more expensive devices are not necessarily much better than their affordable counterparts, but for the same price as a high end biometric device, you can own 50 or 60 fobs and upwards of 1000 smart cards.

When used in a single factor authentication method (for example, just a thumbprint with no username or password), biometrics are the weakest form of authentication available and are unsuitable for even moderate risk applications. Such usage should be restricted to devices the user owns without sensitive or risky data.

Relative strengths and uses of strong authentication

One-time passwords

One time password fobs are cheap – many can be obtained for as little as $5-10, but they only protect against password replay. One time password fobs usually have a number displayed on a screen, and the user will type in their username, pass phrase and the one time password.

One time passwords do not help with man-in-the-middle attacks and as they do not present any details of the use to the user, so spoofed web sites could collect a one time password and log on as the user and perform a transaction.

Soft certificates

Soft certificates (also known as client-side certificate authentication) are a little stronger than passwords, but suffer from the same problems as passwords and any authentication method which automatically processes credentials. The usability and infrastructure issues with certificate-based authentication have been mentioned previously.

Connected hard certificates

USB, PC Card, or otherwise connected tokens which can be programmatically interrogated by the user’s system seem like the best way to store a credential. Although they typically protect against unauthorized duplication of the credential and tampering of the algorithm, as the device is connected to an untrusted host, the hard certificate might be used by an attacker’s site directly, bypassing the otherwise robust authentication mechanism provided.

Most tokens pop up a window that asks the user for permission to supply the credential. An attacker could pop up a similar window, obtain the authentication blob, and forward it to the real system whilst performing an entirely different transaction. This attack works due to two reasons:

  • Chrome on authentication request window – the pop up has no clear relationship between application and authentication. This is a problem with all JavaScript alerts, and not unique to this functionality
  • User brain bypass – most users familiar with an application will simply agree to a dialog they see all the time. As long as the attacker makes a good facsimile of the authentication approval window, they will agree to it

Many other issues surround connected devices, including desktop support issues if the drivers for the hard certificate interfere with the operation of the user’s computer.

Connected devices are suitable for trusted internal access, and closed and trusted user communities.

Challenge Response

Challenge response tokens work by taking a value (challenge) from the system and processing them in a cryptographically secure fashion to derive a result.

Challenge response calculators have a keypad, and therefore the password is usually considered to the be the PIN required to access the calculator. The user enters their username and response into the system, which is verified by the authentication server.

Although protecting against replay attacks, challenge response tokens suffer from authentication disconnection issue discussed above. The user is approving something, but it is not clear what.

SMS Challenge Response

SMS challenge works in countries with a high penetration of text message capable mobile phones. The typical method is to enrol the user in a trusted fashion, registering their mobile phone number. When an authentication or transaction signing is required, the application sends the user a transaction number to their mobile phone, hopefully with some surrounding text to verify what is being signed (such as the reference ID of the transaction).

Problems with SMS challenge response include:

  • It’s a public path; do not send sensitive information with the challenge
  • If sending the transaction amount, the user may trust this figure, but an attacker may send the user one figure and approve another
  • You are not the only source of SMS messages; the user can not verify the source of the SMS beyond only expecting them when they are using the system

Despite this, SMS challenge response is significantly stronger than username and password with minimal cost overheads. It can be effective as long as the account was set up properly in the first place (and not by an attacker). SMS challenge response can help to prevent the subversion of legitimate accounts.

Transaction Signing

Transaction signing is performed by offline challenge response calculators. The user will be presented with various items to enter into the calculator, and it will calculate a response based upon these inputs. This is the strongest form of authentication as the user has to enter the transaction details – any other transaction will fail to produce a suitable response. This type of authentication has strong non-repudiation properties, is robust against man in the middle attacks, cannot be replayed, and is robust against differing transaction limits.

For the best effect, at least the following should be stirred into the challenge:

  • Reference ID
  • From account
  • Amount of the transaction

The tokens are usually date and time based, so there’s only a little to be gained by entering the transaction date. The downsides of these tokens are

  • It can take up to 20 to 40 keystrokes to complete a transaction, which is problematic if the user has to approve each and every transaction
  • If a token is connected to the user’s computer or uses some form of automated entry, although the human factors are better (no details to enter), the non-repudiation property is removed as the user no longer is required to think about the value of the transaction – they just approve the signing window, which is no better than a soft-certificate.

Therefore, although most of the calculators for transaction signing allow connection to the client computer, this functionality should not be used or made available.

Although transaction signing calculators and EMV (smart card) style calculators are identical in functionality from the application’s point of view, they have different values to the user. A calculator will be left on a desk for all to see, whereas an EMV smart card masquerading as the user’s corporate credit card has the appropriate value to the user – they will not leave them on the desk or in their unlocked drawer. The value of the system should decide which type of transaction signing token is provided to the user.

Challenges to using strong authentication

Most common application frameworks are difficult to integrate with strong authentication mechanisms, with the possible exception of certificate-based logon, which is supported by J2EE and .NET.

Your code must be integrated with an authentication server, and implicitly trust the results it issues. You should carefully consider how you integrate your application with your chosen mechanism to ensure it is robust against injection, replay and tampering attacks.

Many organizations are wary of strong authentication options as they are perceived to be “expensive”. They are, but so are passwords. The costs of user management are not usually related to the cost of the authentication infrastructure, but relate instead to the issuance and maintenance of the user records. If there is a requirement to have strong non-repudiation the most formidable and costly aspect of user management is enrolment, maintenance and de-enrolment. Simply sending any user who asks for an account a token or certificate provides no certainty that the user is who they say they are. A robust trusted enrolment path is required to ensure that the authentication system is “strong”.

Federated Authentication

Federated authentication allows you to outsource your user database to a third party, or to run many sites with a single sign on approach. The primary business reason for federated security is that users only have to sign on once, and all sites that support that authentication realm can trust the sign-on token and thus trust the user and provide personalized services.

Advantages of federated authentication:

  • Reduces the total number of credentials your users have to remember
  • Can be appropriate when your site(s) are part of a large trading partnership, such as an extranet procurement network
  • Potentially allows your application to provide personalized services to otherwise anonymous users.

You should not use federated authentication unless:

  • You trust the authentication provider
  • Your privacy compliance requirements are met by the authentication provider

The Laws of Identity

Kim Cameron, Identity Architect of Microsoft has established a group blog focusing on the risks surrounding federated identity schemes. The blog established a set of papers, with seven laws of identity. These are:

  1. User Control and Consent: Digital identity systems must only reveal information identifying a user with the user's consent.
  2. Limited Disclosure for Limited Use: The solution which discloses the least identifying information and best limits its use is the most stable, long-term solution.
  3. The Law of Fewest Parties: Digital identity systems must limit disclosure of identifying information to parties having a necessary and justifiable place in a given identity relationship.
  4. Directed Identity: A universal identity metasystem must support both "omnidirectional" identifiers for use by public entities and "unidirectional" identifiers for private entities, thus facilitating discovery while preventing unnecessary release of correlation handles.
  5. Pluralism of Operators and Technologies: A universal identity metasystem must channel and enable the interworking of multiple identity technologies run by multiple identity providers.
  6. Human Integration: A unifying identity metasystem must define the human user as a component integrated through protected and unambiguous human-machine communications.
  7. Consistent Experience Across Contexts: A unifying identity metasystem must provide a simple consistent experience while enabling separation of contexts through multiple operators and technologies.

Source: http://www.identityblog.com/stories/2005/05/13/TheLawsOfIdentity.html

It is unclear at the time of writing if these “laws” will end up changing the identity landscape, but many of the issues discussed in the laws should be considered by implementers of federated authentication.

SAML

SAML is a part of the Liberty Alliance’s mechanism to provide federated authentication, although it is not just for federated authentication.

At the time of writing, there is no direct support for SAML in any major off-the-shelf application framework (J2EE, PHP, or .NET). Third party libraries, including open source implementations, are available for J2EE. Microsoft has (very) limited support for SAML in the Web Services Enhancement 2.0 SP2, which requires .NET Framework 1.1.

For more details on how the SAML protocol works, see the Web Services chapter.

Microsoft Passport

Microsoft Passport is an example of federated authentication, used for Hotmail, delivery of software, instant messaging, and for a time, by partners such as eBay. Microsoft’s .NET framework supports Passport sign-on. There is limited support on other platforms. However, Microsoft has withdrawn partner Passport usage, so essentially Passport is no longer a viable option and is not discussed further.

Considerations

Adoption of federated authentication has been limited thusfar, and unless your business requirements state that you need to support single-sign on with many different bodies, you should avoid the use of federated sign-on.

Client side authentication controls

Client-side validation is most often used in combination with forms-based authentication. Client-side validation scripts (usually written in JavaScript) are a good control to provide immediate feedback for users if they violate business rules. This can lighten the load of the web server by eliminating requests from round trips that are bound to fail. However, client-side validation is trivially bypassed. It is of benefit largely to web site usability and should not be considered a legitimate security precaution.

How to determine if you are vulnerable

To test, reduce the login page to just a basic form as a local static HTML file, with a POST action against the target web server. You are now free to violate client-side input validation. This form is also much easier to use with automated attack tools.

Also, web request proxy tools can be used to submit a legitimate login request via a browser and then change the values in transit before the reach the web application server. If you are able to use web proxies to submit invalid logon data to server-side logon routines then the application might be vulnerable if it does not properly handle the malformed inputs.

How to protect yourself

To protect your application, ensure that every validation and account policy / business rule is checked on the server-side.

For example, if you do not allow blank passwords (and you shouldn’t), this should be tested at the least on the server-side, and optionally on the client-side. This goes for “change password” features, as well.

For more information, please read the Validation section in this book.

Positive Authentication

Unfortunately, a generic good design pattern for authentication does not fit all cases. However, some designs are better than others. Authentication should be a fail-closed process; a user is assumed to be anonymous until they have positively identified themselves to the system.

If an application uses the following pseudo-code to authenticate users, any form of fall through will end up with the user being authenticated due to the false assumption that users mostly get authentication right:

''bAuthenticated := true''

''try {''

''userrecord := fetch_record(username)''

''if userrecord[username].password != sPassword then''

''bAuthenticated := false''

''end if''

''if userrecord[username].locked == true then''

''	bAuthenticated := false''

''end if''

''	…''

''}''

''catch {''

''	// perform exception handling, but continue''

''}''

How to determine if you are vulnerable

To test, try forcing the authentication mechanism to fail.

If a positive authentication algorithm is in place, it is likely that any failure or part failure will end up allowing access to other parts of the application. In particular, test any cookies, headers, or form or hidden form fields extensively. Play around with sign, type, length, and syntax. Inject NULL, Unicode and CRLF, and test for XSS and SQL injections. See if race conditions can be exploited by single stepping two browsers using a JavaScript debugger.

How to protect yourself

The mitigation to positive authentication is simple: force negative authentication at every step:

''bAuthenticated := false''

''securityRole := null''

''try {''

''userrecord := fetch_record(username)''

''if userrecord[username].password != sPassword then''

''	throw noAuthentication''

''end if''

''if userrecord[username].locked == true then''

''	throw noAuthentication''

''end if''

''if userrecord[username].securityRole == null or banned then''

''	throw noAuthentication''

''end if''


… other checks …

''bAuthenticated := true''

''securityRole := userrecord[username].securityRole''

''}''

''catch {''

''bAuthenticated := false''

''securityRole := null''



''// perform error handling, and stop''

''}''

''return bAuthenticated''


By asserting that authentication is true and applying the security role right at the end of the try block stops authentication fully and forcefully.

Multiple Key Lookups

Code that uses multiple keys to look up user records can lead to problems with SQL or LDAP injection. For example, if both the username and password are used as the keys to finding user records, and SQL or LDAP injection is not checked, the risk is that either field can be abused.

For example, if you want to pick the first user with the password “password”, bypass the username field. Alternatively, as most SQL lookup queries are written as “select * from table where username = username and password = password, this knowledge may be used by an attacker to simply log on with no password (ie truncating the query to “select * from username=’username’; -- and password = ‘don’t care’’”). If username is unique, it is the key.

How to determine if you are vulnerable

Your application is at risk if all of the following are true:

  • More than just the username is used in the lookup query
  • The fields used in the lookup query (eg, username and password) are unescaped and can be used for SQL or LDAP injection

To test this, try:

  • Performing a SQL injection (or LDAP injection) against the login page, masking out one field by making it assert to true:
Login: a’ or ‘1’=’1

Password: password

Login: a)(|(objectclass=*)

Password: password

If the above works, you’ll authenticate with the first account with the password “password”, or generate an error that may lead to further breaks. You’d be surprised how often it works.

How to protect yourself

  • Strongly test and reject, or at worst sanitize - usernames suitable for your user store (ie aim to escape SQL or LDAP meta characters)
  • Only use the username as the key for queries
  • Check that only zero or one record is returned


Java

public static bool isUsernameValid(string username) {

RegEx r = new Regex(“^[A-Za-z0-9]{16}$”);

return r.isMatch(username);

}


// java.sql.Connection conn is set elsewhere for brevity. 


PreparedStatement ps = null;

RecordSet rs = null;


try {

isSafe(pUsername);

ps = conn.prepareStatement(“SELECT * FROM user_table WHERE username = ‘?’”);

ps.setString(1, pUsername);

rs = ps.execute();

if ( rs.next() ) {

// do the work of making the user record active in some way

}

}

catch (…) {

…

}

.NET (C#)


 public static bool isUsernameValid(string username) {

RegEx r = new Regex(“^[A-Za-z0-9]{16}$”);

Return r.isMatch(username);

}



… 

try {

string selectString = " SELECT * FROM user_table WHERE username = @userID”;

// SqlConnection conn is set and opened elsewhere for brevity. 

SqlCommand cmd = new SqlCommand(selectString, conn);

if ( isUsernameValid(pUsername) ) {

cmd.Parameters.Add("@userID", SqlDbType.VarChar, 16).Value = pUsername;



SqlDataReader myReader = cmd.ExecuteReader();

If ( myReader.

// do the work of making the user record active in some way.

myReader.Close();

}

catch (…) {

…

}

Referer Checks

Referer is an optional HTTP header field that normally contains the previous location (ie the referrer) from which the browser came from. As the attacker can trivially change it, the referrer must not be used to make security decisions, as attackers are more likely to use the correct referrer to bypass controls in your application than to use invalid or damaging content.

In general, applications are better off if they do not contain any referrer code.

How to determine if you are vulnerable

The vulnerability comes in several parts:

  • Does your code check the referrer? If so, is it completely necessary?
  • Is the referrer code simple and robust against all forms of user attack?
  • If you use it to construct URLs? Don’t as it’s nearly impossible test all valid URLs

For example, if login.jsp can only be invoked from http://www.example.com/index.jsp, the referrer should check that the referrer is this value.

How to protect yourself

For the most part, using the referer field is neither desirable nor useful as it so easily modified or spoofed by attackers. Little to no trust can be assigned to its value, and it can be hard to sanitize and use properly.

Programs that display the contents of referrer fields such as web log analyzers must carefully protect against XSS and other HTML injection attacks.

If your application has to use the referrer, it should only do so as a defense in depth mechanism, and not try to sanitize the field, only reject it if it’s not correct. All code has bugs, so minimize the amount of code dealing with the referrer field.

For example, if login.jsp can only be invoked from http://www.example.com/index.jsp, the referrer could check that the referrer is this value.


Java

HttpServletRequest request = getRequest();

if ( ! request.getHeader(“REFERER”).equals(“<u>http://www.example.com/index.jsp</u>”) ) {

	throw …

}


.NET (C#)


 if ( Request.ServerVariables(“HTTP_REFERER”) != ‘<u>http://www.example.com/default.aspx</u>’ ) {

	throw …

}


PHP


if ( $_SERVER[‘HTTP_REFERER’] != ‘<u>http://www.example.com/index.php</u>’ ) {

	throw …

}


 ColdFusion



<cfif CGI.HTTP_REFERER IS NOT "http://www.example.com/index.cfm">

<cfthrow … />

</cfif>

}



But compared to simply checking a session variable against an authorization matrix, referrers are a weak authorization or sequencing control.

Browser remembers passwords

Modern browsers offer users the ability to manage their multitude of credentials by storing them insecurely on their computer.

How to determine if you are vulnerable

  • Clear all state from your browser. Often the most reliable way to do this is to create a fresh test account on the test computer and delete and re-create the account between test iterations
  • Use a browser and log on to the application
  • If the browser offers to remember any account credentials, your application is at risk.
  • This risk is particularly severe for applications that contain sensitive or financial information.

How to protect yourself

Modern browsers offer users the ability to manage their multitude of credentials by storing them insecurely on their computer.

In the rendered HTTP, send the following in any sensitive input fields, such as usernames, passwords, password re-validation, credit card and CCV fields, and so on:


<form … AUTOCOMPLETE="off"> - for all form fields

<input … AUTOCOMPLETE="off"> - for just one field

This indicates to most browsers to not to store that field in the password management feature. Remember, it is only a polite suggestion to the browser, and not every browser supports this tag.

Default accounts

A common vulnerability is default accounts - accounts with well known usernames and/or passwords. Particularly bad examples are:

  • Microsoft SQL Server until SQL 2000 Service Pack 3 with weak or non-existent security for “sa”
  • Oracle – a large number of known accounts with passwords (fixed with later versions of Oracle)

How to determine if you are vulnerable

  • Determine if the underlying infrastructure has no default accounts left active (such as Administrator, root, sa, ora, dbsnmp, etc)
  • Determine if the code contains any default, special, debug or backdoor credentials
  • Determine if the installer creates any default, special, debug credentials common to all installations
  • Ensure that all accounts, particularly administrative accounts, are fully specified by the installer / user.

There should be no examples or images in the documentation with usernames in them

How to protect yourself

  • New applications should have no default accounts.
  • Ensure the documentation says to determine that the underlying infrastructure has no default accounts left active (such as Administrator, root, sa, ora, dbsnmp, etc)
  • Do not allow the code to contain any default, special, or backdoor credentials
  • When creating the installer, ensure the installer does not create any default, special, credentials
  • Ensure that all accounts, particularly administrative accounts, are fully specified by the installer / user.
  • There should be no examples or images in the documentation with usernames in them

Choice of usernames

If you choose a username scheme that is predictable, it’s likely that attackers can perform a denial of service against you. For example, banks are particularly at risk if they use monotonically increasing customer numbers or credit card numbers to access their accounts.

How to determine if you are vulnerable

  • Bad username forms include:
  • Firstname.Lastname
  • E-mail address (unless the users are random enough that this is not a problem … or you’re a webmail provider)
  • Any monotonically increasing number
  • Semi-public data, such as social security number (US only – also known as SSN), employee number, or similar.
  • Bank account numbers (they can easily be observed on paper checks)

In fact, using the SSN as the username is illegal as you can’t collect this without a suitable purpose.

How to protect yourself

Where possible, allow users to create their own usernames. Usernames only have to be unique.

Usernames should be HTML, SQL and LDAP safe – suggest only allowing A..Z, a..z, and 0-9. If you wish to allow spaces, @ symbols or apostrophes, ensure you properly escape the special characters (see the Data Validation chapter for more details)

Avoid the use of Firstname.Lastname, e-mail address, credit card numbers or customer number, or any semi-public data, such as social security number (US only – also known as SSN), employee number, or similar.

Change passwords

Where the user has to remember a portion of the credential, it is sometimes necessary to change it, for example if the password is accidentally disclosed to a third party or the user feels it is time to change the password.

How to determine if you are vulnerable

To test:

  • Change the password then change the password again – if there are minimum periods before new passwords can be chosen (often 1 day), it should fail.

How to protect yourself

  • Ensure your application has a change password function.
  • The form must include the old password, the new password and a confirmation of the new password
  • Use AUTOCOMPLETE=off to prevent browsers from caching the password locally
  • If the user gets the old password wrong too many times, lock the account and kill the session

For higher risk applications or those with compliance issues, you should include the ability to prevent passwords being changed too frequently, which requires a password history. The password history should consist only of previous hashes, not clear text versions of the password. Allow up to 24 old password hashes.

Short passwords

Passwords can be brute forced, rainbow cracked (pre-computed dictionary attack), or fall to simple dictionary attacks. Unfortunately, they are also the primary method of logging users onto applications of all risk profiles. The shorter the password, the higher the success rate of password cracking tools.

How to determine if you are vulnerable

  • Determine if the application allows users no password at all. This should never be allowed.
  • Determine if the application allows users to use dangerously short passwords (less than four characters). Applications with a stronger authentication requirement will not allow this. Average applications should warn the user that it’s weak, but allow the change anyway. Poor applications will just change the password
  • Change the password to be increasingly longer and longer until the application warns the user of excessive password size. A good application will allow arbitrary password lengths, and thus will not warn at all

On each iteration, see if a shorter version of the password works (often only 8 or 16 characters is needed)

How to protect yourself

  • Ensure your application does not allow blank passwords
  • Enforce a minimum password length. For higher risk applications, prevent the user from using (a configurable) too short password length. For low risk apps, a warning to the user is acceptable for passwords less than six characters in length.
  • Encourage users to use long pass phrases (like “My milk shake brings all the boys to the yard” or “Let me not to the marriage of true minds Admit impediments”) by not strictly enforcing complexity controls for passwords over 14 characters in length
  • Ensure your application allows arbitrarily long pass phrases by using a decent one-way hash algorithm, such as AES-128 in digest mode or SHA-256 bit.

Weak password controls

ISO 17799 and many security policies require that users use and select reasonable passwords, and change them to a certain frequency. Most web applications are simply non-compliant with these security policies. If your application is likely to be used within enterprise settings or requires compliance with ISO 17799 or similar standards, it must implement Basic authentication controls. This does not mean that they need to be turned on by default, but they should exist.

How to determine if you are vulnerable

Determine if the application

  • Allows blank passwords
  • Allows dictionary words as passwords. This dictionary should be the local dictionary, and not just English
  • Allows previous passwords to be chosen. Applications with stronger authentication or compliance needs should retain a hashed password history to prevent password re-use

How to protect yourself

  • Allow for languages other than English (possibly allowing more than one language at a time for bi-lingual or multi-lingual locales like Belgium or Switzerland)
  • The application should have the following controls (but optionally enforce):
  • Password minimum length (but never maximum length)
  • Password change frequency
  • Password minimum password age (to prevent users cycling through the password history)
  • Password complexity requirements
  • Password history
  • Password lockout duration and policy (ie no lockout, lockout for X minutes, lockout permanently)

For higher risk applications, use a weak password dictionary helper to decide if the user’s choice for password is too weak.

Note: Complex frequently changed passwords are counterproductive to security. It is better to have a long-lived strong passphrase than a 10 character jumble changed every 30 days. The 30 days will ensure that PostIt™ notes exist all over the organization with passwords written down.

Reversible password encryption

Passwords are secrets. There is no reason to decrypt them under any circumstances. Help desk staff should be able to set new passwords (with an audit trail, obviously), not read back old passwords. Therefore, there is no reason to store passwords in a reversible form.

The usual mechanism is to use a cryptographic digest algorithm, such as MD5 or SHA-1. However, some forms have recently shown to be weak, so it is incumbent to move to stronger algorithms unless you have a large collection of old hashes.

How to determine if you are vulnerable

For custom code using forms-based authentication, examine the algorithm used by the authentication mechanism. The algorithm should be using AES-128 in digest mode, SHA-1 in 256 bit mode, with a salt.

  • Older algorithms such as MD5 and SHA-1 (with 160 bit hash output) have been shown to be potentially weak, and should no longer be used.
  • No algorithm (ie you see a clear text password) is insecure and should not be used
  • Algorithms, such as DES, 3DES, Blowfish, or AES in cipher mode, which allow the passwords to be decrypted should be frowned upon.

How to protect yourself

If you don’t understand the cryptography behind password encryption, you are probably going to get it wrong. Please try to re-use trusted password implementations.

  • Use AES-128 in digest mode or SHA-1 in 256 bit mode
  • Use a non-static salting mechanism
  • Never send the password hash or password back to the user in any form

Automated password resets

Automated password reset mechanisms are common where organizations believe that they need to avoid high help desk support costs from authentication. From a risk management perspective, password reset functionality seems acceptable in many circumstances. However, password reset functionality equates to a secondary, but much weaker password mechanism. From a forthcoming study (see references), it appears that password reset systems with five responses are the equivalent to two character passwords and require reversible or clear text passwords to be stored in the back end system, which is contrary to security best practices and most information security policies.

In general, questions required by password reset systems can be answered by information easily found from public records (mother’s maiden name, car color, etc). In many instances, the password reset asks for data that is illegal or highly problematic to collect, such as social security numbers. In most privacy regimes, you may only collect information directly useful to your application’s needs, and disclose to the user why you are collecting that information.

In general, unless the data being protected by your authentication mechanism is practically worthless, you should not use password reset mechanisms.

How to determine if you are vulnerable

Password reset mechanisms vary in complexity, but are often easily abused.

  • If password reset uses hints, check the hints for publicly known or semi-public information such as date of birth, SSN, mother’s name, etc. It should not use these as they can be found out from other sources and from social engineering.
  • There should no further clues in the underlying HTML.
  • If password reset uses the e-mail address as the key to unlocking the account, the resulting e-mail should not contain a password itself, but a one-time validation token valid only for a short period of time (say 15 minutes). If the token is good for a long period of time, check to see if the token is predictable or easy to generate.
  • If the e-mail contains a clickable link, determine if the link can be used for phishing.

How to protect yourself

  • High value transaction systems should not use password reset systems. It is discouraged for all other applications.
  • Consider cheaper and more secure systems, such as pre-sending the user a password reset token in a sealed envelope which is replenished upon use.
  • If the questions and answers are used to identify the user to the help desk, simply generate a random number in the “How to call the help desk” page on your web site and verify this number when the user calls in.
  • Be careful when implementing automated password resets. The easiest to get right is “e-mail the user” as it creates an audit trail and contains only one secret – the user’s e-mail address. However, this is risky if the user’s e-mail account has been compromised.
  • Send a message to the user explaining that someone has triggered the password reset functionality. Ask them if they didn’t ask for the reset to report the incident. If they did trigger it, provide a short cryptographically unique time limited token ready for cut and paste. Do not provide a hyperlink as this is against phishing best practices and will make scamming users easier over time. This value should then be entered into the application which is waiting for the token. Check that the token has not expired and it is valid for that user account. Ask the user to change their password right there. If they are successful, send a follow up e-mail to the user and to the admin. Log everything.

If you have to choose the hint based alternative, use free-form hints, with non-public knowledge suggestions, like “What is your favorite color?” “What is your favorite memory,” etc. Do not use mother’s maiden name, SSN, or similar. The user should enter five hints during registration, and be presented with three when they reset the password. Also consider allowing users to create their own questions and answers as long as they are advised against using questions that can be answered by discoverable, semi-public data. With appropriate user education this can produce password reset “credentials” that are significantly less discoverable

Obviously, both password reset mechanisms should be over SSL to provide integrity and privacy.

Brute Force

A common attack is to attempt to log on to a well-known privileged account name or otherwise guessed account and attempt brute-force or dictionary attacks against the password. Users are notorious at choosing really bad passwords (like “password”), and so this approach works surprisingly well.

Applications should be robust in the face of determined automated brute force and dictionary attack, such as from Brutus or custom scripts. Determined brute force attacks cannot easily be defeated, only delayed.

How to determine if you are vulnerable

To test the application:

  • Use a brute force application, such as Brutus or a custom Perl script. This attack only works with tools.
  • Use multiple dictionaries, not just English
  • Use “common password” dictionaries. You’d be surprised how often “root”, “password”, “”, and so on are used
  • Does the error message tell you about what went wrong with the authentication? If it does then the application is disclosing information that is potentially useful to an attacker searching for accounts to brute force.
  • Are the logs for failed authentication attempts tied to a brute force mechanism? Does it lock your IP or session out?
  • Can you restart the brute force by dropping the session with n-1 attempts left? ie, if you get your session destroyed at 5 attempts, does using 4 then starting a new session work?

If the application allows more than five attempts from a single IP address, or a collection rate in excess of 10 requests a second, it’s likely that the application will fall to determined brute force attack.

How to protect yourself

An application should:

  • Have a delay between the user submitting the credential and a success or failure is reported. A delay of three seconds can make automated brute force attacks almost infeasible. A progressive delay (3 seconds then 15 then 30 then disconnect) can make casual brute force attacks completely ineffective
  • Warn the user with a suitable error message that does not disclose which part of the application credentials are incorrect by using a common authentication error page.
  • Log failed authentication attempts (in fact, a good application logs all authentication attempts)
  • (For applications requiring stronger controls) Block access from abusive IP addresses (ie accessing more than three accounts from the same IP address, or attempting to lock out more than one account). This must be done with care because NAT firewalls and other technologies can shape network traffic in ways not anticipated by web application designers.
  • For online forms, generate a one-time key each time the login page is requested, store a copy in the session, and wait a couple of seconds before sending the form to the user's browser with the key as a hidden field. If the keys don't match when the form is posted, log the failed attempt and destroy the session without even looking at the other details.
  • Destroy the session after too many retries.

In such a scenario, log analysis might reveal multiple accesses to the same page from the same IP address within a short period of time. Event correlation software such as Simple Event Correlator (SEC) can be used to define rules to parse through the logs and generate alerts based on aggregated events. This could also be done by adding a Snort rule for alerting on HTTP Authorization Failed error messages going out from your web server to the user, and SEC can then be used to aggregate and correlate these alerts.

Remember Me

On public computers, “Remember Me?” functionality, where a user can simply return to their personalized account can be dangerous. For example, in Internet Cafes, you can often find sites previous users have logged on to, and post as them, or order goods as them (for example with eBay).

How to determine if you are vulnerable

  • Does the application possess “remember me” functionality?
  • If so, how long does it last? If permanently, how long does the cookie last before expiry?
  • Does it use a predictable cookie value? If so, can this be used to bypass authentication altogether?

How to protect yourself

  • If your application deals with high value transactions, it should not have “Remember Me” functionality.
  • If the risk is minimal, it is enough to warn users of the dangers before allowing them to tick the box.
  • Never use a predictable “pre-authenticated” token. The token should be kept on record to ensure that the authentication mechanism is not bypassable
  • Force all users to positively authenticate themselves before being allowed to engage in even moderate-value activities. Using “Remember Me” functionality to authenticate the user to maintain UI preferences may be all right, but using it to allow users to modify account information is most likely not acceptable.

Idle Timeouts

Applications that expose private data or that may cause identity theft if left open should not be accessible after a certain period of time.

How to determine if you are vulnerable

  • Log on to the application
  • Does the application have a keep alive or “log me on automatically” function? If so, the likelihood is high that the application will fail this test.
  • Wait 20 minutes
  • Try to use the application again.
  • If the application allows the use, the application is at risk.

How to protect yourself

  • Determine a suitable time out period with the business
  • Configure the time out in the session handler to abandon or close the session after the time out has expired.

Logout

All applications should have a method of logging out of the application. This is particularly vital for applications that contain private data or could be used for identity theft.

How to determine if you are vulnerable

  • Does the application contain a logout button or link somewhere within it?
  • Does every view contain a logout button or link?
  • When you use logout, can you re-use the session (ie copy and paste a URL from two or three clicks ago, and try to re-use it)?
  • (High risk applications) When logout is used, does the application warn you to clear the browser’s cache and history?

How to protect yourself

  • Implement logout functionality
  • Include a log out link or button in every view and not just in the index page
  • Ensure that logout abandons or closes out the session, and clears any cookies left on the browser
  • (High risk applications) Include text to warn the user to clear their browser’s cache and history if they are on a shared PC

Account Expiry

Users who have to sign up for your service may wish to discontinue their association with you, or for the most part, many users simply never return to complete another transaction.

How to determine if you are vulnerable

  • Does the application have a mechanism to terminate the account?
  • Does this remove all the user’s records (except records required to provide adequate transaction history for taxation and accounting purposes?)
  • If the records are partially scrubbed, do they eliminate all non-essential records?

How to protect yourself

  • Users should have the ability to remove their account. This process should require confirmation, but otherwise should not overly make it difficult to the user to remove their records.
  • Accounts that have not logged in for a long period of time should be locked out, or preferably removed.
  • If you retain records, you are required by most privacy regimes to detail what you keep and why to the user in your privacy statement.

When partially scrubbing accounts (ie you need to maintain a transaction history or accounting history), ensure all personally identifiable information is not available or reachable from the front end web application, i.e. export to an external database of archived users or CSV format

Self registration

Allowing self-registration can help reduce maintenance and support costs, but the anonymous nature of self-registration can have significant security ramifications. Any application implementing self-registration should include steps to protect against the abuse of this facility.

How to determine if you are vulnerable

  • Does the self-registration feature allow full access to all features without human intervention?
  • If there are limits, are they enforced if you know about them? Many applications simply don’t let you see a particular URL, but does that URL work when cut-n-paste from a more privileged account?
  • Can the process for maximizing the account’s capabilities be forced or socially engineered?

How to protect yourself

  • Implement self-registration carefully based upon the risk to your business. For example, you may wish to put monetary or transaction limits on new accounts.
  • If limits are imposed, they should be validated by business rules, and not just by security through obscurity.
  • Ensure the process to maximize the features of an account is simple and transparent.
  • When accounts are modified, ensure that a reasonable trace or audit of activity is maintained

CAPTCHA

CAPTCHA (“completely automated public Turing test to tell computers and humans apart” … really!) systems supposedly allow web designers to block out non-humans from registering with web sites.

The usual reason for implementing a CAPTCHA is to prevent spammers from registering and polluting the application with spam and pornographic links. This is a particularly bad problem with blog and forum software, but any application is at risk if search engines can index content.

How to determine if you are vulnerable

The primary method of breaking CAPTCHAs is to grab the image and to use humans to crack them. This occurs with “free day passes” to adult web sites. A person who wants to look at free images is presented with the captured CAPTCHA and more often than not, they will type the letters in for a small reward. This completely defeats the CAPTCHA mechanism.

Visual or audible CAPTCHA mechanisms by their nature are not accessible to blind (or deaf) users, and as a consequence of trying to defeat clever optical character recognition software, often locks out color blind users (which can be as high as 10 % of the male population).

Note: Any web site that is mandated or legally required to be accessible must not use CAPTCHAs.

How to protect yourself

Do not use CAPTCHA tags. They are illegal if you are required to be accessible to all users (often the case for government sites, health, banking, and nationally protected infrastructure, particularly if there is no other method of interacting with that organization).

If you have to use CAPTCHA:

  • Always provide a method by which a user may sign up or register for your web site offline or via another method
  • Deter the use of automated sign ups by using the “no follow” tag. Search engines will ignore hyperlinks and pages with this tag set, immensely devaluing the use of link spamming
  • Limit the privileges of newly signed up accounts or similar until a positive validation has occurred. This can be as simple as including a unique reference ID to a registered credit card, or requiring a certain amount of time before certain features are unlocked, such as public posting rights or unfettered access to all features

Further Reading

  • NIST Special Publication 800-63 Version 1.0.2, "Electronic Authentication Guideline" Recommendations of the National Institute of Standards and Technology.

http://csrc.nist.gov/publications/nistpubs/800-63/SP800-63V1_0_2.pdf

  • Body Check”, c’t Magazine. Very amusing article from 2002

http://www.heise.de/ct/english/02/11/114/

  • Klein, A., NTLM Authentication and HTTP proxies don’t mix, posting to webappsec

http://packetstormsecurity.nl/papers/general/NTLMhttp.txt

  • How much does it take before your signature is verified? Apparently three plasma screens:

http://www.zug.com/pranks/credit_card/

  • Schneier, B., The failure of two factor authentication, blog / essay

http://www.schneier.com/blog/archives/2005/03/the_failure_of.html

  • Group blog led by Kim Cameron, The Laws of Identity

http://www.identityblog.com/stories/2004/12/09/thelaws.html

  • van der Stock, A., “On the entropy of password reset systems”, unpublished research paper. If you’d like participate in the survey portion of this research, please contact vanderaj@owasp.org

Authentication

Web and application server authentication can be thought of as two different controls. Web server authentication is controlled by the web server administration console or configuration files. These controls do not need to interact with the application code to function. For example using Apache you modify the http.conf or .htaccess files; or for IIS modify the IIS MMC. Basic authentication works by sending a challenge request back to a user’s browser consisting of the protected URI. The user must then respond with the user-ID and password, separated by a single colon, encoded using base64. See Authentication chapter in this guide for more information. Application level authentication occurs at a layer after the web server access controls have been processed. This section examines how to use ColdFusion to authentication and authorize users to resources at the application level.


Web and Application Server Access Controls.gif


ColdFusion allows you to authenticate against multiple system types. These types include LDAP, text files, Databases, NTLM, Client-Side certificates via LDAP, or others via custom modules. The section below describes using these credential stores according to best practice.


Best Practices

  • When a user enters an invalid credential into a login page, do NOT return which item was incorrect instead show a generic message. For example, “Your login information was invalid!”
  • Never submit login information via GET request always use POST.
  • Use SSL to protect login page delivery and credential transmission.
  • Remove dead code and client-side viewable comments from all pages.
  • Set application variables in the Application.cfc. The values you use ultimately depend on the function of you application; however for best practices use the following.

applicationTimeout = #CreateTimeSpan(0,8,0,0)#

loginStorage = session

sessionTimeout = #CreateTimeSpan(0,0,20,0)#

sessionManagement = True

scriptProtect = All

setClientCookies = False (Use JSESSIONID)

setDomainCookies = False

name (This value application dependent; however it should be set)
  • Do not depend on client-side validation. Validate input parameters for type and length on the server, using Regular Expressions or string functions.
  • Database queries must use parameterized queries (<cfqueryparam>) or properly constructed stored procedures (<cfstoredproc>).
  • Database connections should be made created using a lower privileged account. Your application should not login to the database using (sa or dbadmin)
  • Hash passwords in a database or flat file using SHA-256 or greater with a random salt value for each password. For example, Hash(password + salt, “SHA-256”)
  • Call StructClear(Session) to completely clear a users session. Issuing <cflogout> when using LoginStorage=Session removes the SESSION.cfauthorization variable from the Session scope, but does not clear current user’s session object.
  • Prompt the user to close their browser to ensure that header authentication information has been flushed.


Best Practices In-Action

To help demonstrate the use some of these best practices, let’s assume you want to protect a page called “protected.cfm”. To protect this content we need the Application.cfc, a login page (login.cfm) and code to perform our authentication and logout (Auth.cfc). Note all the filenames and variables used in this section are arbitrary.

Application.cfc



<cfcomponent >

 <cfscript>

   This.name = "OWASP_Sample";

    This.applicationTimeout = CreateTimeSpan(0,8,0,0);

    This.sessionManagement = true;

   This.sessionTimeout = CreateTimeSpan(0,0,20,0);

   This.loginStorage = "session";

   This.scriptProtect = "All";

  </cfscript>



  <cffunction name = "onRequestStart">

    <cfargument name = "thisRequest" required="true"/>

    <cfset Request.DSN = "owaspDB"><!--- <cflogout> --->

    <cfif isDefined('Form.logout')>

      <cfinvoke

        component="auth"

        method="logout"

        loginType="simple">

    </cfif>

    <cflogin>

      <cfif NOT isDefined('cflogin')>

        <cfinclude template="login.cfm"><cfabort>

      <cfelse>

       <cfif len(trim(cflogin.name)) AND len(trim(cflogin.password))>

          <cfinvoke 

            component="auth"

            method="LoginUser" 

            returnvariable="result"

            strUserName="#cflogin.name#"

            strPassword="#cflogin.password#">

          </cfinvoke>

          <cfif result.authenticated>

            <cfloginuser 

              name="#cflogin.name#" 

              password="#cflogin.password#" 

              roles="#result.roles#" >

          <cfelse>

            <cfset Request.boolError = true>

            <cfinclude template="login.cfm"><cfabort>

          </cfif>

        <cfelse>

          <cfset Request.boolError = true>

          <cfinclude template="login.cfm"><cfabort>

        </cfif>

      </cfif>

    </cflogin>

  </cffunction>

  <cffunction name="onSessionEnd">

    <cfargument name="thisSession" required="true"/>

    <cfargument name="thisApp" required="false" />

    <cfinvoke

        component="auth"

        method="logout"

        loginType="simple">

  </cffunction>

</cfcomponent>



protected.cfm
<cfset strPath = ExpandPath("*.*")>

<cfset strDir = GetDirectoryFromPath(strPath)>

<html>

<body>

  <title>OWASP Security Test</title>

</body>

  <b>You have successfully logged into the new application</b> 

  <ul>

    <li>This application directory called "<cfoutput>#strDir#</cfoutput>" is protected</li>

   <li>You can also remove any or all of this text and replace it with any valid browser code that you choose, such as CFML or HTML</li>

  </ul>

<cfform name="logMeout" action="#CGI.script_name#" method="post">

  <cfinput type="submit" name="logout" value="Logout">

</cfform>

</html>



Login.cfm
<cfparam name="Request.boolError" type="boolean" default="false">

<cfif Request.boolError>

  <span style="color: red">Your login information was invalid!</span>

</cfif>

<cfoutput>

You must login to access this restricted resource.

<cfform name="loginform" action="protected.cfm" method="Post">

username: <cfinput type="text" name="j_username" required="yes" message="Username required">
password: <cfinput type="password" name="j_password" required="yes" message="Password required">


<input type="submit" value="Log In">

</cfform>

</cfoutput>

|-

|}


Simple Authentication using a Database


Probably the second most widely used method of authenticating users on the web after Basic Authentication is database login. The code snippet below shows how to accomplish database authentication using best practices.

Auth.cfc

<cffunction name="LoginUser" access="public" output="false" returntype="struct">

<cfargument name="strUserName" required="true" type="string">

<cfargument name="strPassword" required="true" type="string">

<cfset var retargs = StructNew()>

<cfif IsValid("regex", strUserName, "[A-Za-z0-9%]*") AND IsValid("regex", strPassword, "[A-Za-z0-9%]*")>

<cfquery name="loginQuery" dataSource="#Request.DSN#" >

SELECT hashed_password, salt

FROM UserTable

WHERE UserName =

<cfqueryparam value="#strUserName#" cfsqltype="CF_SQL_VARCHAR" maxlength="25">

</cfquery>

<cfif loginQuery.hashed_password EQ Hash(strPassword & loginQuery.salt, "SHA-256" )>

<cfset retargs.authenticated = true>

<cfset Session.UserName = strUserName>

<cfset retargs.roles = "Admin">

<cfelse>

<cfset retargs.authenticated = false>

</cfif>

<cfelse>

<cfset retargs.authenticated false>

</cfif>

<cfreturn retargs>

</cffunction>




NTLM


In addition to using controls available via IIS and using the browser dialog box, ColdFusion allows you to authenticate users via a web form using NTLM. The code snippet below shows how to accomplish NTLM authentication using best practices.

Auth.cfc (cont’d)

<cffunction name="LoginUser" access="public" output="false" returntype="struct">

<cfargument name="nusername" required="true" type="string">

<cfargument name="npassword" required="true" type="string">

<cfargument name="ndomain" required="true" type="string">

<cfset var retargs = StructNew()>

<cfif IsValid("regex", arguments.nusername, "[A-Za-z0-9%]*")

AND IsValid("regex", arguments.npassword, "[A-Za-z0-9%]*")

AND IsValid("regex", arguments.ndomain, "[A-Za-z0-9%]*")>

<CFNTAuthenticate

username="#arguments.nusername#"

password="#arguments.npassword#"

domain="#arguments.ndomain#"

result="authenticated">

<cfif findNoCase("success", authenticated.status)>

<cfset retargs.authenticated = true>

<cfelse>

<cfset retargs.authenticated = false>

</cfif>

<cfelse>

<cfset retargs.authenticated = false>

</cfif>

<cfreturn retargs>

</cffunction>



LDAP


To setup authentication against an LDAP, including Active Directory

Auth.cfc (cont’d)

<cffunction name="LoginUser" access="public" output="true" returntype="struct">

<cfargument name="lServer" required="true" type="string">

<cfargument name="lPort" type="numeric">

<cfargument name="sUsername" required="true" type="string">

<cfargument name="sPassword" required="true" type="string">

<cfargument name="uUsername" required="true" type="string">

<cfargument name="uPassword" required="true" type="string">

<cfargument name="sQueryString" required="true" type="string">

<cfargument name="lStart" required="true">

<cfset var retargs = StructNew()>

<cfset var username = replace(sQueryString,"{username}",uUserName)>

<cfldap action="QUERY"

name="userSearch"

attributes="dn"

start="#arguments.lStart#"

server="#arguments.lServer#"

port="#arguments.lPort#"

username="#arguments.sUsername#"

password="#arguments.sPassword#">

<cfif NOT userSearch.recordCount>

<cfoutput>Error</cfoutput>

<cfset retargs.authenticated = false>

</cfif>

<cfldap

action="QUERY"

name="auth"

attributes="dn,roles"

start="#arguments.lStart#"

server="#arguments.lServer#"

port="#arguments.lPort#"

username="#username#"

password="#arguments.uPassword#" >

<cfif auth.recordCount>

<cfset retargs.authenticated = true>

</cfif>

<cfreturn retargs>

</cffunction>



Logout

Auth.cfc (cont’d)

<cffunction name="logout" access="remote" output="true">

<cfargument name="logintype" type="string" required="yes">

<cflogout>

<cflock scope="session" type="exclusive" timeout="5" throwontimeout="true">

<cfset StructClear(Session)>

</cflock>

<cfif arguments.logintype eq "challenge">

<cfset foo = closeBrowser()>

<cfelse>

<cflocation url="login.cfm">

</cfif>

</cffunction>


<cffunction name="closeBrowser" access="private" output="true">

<script language="javascript">

if(navigator.appName == "Microsoft Internet Explorer") {

alert("The browser will now close to complete the logout.");

window.close();

}

if(navigator.appName == "Netscape") {

alert("To complete the logout you must close this browser.");

}

</script>

</cffunction>

'</cfcomponent>'


Development Guide Table of Contents