ColdFusion TIPS PLUS
Issue 00123 http://www.cftipsplus.com
I. My CommentsII. ColdFusion In Context: Hide Session Id
By R. Martin Ladner
martin.ladner@charter.net
Advanced, Intensive ColdFusion Training!Visit this site. If you have plans to get training here is a company
that provides Advanced, Intensive ColdFusion Training. Check them out.
http://www.coldfusiontraining.com/index.cfm?ref=cftipsplus
I. Comments:
I have been very busy with my new job and I am going to college a online college. So needless to say it has been tough. I also work in Washington, D.C. and live in Milford, DE. We are talking about having our house built. We have found a lot and we are talking to a builder. So hopefully I will be in my own house in a few months.
I have started a small town portal for Milford, Delaware at http://www.MilfordDel.com . It is not finished just yet however if you have some ideas of where I can get some NEWS for it or other content please send me an email at NathanS<at>nsnd.com .
Keep Coding,
Nathan Stanford
http://www.cftipsplus.com
If you have suggestions for articles send them to us.
If you would like to write for cftipsplus.com
send us an email to:
NathanS<at>nsnd.com
IF YOU WANT TO BE AN AUTHOR SEND IN YOUR COLDFUSION TIPS.
Remember this is a great way to get your name known in the
ColdFusion Community.
New CF News*Macromedia CF Community manager to give Keynote at CFUN-03*Christian Cantrell, the Macromedia CF Server Community manager will be giving the keynote speach at CFUN-03 on
Saturday 6/21/03. Christian will be speaking on the future of ColdFusion. Given all the changes happening with CFMX and Flash this seems like a hot topic to me! You can learn more at
http://www.cfconf.com/cfun-03/*Fusebox 4 released, more details at CFUN-03*
Fusebox version 4 was release in Atlanta GA today 5/7/03. Fusebox 4 will add new features using XML and compilation of the switch file. It also includes many ideas from FuseQ, the version of Fusebox written by John Quarto-vonTivadar that allow for multiple fuseactions and streamed output into CSS and Flash front ends. If you can't make it to Atlanta there will be four talks on Fusebox 4 at CFUN-03. The speakers include Hal Helms, Jeff Peters, John Quarto-vonTivadar and Sandra Clark. For more information see http://www.cfconf.org/cfun-03/
II. ColdFusion in Context: Hide Session Id
By R. Martin Ladner
martin.ladner@charter.net
Ignoring inter-frame communication and Web bugs for a moment, there are three basic ways to identify a logical session from page to page: forms, URLs, and cookies. Once you've identified the session, there are a few basic ways to retrieve information associated with that session: forms, URLs, cookies, files on a server (including code in pages), databases on a server, other applications on a server, and memory on a server. If you eliminate storage the client can see, that leaves files, databases, applications, and memory. Of these, memory is typically fastest.
Suppose you want to get information about a user from a database at login, load that information into memory for the session, and then retrieve that information for that specific session from memory at the begining of each page. The pages can use form, URL, or cookie variables to provide the session identifier so ColdFusion will know which session this is. The pages can also pass the UserID again so that your application can compare it with the UserID you stored in session memory to prevent user A from pretending to be user B.
To make this combination of session ID and UserID resistant to tampering by the user, you'd like to combine it with some random information and encrypt the result. However, if you don't use clear-text URL or cookie variables with the exact names that ColdFusion expects its default session mechanism to use, how do you get ColdFusion to access the right session in memory? That's the subject of this demonstration.
Let's review the problem once more before approaching a solution. When you first browse a domain, ColdFusion assigns a session if session management is enabled on the page. When you browse another page in the domain, ColdFusion looks for variables named CFID and CFTOKEN in a URL or cookie. If it doesn't find them or can't match them to an active session in memory, it assigns a NEW session when session management is enabled for that subsequent page. Let's say that again. You have to enable session management to use session memory. If ColdFusion hasn't already recognized the session before session management is enabled, it generates a NEW session with a different session ID and a different structure in memory. If you try to use code to set session variables such as the session ID and token before session management is enabled so you can get the right structure in memory, ColdFusion will (naturally) complain that you can't set session IDs if session management isn't enabled. After session management has been enabled, ColdFusion ignores your attempts to set the session ID and token; because, it has already created a new session. So, how can you win?
It CAN be Done
The answer is to use a method that ColdFusion is expecting, but in a context where the user can't see what you're doing. ColdFusion expects to see plain-text values (well, simple integers) in variables named CFID and CFTOKEN, and the variables have to be URL or cookie variables. If you set a cookie, the user can see it. However, if you set a URL in the middle of a page but don't browse the URL, ColdFusion "sees" the URL variables without presenting them to the user! That's how you reach your goal.
The overall flow goes something like this. On the first page, enable session management (so you can use session memory) with the cookie setting turned off (so ColdFusion won't write cookies unless you tell it to), store the session.cfid and session.cftoken along with the UserID in an encrypted string in the cookie. On subsequent pages, decrypt the string, set url.cfid and url cftoken, and then enable session management for the page (again, with the cookie setting turned off). ColdFusion will read the "URL" variables to select the right session in session in memory, and you can compare the UserID in memory with the UserID in the cookie to decide if it's safe to use the other information stored for this session.
Build an Gate
Make a credential-checking file: call it gate.cfm. To avoid confusion in case you've just browsed another ColdFusion site, delete cfid and cftoken cookies. In case you've been inside this application earlier, delete the "pass" cookie (you'll set later) as well. Enable session management with cookies turned off and permit idle time to be three minutes.
<!--- Remove old cookies and set session parameters --->
<cfcookie name="cfid" value=0 expires=-1>
<cfcookie name="cftoken" value=0 expires=-1>
<cfcookie name="myid" value=0 expires=-1>
<cfcookie name="mytoken" value=0 expires=-1>
<cfapplication Name="HideSession"
clientmanagement="no"
sessionmanagement="yes"
setclientcookies="no"
sessiontimeout=#createTimeSpan(0,0,3,0)#>
For this demonstration, replace database logic by simply pretending that the "Frank" login was validated and that the database says Frank has AccessLevel 5. Then concatenate the Application name and session ID to form a lock name that should only block another window of this same browser, copy cftoken to a variable that doesn't have to be locked, and store the UserId and AccessLevel in a memory structure for this session.
<!--- Pretend that "Frank" login was validated
and that the "database" said Frank has AccessLevel 5 --->
<cfset form.UserId="Frank">
<cfset request.AccessLevel=5>
<!--- Copy session identifiers and store data in session memory --->
<cfset Lock="HideSession"session.cfid#>
<cflock name="#Lock#" timeout=30>
<cfset request.cftoken=session.cftoken>
<cfset session.User=form.UserId>
<cfset session.Access=request.AccessLevel>
</cflock>
Use list functions to build a list of elements separated by spaces, urlEncode it to make its special characters safe, and encrypt the result as you store it in a cookie named "Pass". It's a bad idea to permit spaces in UserIDs anyway; this avoids problems in case someone wants to have a comma in a UserId [groan]. The random number just adds aggravation. It doesn't do much in this demonstration, but if you rearranged the pieces before (or after) encryption, it might make the string appear even more different from attempt to attempt.
<!--- Store the UserID and session keys in an encrypted cookie --->
<cfset Temp="">
<cfset Temp=listAppend(Temp,randRange(0,9999)," ")>
<cfset Temp=listAppend(Temp,session.cfid," ")>
<cfset Temp=listAppend(Temp,request.cftoken," ")>
<cfset Temp=listAppend(Temp,form.UserId," ")>
<cfset cookie.Pass=urlEncodedFormat(encrypt(Temp,"welcome"))>
Because this is a demonstration, you need a method to help you realize what the session Id was on the first page so you can see if the session retained its integrity between pages. Build a form to help with this task.
<form name="Gate" action="menu.cfm" method="post">
Notice the session Id: <cfoutput>#session.cfid#</cfoutput><br>
<input type="hidden" name="Reference" value=<cfoutput>"#session.cfid#"</cfoutput>>
<input type="submit" name="Go" value="Done reading">
</form>
Build a Menu
This "menu", menu.cfm, merely contains the code needed to show that session memory can be accessed based on the contents of an encrypted cookie. (In real life, the available menu items would depend on AccessLevel.) Read the Pass, display it for educational purposes, and interpret it. When you interpret it, set url variables CFID and CFTOKEN based on the contents of Pass so ColdFusion will "resume" this session when you turn session management on.
<!--- Read the Pass --->
<cfparam name="cookie.Pass" default="">
<cfif not len(cookie.Pass)>
The credential is missing
</cfif>
<pre>
urlEncoded Pass:<cfoutput>#cookie.Pass#</cfoutput><br>
urlDecoded Pass:<cfoutput>#urlDecode(cookie.Pass)#</cfoutput>
</pre>
<p>
<!--- Interpret the Pass --->
<cfset Temp=decrypt(urlDecode(cookie.Pass),"welcome")>
<cfoutput>Random number is #listGetAt(Temp,1," ")#</cfoutput>
<p>
<cfset url.cfid=listGetAt(Temp,2," ")>
<cfset url.cftoken=listGetAt(Temp,3," ")>
<cfset url.UserId=listGetAt(Temp,4," ")>
Set session parameters as before, and read session memory. If for some reason the session does not contain a UserId and SessionLevel - perhaps the old session didn't restart after all - use cf try-catch combinations to avoid exposing the user to raw errors. Finally, display the desired and actual data.
<!--- Set session parameters --->
<cfapplication Name="HideSession"
clientmanagement="no"
sessionmanagement="yes"
setclientcookies="no"
sessiontimeout=#createTimeSpan(0,0,3,0)#>
<!--- Access session memory to prove the session was found --->
<cfset Lock="HideSession"session.cfid#>
<cflock name=Lock timeout=30>
<cftry>
<cfset request.UserId=session.User>
<cfcatch>
UserId not found<br>
<cfset request.UserId="">
</cfcatch>
</cftry>
<cftry>
<cfset request.AccessLevel=session.Access>
<cfcatch>
SessionLevel not found<br>
<cfset request.AccessLevel=0>
</cfcatch>
</cftry>
</cflock>
UserId desired: Frank<br>
UserId seen: <cfoutput>#request.UserId#</cfoutput><br>
Access Level desired: 5 <br>
AccessLevel seen: <cfoutput>#request.AccessLevel#</cfoutput><br>
Session desired: <cfoutput>#form.reference#</cfoutput><br>
Session seen: <cfoutput>#session.cfid#</cfoutput>
Review
To see this in operation, browse gate.cfm, accept the prompt that tells you which session you're in, and review the window displayed by menu.cfm to confirm that ColdFusion allowed you to access session memory based on encrypted values. You'll probably want to rearrange portions of the cookie value to make "Pass" harder to interpret and forge. However, don't lose much sleep over forgery. Once a session expires in memory, a forged pass for that session is useless anyway, and when the session is eventually reused, it's unlikely to be for the same UserId right away. You can block sessions whose UserId in the cookie doesn't match the UserId in memory.
So what did you accomplish? You used encryption and an additional identification element to reinforce ColdFusion's already intuitive session management.
=Marty=
SPONSOR ADS:
This e-mail is sponsored by the following ads.
Advanced, Intensive ColdFusion Training!Visit this site. If you have plans to get training here is a company
that provides Advanced, Intensive ColdFusion Training. Check them out.
http://www.coldfusiontraining.com/index.cfm?ref=cftipsplus
Publisher and Creator:
Nathan Stanford,
NathanS<at>nsnd.com
http://www.cftipsplus.com
Macromedia and ColdFusion are U.S. registered trademarks.
Copyright (c) 2000 - 2003
CFTIPSPLUS.COM and NSND.COM
Permission is granted to circulate this publication via
MANUAL forwarding by email to friends provided that the text is
forwarded in its entirety and no fee is charged.