ColdFusion: CFID and CFToken change on each page request - security

I have been asked to use J2EE Variables and not store the CFID and CFTOKEN in cookies, as the CFID is reported as non-compliant: Predictable Cookie Session ID's Reported by Compliance Tests
In my Application.cfm, I have added setclientcookies="false". This stops the CFID and CFToken being written as cookies.
In the ColdFusion Admin, I have enabled J2EE Session Variables
So I now have a cookie with JESSIONID, and a session variable with URLToken containing CFID and CFTOKEN. However, every time I refresh the page, the CFID and CFTOKEN change. They do not persist as they did before. Which mean our admin login system fails.
I have done my own googling, but have found nothing so far. One suggestion I found was to write code to persist the CFID and CFTOKEN. However, this doesn't feel like a good solution.
Any suggestions?
Barebones Test
I installed CF 10 Developer Edition and enabled J2EE Session Variables
Created an Application.cfm with
<cfapplication name="test" sessionmanagement="Yes" setclientcookies="false">
and an index.cfm with
<h1>Cookie</h1>
<cfdump var="#cookie#">
<h1>Session</h1>
<cfdump var="#session#">
The Session.URLToken changes with every refresh
CFID=2212&CFTOKEN=41db974c3d2eb4b6-640C21AE-FD53-499C-71FBEBA35D6B09E8&jsessionid=E28AA17629928FB6F9E17674AC85C7AA.cfusion
CFID=2213&CFTOKEN=bb791a304929d0f5-6425021B-A31B-B9C8-3628AE391B0F48FF&jsessionid=E28AA17629928FB6F9E17674AC85C7AA.cfusion
Further Thoughts
The CFIDand CFTOKEN are used in our login system to verify the user session matches, maybe I should change it to store and verify against the JESSIONID. Maybe it doesn't matter that the CFIDand CFTOKEN change. The session scope is actually maintained, so this could be a completely non-issue.
<cfparam name="session.timestamp" default="#now()#">

setClientCookies="false" means that coldfusion server will not create cookies for the current session. CFID and CFToken will still exist and will be non-persistent.
Check in your example that jsessionid value is same in both cases and that is what you should use instead of CFID & CFToken only if need be.
And you are correct, your session state is maintained as you have enabled J2EE session variables.

Related

how do i keep the session permanent with servicestack

I am working with a remote iPad developer who is using a tool that he says does not allow him to set the "RememberMe=true" value when registering the user. Since we always want to have this value set anyway, I thought I could simply intercept the request on the server side and set it myself. I am using Basic Authentication and I had already overridden "BasicAuthProvider" so I have access to the "TryAuthenticate" and "Authenticate" methods. These methods both provide a parameter of IServiceBase which contains the original Request. I was thinking about modifying the DTO but it is null. So I looked at the cookie values and I could easily add a value for "ss-opt=perm" in there. But I'm not even sure "perm" is right.
My question is this...is this the best way to set the RememberMe flag to true on the server side? My partner says the library he is using is called "afnetworking" but that looks to be a dead end.
Marcus
EDIT: My partner found a way to set the "ss-opt" value with their tool but this does not seem to be helping. He is still experiencing a problem after 6 hours. There is additional information. The first response he gets after waiting 6 hours has the "ss-pid" cookie value but the "ss-id" and "ARRAffinity" cookies are missing from the first response. The subsequent responses has them. Weird.
I am going to switch to using the AzureCache instead of MemCache to see if that helps. But I did not update the server in that 6 hours so shouldn't the memory cache still have the session id values that correlate to the ss-pid value?
EDIT 2: I was under the false impression the "cache" was where the system kept the permanent ss-pid values and all I had to do was to register the cache. How do I keep the ss-pid values around between server updates?
Switching to AzureCache and having the client insert the ss-opt cookie seems to be working.

ColdFusion 8 to ColdFusion 10 Migration: CFloginUser Not Working As Expected

After upgrading from CF8 to CF10, moving all files and databases and jumping through all the configuration hoops, the new version of the site is up and running, but the authentication/login is not working.
Here are the environments:
Old server: ColdFusion Enterprise 8,0,1,195765
Operating System: Windows Vista*
OS Version: 6.0
Update Level: .... hf801-00007.jar
IIS Version: 7
(*not sure where that "Vista" comes from? The System Information says "Windows Server 2008 Datacenter without Hyper-V")
New server: ColdFusion Enterprise 10,0,11,285437
Tomcat Version: 7.0.23.0
Operating System: Windows Server 2008 R2
OS Version: 6.1
Update Level: .... chf10000011.jar
Adobe Driver Version: 4.1 (Build 0001)
IIS Version: 7.5
I have a pretty standard ColdFusion login system, using cfloginuser in Application.cfc. After I login on the old site, outputting #GetAuthUser()# prints my username to screen, and all my role-based rules work.
On the new server, outputting GetAuthUser() prints empty.
On the old site, cfdump var="#SESSION#" includes:
cfauthorization_kllcms dXNlcm5hbWU6cGFzc3dvcmQ6YXBwX25hbWU=
On the new site, CFDUMP of session does not show a cfauthorization_kllcms value at all. All other session values exist in both instances.
It is the exact same codebase, database structures, etc. Naturally, none of my role-based rules work, because they all depend on validation of getAuthUser() and IsUserInRole("x") conditionals.
I know the initial login process itself is working, because it is correctly setting session variables with user information, and they are available on subsequent requests. But none of the traditional cflogin data is available on subsequent calls.
Any ideas what might have changed?
UPDATE: Per Adam's suggestion (below) I set up 2 test apps, one on the old server, one on the new.
Old Server: http://cfloginold.cimhost.com/index.cfm
New Server: http://cflogin.cimhost.com/index.cfm
Use "test" and "demo982013" as user and password.
Append ?logout=true to the URL to logout and re-test. These two apps have exactly the same code, same database. I am dumping session and form values to screen, along with GetAuthUser() value.
The authentication method is pretty much exactly as outlined in Adobe's documentation, and I can share all relevant code here if necessary.
Note that in the "new" server, the form loads each time you visit the page, whether you have logged in or not. This is exemplar of the fact that the cflogin session is not being retained or recognized, thus presenting the login form each visit (although not on initial form completion, which shows that cflogin is at least working on the initial login, I think).
UPDATE 2:
I've been drilling deeper into this, and I am able to get cfloginuser to fire a couple of ways, just not as part of the standard Adobe documented application-based user security model.
Option 1: I created a standalone page, and placed the following code in it:
<cflogin><cfloginuser name="directtest" Password = "2519D6025B5191F754D01BE163972628" roles="1"></cflogin>
I then instructed Application.cfc to allow this past the cflogin gate. You can see the results by pointing your browser to: http://cflogin.cimhost.com/directlogin.cfm?bypass=true
Voila. 'cfauthorization_cicmstest' value has been set, and user is logged in. Subsequent calls to GetAuthUser() are successful. So I know now that CF10 and the application do allow cfloginuser, and the user session can be created.
Option 2: I then decided maybe it was something about my Application.cfc file, so I again bypassed the cflogin gate, and placed the hard-coded cfloginuser snippet directly in my Application.cfc onRequestStart function. Logged out and visited: http://cflogin.cimhost.com/index.cfm?bypass=true&noquery=true
Again, cfauthorization_cicmstest value was successfully set, and user is logged in.
However, logging in still fails if the cfloginuser directive is fired within the actual cflogin process in Application.cfc. Here is what that code looks like:
<cfquery name="loginQuery" dataSource="mydatasource">
SELECT id,username, userroles
FROM myusertable
WHERE
username = '#cflogin.name#'
AND userpass = '#HASH(cflogin.password)#'
</cfquery>
<cfif loginQuery.userroles NEQ "">
<cfloginuser name="#cflogin.name#" Password="#cflogin.password#" roles="#loginQuery.userroles#">
<cfset MyMessage = "#MyMessage#<br />The Login Query fired and returned expected - loginQuery.userroles NEQ ''">
<cfelse>
<CFSET MyMessage = "Your login information is not valid. <a href='index.cfm?logout=1'>If your session timed out, click here!</a>">
<cfinclude template="loginform.cfm">
<cfabort>
</cfif>
I know that the query is successful, because I am setting an alert message that tells me the loginquery.userroles value was not empty, which is the condition for processing cfloginuser.
I know where the code is failing now, just not why. I've tried hard coding that cfloginuser value, and it still fails. I'm at a loss as to what to try next. The cfloginuser functionality works, just not in the one place (within the loginQuery.userroles conditional) that I need it to work.
UPDATE 3:
Just to prove to myself it wasn't my code, I created 2 more test sites, one on the old server, one on the new server:
New Server (CF10) = http://cf10loginadobe.cimhost.com/securitytest.cfm
Old Server (CF8) = http://cf8loginadobe.cimhost.com/securitytest.cfm
I copied exactly Adobe's 3 files from their Application-based security example. I created a database table with their schema and values. I added my cfdump outputs to show the sessions being created.
Test with user of "Bob" and password of "secret". Even with Adobe's own code, the tests fail on CF10.
I'm not sure what to do next. Rewriting the application to not use cfloginuser is not an option, as we have more than a dozen applications we are migrating to CF10 that use this authentication model, across hundreds of templates.
It's possible it's something weird about how IIS7.5 is handling ColdFusion requests, but that seems unlikely given the ability to successfully instantiate cfloginuser outside of the query result conditional.
ColdFusion 10 Application Based User Security Is Broken
I have deployed two test sites, using Adobe's own example code for application based user security, copied in its entirety from the Adobe website. One test site is in ColdFusion 8, one is ColdFusion 10. The code and databases are identical on both sites. I added cfdump output to monitor session variables and login status as they are set.
Test Site ColdFusion 8: http://cf8loginadobe.cimhost.com/securitytest.cfm
Test Site ColdFusion 10: http://cf10loginadobe.cimhost.com/securitytest.cfm
Logging in using a user of "Bob" and password of "secret" demonstrates the failure in CF10. Initially it appears login was successful, but note that the cfdump of the session does not show a cfauthorization_orders value in CF10, where in CF8 the value is present.
In CF8 subsequent visits to the same URL after login correctly retain the logged in user status and do not present the login form. In CF10, no session was actually created for the user, and therefore subsequent visits to the same URL prompt for login again.
I have tested this thoroughly, including bypassing the cflogin logic and forcing cfloginuser, which successfully creates an authenticated user in CF10, demonstrating that cfloginuser is supported.
It appears to me there is something about CF10's handling of the OnRequestStart function in Application.cfc that creates and then immediately kills the user session.
Workaround: The inelegant workaround I am using involves re-creating the cfloginuser session instantiation in a subsequent OnRequest function in Application.cfc. The code is as follows:
<cffunction name="onRequest">
<cfargument name = "targetPage" type="String" required=true/>
<cfinclude template=#Arguments.targetPage#>
<cfif IsDefined("loginQuery")>
<cfif loginQuery.userroles NEQ "">
<cflogin><cfloginuser name="#loginQuery.username#" Password = "#loginQuery.userpass#" roles="#loginQuery.userroles#"></cflogin>
</cfif>
</cfif>
</cffunction>
If there was an attempt to login in the OnRequestStart, I leverage the results of that request, check if it was valid (loginQuery.userroles NEQ ""), and then instantiate the authenticated session. There is a downside in that users have to click to a new page for logged in options to appear. The GetAuthUser() test is not met until another page load is requested.
Extensive testing of alternatives within Application.cfc did not reveal any alternative to this approach.

Creating a new JSESSIONID after authentication

When a user hits login page of a Portal (it could be Liferay, Jboss Portal..), JSESSIONID cookieis created by the container. After entering credentials in the login page, same JSESSIONID gets carried over.
Here, end user will come to know the JSESSIONIDbefore he could get authenticated (by checking the JSESSIONID in the login page). This will increase vulnerability of the site for hacking because one can know the JSESSIONID before one gets authenticated.
This post advices to have a different JSESSIONID after authentication.
So, creating a new JSESSIOND can be achieved by Portal server being used (am using Liferay CE 6.0) or it has to be handled by web application developer? If it has to be handled by web application developer what is the best way to do? request.getSession(true) is the only option?? If I need to instruct Liferay to create a new JSESSIONID after authentication how it can be done?
This looks a lot like the session fixation problem I solved for Liferay 5.2.5 a long time ago. The solution consists of creating a custom Tomcat Valve that will force a new session ID. So the solution isn't really specific for Liferay and is dependent on if you use Tomcat or not.
I suspect it shouldn't be too difficult to adapt my old solution to a newer Liferay/Tomcat combination. You can find the necessary information about my solution in my old and currently unmaintained blog (if I only had more time...): Fixing session fixation in Liferay
The problem here is not that the user knows the session ID (the user always knows it, it is sent by his browser). The attack scenario is that the user, while logged out, clicks on the link that already has JSESSIONID embedded, then authenticates and this session becomes a logged-in session. Now someone who initially created the link can use the same session to act as the user. More details at https://en.wikipedia.org/wiki/Session_fixation
So yes, use the web or app server to re-set session ID after a user authenticates. You do not need to write it yourself. For Tomcat 7: http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection
You can fix this issue by setting the following property to true like Liferay has as default.
#
# Set this to true to invalidate the session when a user logs into the
# portal. This helps prevents phishing. Set this to false if you need the
# guest user and the authenticated user to have the same session.
#
# Set this to false if the property "company.security.auth.requires.https"
# is set to true and you want to maintain the same credentials across HTTP
# and HTTPS sessions.
#
session.enable.phishing.protection=true
#Thiago:
This session.enable.phishing.protection=true is by default true in portal.properties. Anyhow, I have added this entry in portal-ext.properties. But, even then JSESSIONID remains same before and after login.
I have implemented a filter as per this link. After implementing this filter, when I hit login page of Liferay, one JSESSIONID gets created. After I enter the credentials and login, the same JSESSIONID is retained.
I have implemented this filter in a Servlet and not in any of my Portlets or in Liferay's ROOT application. My Servlet is deployed in LR + Jboss AS bundle. Am first hitting the Servlet and from here I have a link which will redirect to Liferay's login page. I have implemented this filter in my Servlet because Container will append JSESSIONID for first time request as it doesn't know if cookies are enabled or not. Since, JSESSIONID is getting appended, am not able to retrieve my images in Servlet (because url is myImage.jpg;jsessionid=). Hence, I have implemented this filter.
Is this filter conflicting with Liferay's configuration? Even after setting session.enable.phishing.protection=true same JSESSIONID is retained means what else could be the problem?
Put this code inside the portal-ext.properties.
It will fix the problem, each and every time logged in, new session id will be generated.
session.enable.phishing.protection=true
com.liferay.util.servlet.SessionParameters=true

can I discover another users LTPA2 token on the machine / in the browser?

If you put sit Paros on the traffic between your browser and a web application being hosted in WebSphere, you will have two session identifiers passed as part of the cookie section of the HTTP request:
A JSESSIONID. This is your HTTPSession ID as far as I can tell.
An LTPA2 token. This is your “single sign on” session as far as websphere is concerned.
Now, IBM say that a single hosted application cannot invalidate the LTPA2 token when a user is signing out. The thinking behind this is that it is an SSO identifier, so a single application should not be able to invalidate it as it is intended for use across multiple applications. There is no configuration in WAS to declare “this environment hosts only one application so therefore that app can invalidate the LTPA2 token”.
What is worrying is that these LTPA2 sessions hang around for a configurable amount of time. Therefore, if another user got a handle on a users’ LTPA2 token, they can use it to access that users’ session and therefore their sensitive data.
You can prevent a man in the middle attack to capture the session value by forcing the transmission of the cookie to occur over SSL, and by specifying HTTP only for cookies. However, I am still worried about the cookie being available on the local machines’ hard drive. The browser has to store it somewhere, so therefore there has got to be a way to get access to it?
My question is, is it possible for someone to get an LTPA2 value such as this from the hard drive? Say someone sits down in a library, signs in to their online banking, does some work and then logs out. Is it possible for the next user to get the LTPA2 token somehow?
I tried searching through the directories where I thought FireFox 4 and IE8 would store the cookie, but couldn’t pattern match the value. My gut instinct is that it may be possible to find this data on certain browsers?
By default the LTPA2 token is a "Session Cookie" Websphere does not set an expiry on that cookie, and it is just stored in Browser Memory until the user closes their browser.
Unless your client is explicitly manually pulling that cookie and storing it client side, it will not be stored in any files on the user's machine.
You can invalidate the LTPA token if you want to.
But this would require using IBM extensions (naturally)
Look at these:
(a) http://www.ibm.com/developerworks/websphere/techjournal/1003_botzum/1003_botzum.html
LTPA token is non-standard, but is simply a credential/token and does not impact the application development team.
Redirects to the ibm_security_logout URL in order to remove the LTPA token when users log out.
(b) ftp://ftp.software.ibm.com/software/dw/wes/0409_botzum/WAS-511-Security-AdvancedTopics.pdf
Though these articles are old, these should still work (as these basics haven't changed a lot over the years)
By invalidating the LTPA token(which as Terrell mentioned in a "in memory session cookie" )all your worries that you had should be gone.
HTH
Manglu

what is the vulnerability of having Jsessionid on first request only

Recently we removed jsessionid from URL did cookies based session management to prevent "session hijacking attack"
But we found that first request URL always has jsessionid when cookies are enabled and subsequent request URL has NO jsessionid.
using the jsessionid from first url we could directly hit other pages in the workflow
Question : is there any security vulnerability exposing jsessionid only on first request?
There is a solution to remove jsessionid from first request , but wanted to check , if its really vulnerable to mandate the changes
thanks
J
EDIT : I got my doubt clarified. Thanks for replies.
What you've done here could improve the overall security of the solution somewhat, but won't necessarily prevent session hijacking.
the security issue with placing the session ID in the URL is that URLs are exposed in various places (eg, copy and pasted URLs could expose a live session, URLs can be stored in proxy server logs, web server logs and browser history), which could allow an attacker to grab a valid session ID and get access to your users data.
Ideally you should remove the JSESSIONID from the URL in all places, and only use cookie storage.
Additionally if you want to mitiate Session hijacking there's a number of other areas to consider.
You need to use SSL on all pages where the session ID is passed (this is to mitigate the risk of the session ID being intercepted in transit (eg, the Firesheep attack).
If the session ID is set before you authenticate the user, you should ensure that a new session ID is issued when the user logs in.
Also if possible the session cookies should be use of the httpOnly and secure flags, to reduce the risk of them being leaked over cleartext channels.
There's some good additional information on the OWASP Site
BTW if you've got more question on the security side of things, there's a stack exchange site specifically for that at Security.stackexchange.com
did cookies based session management to prevent "session hijacking attack"
Whats stopping the cookie being hijacked?
Session managment is a server side thing - You need to server to check (based on the cookie) that the user is meant to be logged in.
I don't think you've improved security here at all to be honest, take a look at this excellent article to see why.
If someone gets hold of the session id then they pretty much hijack the whole session, see Predictable Session IDs vulnerability.

Resources