Check if Session still exists - coldfusion

On the time of login, coldfusion server assigns me a CFID and a CFTOKEN. Later on using those CFID and CFTOKEN how can I check if my session still exists or not.
In other words I want a function that will take CFID and CFTOKEN and will tell if the session related to those CFID and CFTOKEN still exists or not.
Thanks

The easiest way to achieve this would be to set a flag in the session when your user logs in.
for example
<cfset session.loggedin = true />
then when you want to check if the user still has a valid session you can do
<cfparam name="session.loggedin" default="false" />
<cfif NOT session.loggedin>
<!--- do something here --->
</cfif>

There is nothing wrong with Chris' answer and is usually the standard norm when checking for sessions.
These two cookies are meant to "link" your browser with your session, not to actually maintain that session (in fact, I believe these cookies are set to expire in 30 years(?) and are even ignored if you're using J2EE session management if I'm not mistaken). From the docs:
To use client and session variables, ColdFusion must be able to
identify the client. It normally does so by setting the following two
cookie values on the client’s system:
CFID: A sequential client identifier
CFToken: A random-number client security token These cookies uniquely identify the client to
ColdFusion, which also maintains copies of the variables as part of
the Session and Client scopes.
As you can read here, Ben Nadel did some playing around with CFID and CFTOKEN where CF used the same CFID and CFTOKEN cookies to create NEW sessions after it had expired.
As for your 'ColdFusion Proper' way, you could look into using CFLOGIN and other security tags which are meant to assist in handling authentication but I don't believe many people use it because maintaining your session is very easy as Chris demonstrated.

Related

Efficient,secure cookie authentication and usage

I inherited a coldfusion application. The code is very old (think Allaire days) and I've been slowly upgrading it. Recently, we endured pentration testing, which failed in numerous areas. My focus at this moment is the login functionality, specifically how to store and use cookies. We recently upgraded to CF 2018 on Windows.
The site is only accessible via RDS currently, but will be made available via the general web in the near future.
Currently, the code sets a "rememberme" cookie onLogin, as follows, using a heap of obfuscation. I think this was borrowed from a Ben Nadel example: https://www.bennadel.com/blog/1213-creating-a-remember-me-login-system-in-coldfusion.htm
<cfset strRememberMe = (
CreateUUID() & ":" &
SESSION.User.ID & ":" &
SESSION.User.Name & ":" &
SESSION.User.Billing & ":" &
SESSION.User.Admin & ":" &
SESSION.User.Reversals & ":" &
CreateUUID()
) />
<cfset strRememberMe = Encrypt(
strRememberMe,
APPLICATION.EncryptionKey,
"cfmx_compat",
"hex"
) />
<cfcookie
name="RememberMe"
value="#strRememberMe#"
expires="never"
httponly="true" <!--- Set in CFAdmin so not reqd here --->
/>
Several user permissions are included in this cookie, flagging the user as being able to access certain parts of the site and/or perform certain functions.
I would like to keep any unnecessary data completely out of the cookie, perhaps keeping only the userID there. A check could be made, perhaps in application.cfc onRequest() method, to check for the cookie and query the database, then set session variables related to user permissions. Currently, application.cfc onSessionStart() parses the user permissions out of the cookie to create the session-scoped variables. Problem I see with only having the raw UserID in the cookie is that the UserID could be rather easily guessed, so some type of obfuscation or encryption would probably still be necessary.
I realise from my reading that cfmx_compat provides weak encryption.
I'm after the cleanest, most effective way to secure the cookie from any type of third-party or MITM abuse/attack, and make use of it in the application. I've read just about everything on the internet about this and people are doing and suggesting different things. My brain is overloaded with ideas right now. I don't want to be fancy, just effective.
The site doesn't have SSL or TLS right now, but will be implemented soon, which should help matters security-wise.
Think of the remember me with the same security concerns as normal login credentials. Do not include any sensitive info, rather save all other data in the database and only access it after the user is authenticated.
In the cookie, have a way to identify a user and a secret with sufficient length/entropy. The secret should be hashed (ex: bcrypt) in the database, so if someone sees your database they can't simply send the data in a cookie to authenticate as any user. You can include the username in the cookie or create a random string for each user that can be used instead.
Did you have other concerns or questions?

Do I need to delete the cookie in Coldfusion when I change other session variables

I have a problem with session variables in my app. To make it short, my coldfusion application is inside a dot net application using iFrame. The Main application is using dot net so user login to dot net app.
Once user successfully login they can access my coldfusion app. through a link. So there is no login to my coldfusion app. (Boss does not want our users to login twice!).
To differentiate each user, the dot net app pass two url variables, url.userid and urlusergroup to my coldfusion app. Then I created session variables based on these url variables, such as session.userid and session.usergroup, to differentiate each user and their roles when they are roaming in my coldfusion app.
This is how I create the sessions:
in my application.cfc (ColdFusion 10) OnSessionStart I have:
<cfset session.userid= url.userid>
<cfset session.usergroup= url.usergroup>
If I login as user A, those two sessions are created then when I log out (through the dot net app), then login again as user B, another set of sessions are created for user B but the session variables that belong to user A still exist. This mess up everything.
To only maintain 1 set of sessions running at a time, I do the following in my index.cfm:
<CFIF StructKeyExists(session,"userid") >
<cfif session.usergroup NEQ URL.usergroup AND session.userid NEQ url.userid>
<cfset sessionInvalidate() />
<cfset session.userid = url.userid>
<cfset session.usergroup = url.usergroup>
</cfif>
</CFIF
This work, I can login and log out as different users with different roles and access perfectly but one thing that I notice still stay the same is the cookie.
When I cfdump var="#cookie#" I see the same jsessionid=C2AEE274A09334EB98CCB2D332D6CADA.cfusion
My question is: should I do something with the cookie? should I also make it expired and rebuilt the cookie for every new user just like what I did with their sessions?
How to delete a cookie and how to rebuild one for the user?
Not quite the answer you are looking for, but it does seems to me that you could have a bigger problem though - are any of the URL params numeric or 'plain text'? If so any user can see the URL params being passed via the iframe, so could easily change the userid and/or the usergroup which presumably would give them access to things they shouldn't.
For example if the iframe calls:
http://mycfapp.com/?userid=123&usergroup=2
Then by tampering with the params I could potentially login as a different user:
http://mycfapp.com/?userid=1&usergroup=2
You need to think about securing these. You could get the .net application to call CF server-side to authenticate and get a token which you can then pass in the iframe. That way you can provide a time-sensitive token without the user ever seeing the ids being passed as simple URL params.
You could also have your .net application call CF when the user logs out to invalidate the token.
Expanding on what John said, you need to make two calls from your .net application.
First will be for authenticating the call from .net system. In response to that you should give back a token. You can save this token into your session or database against the userId.
Then using that token, you should allow .net application user to be able to access your ColdFusion application. You can set a timeout on that token based on user journey.

what persistent scope to use in absence of session scope

I need to maintain a variable in persistent scope, that is until user session is active. Problem is application does not allow session management and it is not possible to change that.
I want to display a message to the user only once in logged in session. What are my options except session and if possible except using DB.
This is a very long comment. It won't answer the question but it might give the questioner some ideas.
I wrote and still maintain a ColdFusion application that has sesssion management set to false. This app displays html content inside a desktop application - not a web browser. Security is handled by the desktop application. If you can log into that application and are the appropriate type of user, you can access the html content.
On the ColdFusion side, the possibility of someone discovering the url and trying to access the site with a web browser must be handled. That's done with data. The desktop application puts a UUID into a database and sends it as a url variable. ColdFusion checks to see if the UUID exists and is sufficiently recent. If that check fails, the user is sent to a "shame on you for trying" page. This is done in the onRequestStart method of Application.cfc
Other relevent variables are sent to ColdFusion from the same database record as the UUID, but they could conceivably also be url variables. The onRequestStart method copies these variables to the request scope which is used in the other ColdFusion pages.
you can set a session cookie using cfcookie that doesn't use the expires attribute. This would cause the cookie to expire when the user closes the browser. Your cookie would indicate whether or not the message has been displayed.
<cfif structkeyexists(cookie, "message_displayed") eq false>
<cfcookie name="message_displayed" value="true"/>
<p>Your Message Here</p>
</cfif>

ColdFusion inconsistent cookie availability

I've inherited a ColdFusion site, despite no background in CF, but have been tasked with making a change to the behavior of the site. I'm running into a problem with cookies, though.
A site on another domain is linking to this site and includes a query string. Now I'm checking for that value (a zip code) in the index.cfm file and storing it in the cookie and that seems to be working fine. I looped through the cookie collection and dumped the results, and the zip code was there. So at this point, all is well.
But then the user clicks on a button, which reloads the index.cfm file with a different <include>, and the cookie no longer has any values other than CFID and CFTOKEN. This was confirmed by looping through the cookie collection, and later by Fiddler.
Client storage is set to cookie, and I can't find anywhere in the index.cfm, application.cfm, or the included files where the cookie is being set to expire.
Here's the line that's storing the value:
<cfcookie name="ZC_Zip" value="#ZC.ZC_Zip#" expires="NEVER">
What else should I be looking for to figure this out? It's ColdFusion 5, if that helps.
Cookies without a set expiration are set to a default of expiring at session close. Could this reload be resetting the session of the user?

What is the most effective way to reset ColdFusion session variables (CFTOKEN, CFID, JSESSIONID)?

The conclusion of the following question was that rebuilding session token after switching from http to https is a good idea.
In ColdFusion do I need to reestablish session tokens after switch from http to https?
The question is, what is the most effective way to do so?
This is one of those easier-said-than-done things.
It has been a while since I have researched this, so please take this with the understanding that you may need to troubleshoot it.
For Java EE sessions I think it is a bit easier because you can call invalidate() on the session. But, unfortunately, that is only half of the battle. You really have several problems to solve. They are
Find some way to store any existing session data that you need (serialize and store)
Invalidate the old session (Possible with both Java EE and CF sessions but the way to do it with CF sessions is undocumented)
Expire the old cookies
Create a new session
Copy the data from the old session that you stored in step 1 into the new session
Set new cookies for the new session
This may not seem too tricky, the potentially hard part is doing it in one request, since normally a session is not created until a request is made and cookies are not set until a response is returned.
I think it is easiest using Java EE because you can call invalidate() on the old session, and get a new one by called getRequestContext().getSession() (I believe this is the case, and I believe it ONLY works with Java EE sessions).
I have contemplated how to do these things with CF Sessions and the only thing I can think is to have the code that is creatign a new session make a CFHTTP request to a page on the site so that a new session can be created. The CFHTTP response will have a new cookie in it, then you can expire the old cookies, and set the new using the tag.
Hope this helps
After performing a whole bunch of tests, it seems like the most effective way to kill the session is to expire the jsessionid cookie with a value of now.
<cfcookie name="jsessionid" expires="now"/>
This obviously assumes the use of J2EE session variables.
If J2EE session variables are not being used, then it seems that session variables and client variables are both keyed off of the CFID and CFTOKEN cookie variables. Which means the only way to kill the session is to expire those cookies with a value of now.
<cfcookie name="cftoken" expires="now"/>
<cfcookie name="cfid" expires="now"/>
This method will also invalidate the client variables.
It seems like the best way to kill sessions without killing client vars while not using the J2EE session variables would be to create a session cookie that expires on browser close and check for that value under application.cfc request processing. If the value does not exist, clear the session struct.
structDelete(session, "CFTOKEN");
structDelete(session, "CFID");
structDelete(session, "JESSIONID");
Will delete the keys from the struct, but I am unsure if you will have issues with CF 'reapplying' those variables to the session.