Best Practices for Secure Password Storage in ColdFusion

Epicenter Consulting Blog

In today’s post, I want to discuss best practices for secure password storage in ColdFusion.  The examples I will provide are directed towards ColdFusion development. However, this is not limited to ColdFusion; these principles apply to any software development project.


The first best practice of secure password storage is:

Never, ever, ever, ever, ever, ever store passwords in the clear.


The biggest mistake that a developer can make is to store passwords in the clear.  I have seen countless ColdFusion websites connected to a database that contains some iteration of the following table:

 

 userID

 username

 password

 1  admin  admin
 2   info  admin
 3  webmaster  w3bM@$t3r


If someone with nefarious intention were to obtain access to this table, all of the usernames and passwords would be compromised.  Someone could log in and perform actions as any user in your application, causing a massive security loophole.


Why do developers store passwords in the clear?  In discussion with developers and administrators, I’ve been told that they feel the need to know what specific user passwords are, or require a means to be able to look up a user’s password if necessary.  Which brings us to the next best practice tip:

Let go of the idea of being able to access a user’s password.


As a best practice for secure password storage, you need to let go of the notion of being able to look up a user’s password.  If you’re concerned about the security of your application (and you should be), then you must build in reasonable security measures to protect your data.  Consider these rules from a security standpoint:

  • No user should be able to see any user’s password, including their own.
  • A user should be able to change their own password.
  • An administrator should be able to assign a randomly generated password to a user, but that password should be changed to a user assigned password on the first login.


The bottom line is that you do not need to know or even be able to look up what a specific user’s password is.  Let it go.


Once that notion is purged from your expectations, you may be asking yourself, “Self… how do I store passwords without storing the password?”  It’s simple:

Hash your passwords.


ColdFusion, like most programming languages, has a built-in hash() function that will perform a one-way encoding of a string into a fixed-length string. ColdFusion’s hash function takes four arguments:

  • string – the string you want to hash.
  • algorithm – the algorithm used to hash the data.
  • encoding – the character set encoding used to create the result of the hash, defaulting to the “defaultCharset” attribute of ColdFusion’s neo.xml file, but is typically “utf-8”.
  • iterations – the number of times ColdFusion will iterate over the hash making it more complex, but also more computationally intensive.  This value defaults to 1.


Let’s create a new field in that user’s table above called “passwordHash” making it a char variable type with a length of 40 characters and run the following ColdFusion script:

 

<cfquery name=”getUsers”>
  SELECT * FROM Users
</cfquery>
<cfloop query=”getUsers>
  <cfquery name=”setPasswordHash”>
    UPDATE Users
    SET passwordHash = <cfqueryparam cfsqltype="char" value="#hash(Password,’SHA’)#">
    WHERE (userID = <cfqueryparam cfsqltype="integer" value="#userID#">
  </cfquery>
</cfloop>


Looking at the resulting table, this is what we see:

 userID

 username

 password

 passwordHash

 1  admin  admin  4ACFE3202A5FF5CF467898FC58AAB1D615029441
 2  info  admin  4ACFE3202A5FF5CF467898FC58AAB1D615029441
 3  webmaster  w3bM@$t3r  9001EC3B7E9293AF92D5F35014C580779AD5EDA2

 

This is better.  Now that we have a hash of the password stored, we can start authenticating users based on the password hash and not the password in the clear.  Once we do that, we can drop the password column and clean up our exposed data. We’re well on our way to best practices for secure password storage!


But we’re not quite done yet. There’s a problem here; the password hash for the admin and info user is the same since they used the same password.  The username/password combination may be distinct, but if one part of that equation matches another record in the table exactly, it’s not as safe as we can make it.  The next step is to:

Add some salt.


To create unique password hashes for each user, we are going to perform a technique called “salting the data.” A password salt is an additional hash, randomly generated, that gets appended to the password to guarantee uniqueness.  The first thing I am going to do is make some changes to the users’ table. I will:

  • Modify the passwordHash column to be 128 characters in length.
  • Add another column called passwordSalt, that is also a char field, 128 characters in length.


The reason for updating these fields is to accommodate the change I am making to the hashing to support the much more robust SHA-512 algorithm in my ColdFusion script.


Looking at my ColdFusion script above, I’ll make some modifications and run the following:

 

<cfquery name=”getUsers”>
  SELECT * FROM Users
</cfquery>

<cfloop query=”getUsers>
  <cfset passwordSalt = hash(generateSecretKey(“AES”),”SHA-512”)>

  <cfquery name=”setHashedPassword”>
    UPDATE Users
    SET
      passwordHash = <cfqueryparam cfsqltype=”char” value=”#hash(Password & passwordSalt,’SHA-512’)#”>,
      passwordSalt = <cfqueryparam cfsqltype=”char” value=”#passwordSalt#”>
    WHERE userID = <cfqueryparam cfsqltype=”integer” value=”#userID#”>
  </cfquery>
</cfloop>

 

Running this script, and looking at the table, we can now see solid, secure password storage.

 userID

 username

password

passwordHash

passwordSalt

 1  admin  admin  03C3529A170…  13C55682B9…
 2  info  admin  323FC900F49…  7559EBC821…
 3  webmaster  w3bM@$t3r  5F90E940583…  9E29A211D39…


Now that we’ve stored the hash of the salted password, and the salt itself, your authentication will require some modification.  You need to get the password hash and salt of the user you are trying to authenticate against and perform the comparison in ColdFusion.


Excellent! We’re no longer authenticating against passwords in the clear.  We are salting password hashes before we store them in the database. We’re comparing the hash of the salted password to the user entry.  The security of our application is looking much better! But there’s one final step.

Remove insecure data.


The very last step is to drop the column of passwords in the clear from your table.  Once this is done, and users are being authenticated against a password hash and password salt, you will be performing best practices for secure password storage in your ColdFusion application!

Happy coding!

Related Content