Skip to content

Instantly share code, notes, and snippets.

@learncfinaweek
Created November 20, 2012 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save learncfinaweek/4121399 to your computer and use it in GitHub Desktop.
Save learncfinaweek/4121399 to your computer and use it in GitHub Desktop.
Security - Hands On 29

In this hands on we are going to secure our session and improve our admin security by hashing our passwords.

Tags Used: <cfif>, <cfset>, <cfquery>, <cfqueryparam>

Functions Used: len, trim, Hash, GenerateSecretKey, SessionRotate, SessionInvalidate

  1. Open up the /www/Application.cfc file in your code editor.
  2. When cookies are enabled on a web site (which is the case for this web site), it is important to secure them. Locate the block of variable declarations that sets values of the this scope. They should be at the top of the file.
  3. After the last variable declaration, add the following lines of code:
    this.sessioncookie.httponly = true;
    this.sessioncookie.timeout = "10";
    this.sessioncookie.disableupdate = true;
    
  4. Now that the session cookies are secured, improve the security of the admin area by updating the administrator passwords. Open up the /www/admin/content/system/editadministrator.cfm file in your code editor.
  5. Locate the line of code that checks if there were any validation errors on or around line 38.
  6. The first thing to do when implementing hashing into the admin is to check if a password has been submitted. If no password has been submitted when the record is being updated, then we do not plan on updating the password and do not need to hash anything. Create a <cfif> tag that checks if form.password has a length. Remember to trim the value just in case any errant spaces have been entered. Your code should look similar to this:
    <cfif len(trim(form.password))>
    

    </cfif>

  7. Inside of the <cfif> tag, create two values: the first is the salt value we will be using and the other will be the hashed password. To create the salt value, create a <cfset> tag that creates a variable called salt. In the <cfset> tag call the Hash() function and pass in a call to the GenerateSecretKey function as the string to hash, and pass in SHA-512 as the algorithm to use when hashing. In the GenerateSecretKey call, pass in AES as the algorithm to use. Your <cfset> should look similar to this:

    <cfset salt = Hash(GenerateSecretKey("AES"), "SHA-512") /> 
    
    </li>
    <li>
    	Next, generate the hashed password.  To do this, create another <span class="code">&lt;cfset></span> tag that sets a variable called <span class="code">password</span>.  In the <span class="code">&lt;cfset></span>, call the <span class="code">Hash()</span> function again and pass it in a concatenated string of the <span class="code">form.password</span> value and the <span class="code">salt</span> value.  Tell the <span class="code">Hash()</span> function to use the <span class="code">SHA-512</span> algorithm.  Your <span class="code">&lt;cfset></span> should look similar to this:
    
    <cfset Password = Hash(form.password & salt, "SHA-512") />
    
    </li>
    <li>
    	Once there is a salt and a hashed password created, we need to update the queries to accept these values.  Locate the <span class="code">&lt;cfquery</span>> tag that updates the administrator record on or around line 45.  Update the SQL code so that the password value stored is the new password variable.  Also, update the SQL so that the salt value is saved into a column called <span class="code">salt</span>.  The update query should look similar to this:
    
    <cfquery>
    	UPDATE
    		administrator
    	SET
    		firstname = <cfqueryparam value="#trim(form.firstname)#" cfsqltype="cf_sql_varchar" />,
    		lastname = <cfqueryparam value="#trim(form.lastname)#" cfsqltype="cf_sql_varchar" />,
    		emailaddress = <cfqueryparam value="#trim(form.emailaddress)#" cfsqltype="cf_sql_varchar" />
    		<cfif len(trim(form.password))>
    			,password = <cfqueryparam value="#password#" cfsqltype="cf_sql_varchar" />
    			,salt = <cfqueryparam value="#salt#" cfsqltype="cf_sql_varchar" />
    		</cfif>
    	WHERE
    		id = <cfqueryparam value="#form.id#" cfsqltype="cf_sql_integer" />	
    </cfquery>
    
    </li>
    <li>
    	Once the update functionality is changed, it is time to change the insert functionality.  Locate the <span class="code">&lt;cfquery></span> that creates a new <span class="code">administrator</span> and update the statement to use the new <span class="code">password</span> variable.  Also update the SQL to store the <span class="code">salt</span> value.  Your <span class="code">&lt;cfquery></span> should look similar to this:
    
    <cfquery>
    	INSERT INTO
    		administrator (
    		firstname,
    		lastname,
    		emailaddress,
    		password,
    		salt
    	) VALUES (
    		<cfqueryparam value="#trim(form.firstname)#" cfsqltype="cf_sql_varchar" />,
    		<cfqueryparam value="#trim(form.lastname)#" cfsqltype="cf_sql_varchar" />,
    		<cfqueryparam value="#trim(form.emailaddress)#" cfsqltype="cf_sql_varchar" />,
    		<cfqueryparam value="#password#" cfsqltype="cf_sql_varchar" />,
    		<cfqueryparam value="#salt#" cfsqltype="cf_sql_varchar" />
    	)
    </cfquery>
    
    </li>
    <li>
    	Now that the newly encrypted password can be saved, we need to update the login logic to accommodate the changes that have been made.  Before we do this, update the password for the current administrator.  If we do not, as soon as the new logic is in place you will no longer be able to login to the admin.  Open up <span class="code">/www/admin/</span> in your browser.
    </li>
    <li>
    	Login with the username: <span class="code">system@yoursite.com</span> and password: <span class="code">admin</span>.
    </li>
    <li>
    	Navigate to: System > List Administrators.
    </li>
    <li>
    	Edit the Administrator, provide a new password and click 'Save'.  You have now updated your account with a newly hashed password.
    </li>
    <li>
    	Now that the new password is created, we can update the login logic.
    </li>
    <li>
    	Open up the <span class="code">/www/admin/login.cfm</span> file in your code editor.
    </li>
    <li>
    	Update the query that checks the <span class="code">username</span> and <span class="code">password</span>.  Because we need to hash the password supplied with the applicable salt value, we can no longer search on the <span class="code">password</span> value.  Locate the <span class="code">&lt;cfquery></span> tag with the name of <span class="code">qLoginCheck</span> on or around line 10.
    </li>
    <li>
    	Remove the part of the query that searches against the password and update the select list to return the <span class="code">password</span> and <span class="code">salt</span> columns.
    </li>
    <li>
    	Locate the <span class="code">&lt;cfif></span> statement that checks if any records were returned from the query, on or around line 22.
    </li>
    <li>
    	Next, hash the password that was submitted by the form with the salt that was returned in the query.  If that hashed value does not match what was returned by the query, then the password is incorrect.  Update the <span class="code">&lt;cfif></span> statement so it reads:
    
    <cfif !qLoginCheck.recordcount || qLoginCheck.password NEQ Hash(form.password & qLoginCheck.salt, "SHA-512")>
    
    </li>
    <li>
    	The logic is now in place to check the submitted password with the hashed password.  Before testing it out to make sure everything is working, we are going to add 2 more function calls to protect our session identifiers.  Locate the <span class="code">&lt;cflocation></span> tag on or around line 27.
    </li>
    <li>
    	Before this tag make a call to <span class="code">SessionRotate()</span> using a <span class="code">&lt;cfset></span> tag.  This will rotate the session identifiers every time we log in.
    </li>
    <li>
    	Next, make sure the session is completely removed when we log out; open up the <span class="code">/www/admin/logout.cfm</span> file in your code editor.
    </li>
    <li>
    	Locate the <span class="code">&lt;cflocation></span> tag on or around line 3.
    </li>
    <li>
    	Before this tag, make a call to <span class="code">SessionInvalidate()</span> using a <span class="code">&lt;cfset></span> tag.
    </li>
    <li>
    	Now that we have our hashed passwords set up and our session protection in place, it is time to test that everything is working.  Log out by clicking on the <span class="code">system@myWebsite.com</span> email address on the top right of the admin.
    </li>
    <li>
    	Fill in the log in details for the administrator account you edited.
    </li>
    <li>
    	Once logged in, click around the admin and then click log out.  You have now successfully added security to our admin area.
    </li>
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment