Session variable not found - coldfusion

for a long period of time I have an issue with Session variables. I'm looking for some pointers or directions to address this problem. I try to explain what is happening and I understand that the information provided isn't sufficient to understand what is happening, but I'm trying to solve this and it's driving me nuts :-)
I have several Lucee webapplications (Lucee: 5.3.7.48) which are also available as Cordova app. Error messages are sent to my by e-mail. On a daily bases I receive about 100 messages that the session variable can not be found.
[APP] is a session variable, set in the file index.cfm.
<cfparam name="SESSION.auth.app" default="">
In line 592 there is something like
<cfif session.auth.app is 1>do something</cfif>
I don't want to focus on line 592, the real problem is that the session variable is/gets lost. What happens next is that the user is redirect to the login page (login.cfm), because the session is lost and then the problem repeats, it's a kind of loop. The application has a save username/password option.
This all happens when the application is running in the background, like the Cordova app running in the background. I know this because I reached out to a user when receiving 20 error messages, and he told me that I wasn't using the application at the time of the error messages.
In conclusion I measure a user when he is using the login.cfm page. As you van see in the image there is a peak in usage on March 16th, which has to do with the problem described.
I understand that I provided not much useful information to go on, but can someone give me some directions how to approach this problem?
UPDATE April 14th
I have changed the way session vars are set and followed the suggestions in the reactions.
In the application.cfc I have add:
<cffunction name="onSessionStart" access="public" returntype="void" output="false" hint="I fire when a new session begins.">
<cfset SessionRotate()>
<cfset SESSION.app = ''>
<cfset SESSION.device = ''>
<cfset SESSION.app_file_url = 'window.open'>
</cffunction>
Restarted Lucee just the be sure. But still the same error messages, APP doesn't exist. After some additional searching I found: https://www.bennadel.com/blog/1535-coldfusion-session-is-always-created-even-if-onsessionstart-fails.htm
Could this be a Lucee bug? Are do you have more suggestions to try?

In your onSessionStart function, Can you please change it to this?
<cfset session.auth = {}>
<cfset session.auth.app = ''>
I see you are checking <cfif session.auth.app is 1>do something</cfif> which should have the session.auth defined for it to work.
I hope the above helps.
Also, I'd be interested in knowing what are you dumping on the screen?

Related

How do I locate a custom tag instantiation in a coldFusion App

I am migrating a very old app (currently running in CF8) to Lucee. But I am running into a problem with what appears to be a custom tag of some sort.
I have tried to make sure that all the virtual directories are the same in IIS for both the old and the new installs. And made sure the mapping and custom tag paths in both the CFIDE and the Lucee Admin are the same.
But I am getting this error. And can't figure out how this cflink is being instantiated.
I have found the location of the erroring code on line 300 the utils.cfc file
I haven't used custom tags in a long time but thought they were generally called with an underscore and the code should like more like <cf_link pageid="#LinkPageID#" Init="start"> if this was being called as a custom tag.
If I go the the current CF server that is running this app I can find that a cfclass files HAS been created
From a file called cflink.cfm in a directory called "tags" even though there seems to be no mapping for the "tags" directory nor is is listed under "custom tags paths" in the administrator.
This App was start in 2003 and as you can imagine has grown into a mis-match of spaghetti code and no one from the beginning is around to ask how this tag is instantiated.
Does anyone with experience in legacy code has any other ideas where I should be looking to try to get this to work? The currently has only a production environment and if I can get it to work on Lucee it will not only be a dev environment that hasn't existed here in 10 years but will be a great way for me to be able to continue showcasing Lucee as a great CFML engine
Adding addition info
Leigh had asked if the init might be a jar reference but in the cflink.cfm file I see this code:
<cfif Attributes.Init IS "start">
<cfset Request.PageID = Attributes.PageID>
<cfset Request.Page_Width = Variables.qParentInfo.Page_Width>
<cfset Request.Page_Height = Variables.qParentInfo.Page_Height>
<cfset Request.Page_TypeID = Variables.qParentInfo.Page_TypeID>
<cfset Request.AddPath = "">
<cfif IsDefined("Attributes.Anchor")>
<cfset Request.Anchor = Attributes.Anchor>
<cfelse>
<cfset Request.Anchor = "">
</cfif>
<cfset Request.IsInternalLink = false>
<cfexit method="EXITTAG">
</cfif>
There are also references to cflink in the code inside tags\cflink.cfm
<cfif Len(Variables.qParentInfo.ParentID) GT 0>
<!--- Add the page title to the end of the path --->
<cfset Request.AddPath = ReplaceNoCase(Variables.qParentInfo.Nav_Title," ","_","ALL") & "/" & Request.AddPath>
<cflink init="working" pageid="#Variables.qParentInfo.ParentID#" popcode="#Attributes.popcode#">
<cfelse> ......</cfif>
Although this may be recursion given it was written in 2004 I kind of doubt it
Adding screen shots of searches
If anyone else runs into this. In CF8, and presuming earlier versions, you could put a cfm file into the ColdFusion8\wwwroot\WEB-INF\cftags Directory and that file in this case ColdFusion8\wwwroot\WEB-INF\cftags\link.cfm Then acts as any other cftag.
I was able to find the person who originally build this app in 2004 and he told me that they did it this way to avoid typing the underscore that they would have typed if they'd done it as a custom tag.
I kind of get it since this tag is used everywhere in the app, literally hundreds of times. Bit boy with a bitch to find.
Now all I have to do is figure out how to move it to the Lucee world in a similar fashion. So it instanciates the same way.
Thanks #Leigh for all your help, you are always amazing!
Adding more information
if there are files in the WEB-INF\lucee\library\tag the corresponding Lucee directory is WEB-INF\lucee\library\tag. These files are read on load and then able to be used as any other cf tag.
For example if you have file WEB-INF\lucee\library\tag\link.cfm it can be called by `cflink'.
Seems like a cool idea but a bit of a bitch for someone to find 10 years after the fact

How can you get a list of the datasources used to generate a page in coldfusion?

When you add a debug IP to review the debug information from the collection of templates that are parsed to present the page, it includes a list of all queries from that page.
Is it possible to get access to that object for inspection?
I'm looking at trying to automate the documentation which data sources are in use for which page requests. We have a large number of small web apps that access different databases and have different dependencies. I'm hoping to find a way to automate the documentation of these dependencies rather than having to manually review all code for all of the webapps.
Not sure if the object doesn't get created until after the page creation is too far gone to actually do anything with the data, but who knows...
Here is a snippet of code that you can add to the end of your template to get a list of datasources used on the page:
<cfobject action="CREATE" type="JAVA" class="coldfusion.server.ServiceFactory" name="factory">
<cfset cfdebugger = factory.getDebuggingService()>
<cfset qEvents = cfdebugger.getDebugger().getData()>
<cftry>
<cfquery dbtype="query" name="cfdebug_qryDSN">
SELECT DISTINCT DATASOURCE FROM qEvents WHERE type = 'SqlQuery'
</cfquery>
<cfcatch type="Any">
<cfset cfdebug_qryDSN = queryNew('DATASOURCE')>
</cfcatch>
</cftry>
<cfdump var="#cfdebug_qryDSN#" label="cfdebug_qryDSN">
PS: most of the inspiration for this snippet came from {cfusion 10 home}\cfusion\wwwroot\WEB-INF\debug\classic.cfm. You can get some good ideas on how to gain access to debugger objects/data from this file.
For anyone stumbling across this....
If your [cfroot]/cfusion/lib/neo-datasource.xml file is WDDX encoded and you're not sandboxed, you can use the following (tested on CF2021)
<cflock type="readonly" scope="Server" timeout="5">
<CFSET LibPath=Server.System.Properties["coldfusion.libPath"]>
</cflock>
<CFFILE action="Read" file="#LibPath#/neo-datasource.xml" variable="DatasourcesWDDX">
<cfwddx action="wddx2cfml" input="#DatasourcesWDDX#" output="Datasources">
<cfoutput>#StructKeyList(Datasources[1])#</cfoutput>
<cfdump var=#Datasources#>
The first position of the Datasources array holds a structure containing information on each configured datasource with the main key being the name of the datasource.
Here's an idea that'll work for each application which uses an Application.cfc.
Enable Request Debugging Output in CF Administrator.
Configure Debugging IP Addresses so that every page receives debugging information.
Assuming that Select Debugging Output Format is set to classic.cfm, short circuit {cfusion 10 home}\cfusion\wwwroot\WEB-INF\debug\classic.cfm by making <cfreturn> the first executable statement in classic.cfm. This will prevent any pages from seeing the debug output.
In Application.cfc::OnRequestEnd() do what Scott Jibben suggested. You can wrap Scott's idea in an <cfif IsDebugMode()>.

What is wrong with this CFIF structure?

I have the following at the top of a page...
<cfif isdefined("session.loggedin") and session.loggedin eq true>
<cfinclude template="includeUserInfo.cfm">
<cfinclude template="includeSideBar.cfm">
<cfelse>
<cflocation url="../sign-in.cfm">
</cfif>
When I execute the page and session.loggedin DOES equal true it executes as expected and adds the included files.
If I hit the page without logging in - I'm not being redirected to the sign in page - I'm just getting a completely blank page - zero html in the view source.
Session management is enabled in my application.cfc file
I'm not sure if what I am doing is wrong - appreciate any advice.
OK - so (as is often the case) I had missed the underlying cause of the problem - and while focussing on the imagined problem with the CFIF statement itself, missed the small cfinvoke that was before it in the code. That was trying to execute a database lookup, but failing when a user was not logged in.
swapping these around and making sure the block above is before everything else on the page has done the trick. Go me. Thanks everyone for the input.

Change to OnRequestEnd behavior in CF9 (was ColdFusion 9 Bug - Can't Reference a Request Variable in OnRequestEnd)

Here's a weird one. I haven't had any luck finding any information about this on Google, so I'm wondering if any of you have seen this before?
I've got a CFC in the request scope and then in the onRequestEnd event I grab that CFC out of the request scope and do some end-of-request stuff with it. The problem is I can't reference the variable in my onRequestEnd event because it produces an error that says it's not defined in the scope... but here's where it gets really weird and why I KNOW this is a bug (it's not just a suspicion)... If I DUMP the variable, the cfdump tag successfully displays the CFC and all its stuff... and then produces the same "is undefined in scope" error. Here's a screen-capture.
So... anybody seen this before? 'Cause I'm totally stumped. I've already installed the 9.0.1 updater and both of the cumulative hot fixes.
p.s. Yeah, I know it says OnRequestEnd.cfm, but this is actually inside the Application.cfc onRequestEnd method -- it's a legacy from the framework dating back originally to CF5, just go with it. ;P
EDIT: Okay, it's gotten weirder... I tried using evaluate() to set it to a local variable, which apparently works, because then I dump the local variable. The dump still works, even though it's on line 2 AFTER the line on which the error occurred?!!
EDIT 2: EDIT: Here's the code from the Application.cfc that includes the file where the error occurs:
<cffunction name="onRequestEnd" access="public" output="true">
<cfinclude template="OnRequestEnd.cfm">
</cffunction>
It appears to have something to do with the combination of the method and the include file.
It still fails if I execute the method in the onRequestStart like this:
<cffunction name="onRequestStart" access="public" output="true">
<cfset onRequestEnd() />
</cffunction>
But it works fine if I include the file in onRequestStart like this.
<cffunction name="onRequestStart" access="public" output="true">
<cfinclude template="OnRequestEnd.cfm">
</cffunction>
HOWEVER! There's obviously more to this because I can't create a simple test case. If I create a new project with a very simple application.cfc in it and replicate all these details, it works fine. So there's something else in the framework that's contributing to it beyond just the method names and file names.
And the file name doesn't seem to actually contribute, since it still fails in the same way if I change the name of the file like this:
<cffunction name="onRequestEnd" access="public" output="true">
<cfinclude template="reqend.cfm">
</cffunction>
EDIT 3: Okay it has nothing to do with the file... well it does, but not with the file name... At the bottom of the onRequestEnd.cfm is this code
<!--- this seems to help resolve a leaky-memory issue in CF/JRun --->
<cfset structClear(variables) />
<cfset structClear(request) />
<cfabort />
If I comment out those StructClear statements, then the error goes away, which told me that it was executing the OnRequestEnd.cfm twice... and I THINK that means that CF9 changed the behavior of the CFABORT tag and it now executes the onRequestEnd event when the tag is used... it didn't in previous versions of cf...
I didn't find documentation of this, but I did find this blog from Ben Nadel about this behavior with the CFLOCATION tag, so it seems to be more generally about the onRequestEnd event. It seems now in CF9, no matter how a page finishes executing, the onRequestEnd event is executed at the end... That's a change from all the previous versions and so it mucks with code I had created in order to actually cause this to happen on previous versions. Since I was causing execution of the onRequestEnd and then aborting the page early, CF now executes the onRequestEnd, aborts and then executes the onRequestEnd again because of the abort.
Luckily, this fairly simple bit of code at the top of the template seems to fix the problem:
<cfif structIsEmpty(request)>
<cfexit method="exittemplate" />
</cfif>
I decided to leave this question here (rather than deleting it) since it may help some other folks, though I found the source of the problem and a workaround while working with some of the comments and it wasn't what we thought. Ben Nadel also posted a blog about the change to CFABORT a while ago as well... and Adam Cameron tells me that although this change was added by-design in CF9 (without warning anyone apparently, since I saw no mention in the LiveDocs and added 2 comments about it), it was then removed in the (not yet released?) CF10. I think Adam might be in the beta, I'm not sure.

ColdFusion security by checking ARGUMENTS.TargetPage in Application.onRequestStart?

I have a ColdFusion app in which I wish to restrict access to certain pages, based on some criteria. I am currently doing it like this, in Application.cfc:
<cffunction name="OnRequestStart" access="public" returntype="boolean" output="true">
<cfargument name="TargetPage" type="string" required="true" />
<cfif not SESSION.isAdmin and REFindNoCase("/admin",ARGUMENTS.TargetPage) >
<!--- Deny non-admin access to admin pages. --->
<cfinclude template="/notauth.cfm">
<cfreturn false />
</cfif>
<cfreturn true />
</cffunction>
My main concern is: How vulnerable is the general approach of checking TargetPage against a regex, and are there ways to improve the security of this design? Specifically, I'm concerned about avoiding "canonical representation vulnerabilities." See here.
For example, using just a REFind instead of REFindNoCase would let people slide right on through if they went to "/ADMIN/". Are there are other things to watch out for here?
I know there are other designs, like using another Application.cfc in a subfolder, or doing checks right in the page code. But I like the idea of having all my security code in one place. So please only suggest those in your answer if there's no way to do the above securely, or if it's just really a bad idea for some reason. Thanks.
I'm sure there are reams of this stuff on the internets but here is my take on it :)
They way I would solve your specific example is to maintain a database list of scripts that are restricted (a blacklist) unless you are a member of a certain group (i.e. you are an admin).
You can make this as complicated as you wish but for a simple start you could compare the full script name (CGI.SCRIPT_NAME) to a query of queries representing blacklisted pages you store in the APPLICATION scope that you loaded in onApplicationStart() called qRestrictedList.
So in onRequestStart you could do the following:
<cfquery name="qThisPageRestricted" dbtype="query">
SELECT * FROM qRestrictedList
WHERE ScriptName = '#CGI.SCRIPT_NAME#'
</cfquery>
<cfif qThisPageRestricted.recordCount and not SESSION.isAdmin>
<cfinclude template="/notauth.cfm">
<cfreturn false />
</cfif>
Even better, you can expand on this at a later date by wrapping all this in a 'authentication' CFC and creating user groups and levels, i.e. move your logic out of onRequestStart() and encapsulate it.
But as a start, storing the data in the database might be a more maintainable way for you to get this done and provide a better foundation for future changes to how your authentication works.
I hope this helps.
It may worth to make regex a bit stricter:
REFindNoCase("\/admin\/([A-Za-z_]+)\.cfm", ARGUMENTS.thePage)
A better approach would be to put an application.cfc in the /admin directory that controls access (maybe based on a SESSION variable set through logging in as an admin), and have that "child" application.cfc reference the parent one if necessary.
See this question for an example on how to do this: Extending application.cfc in a subdirectory