Session Variables and Remote CFC Calls - web-services

Why does ColdFusion not recognize my session variable when I remotely call a CFC?
Example:
I have a CFC that I call using:
http://www.mywebsite.com/CFC/myfunc.cfc?method=dosomething;arg1=foo;arg2=foo2
If I put the following...
<cfdump var="#session#" abort>
...on the very first line of myfunc.cfc, I see a properly displayed cfdump of all of my session variables. However, if I do something simple like:
<cfset myvar = session.datasrc>
I get a 500 error. Element DATASRC is undefined in SESSION.
session.datasrc appears in the cfdump and if I don't access it remotely (like with a <cfinvoke>) it works fine. Am I missing a some property, or a setting in CFIDE? Something somewhere isn't allowing for remote calls to CFC's to access session variables. Thanks.

Calls to a "remote" cfc do maintain session if called through a browser.
<cffunction access="remote" returntype="any" output="No" hint="this hint" name="test">
<cfargument required="false" name="username" type="string" default=""/>
<cfset session.username="#arguments.username#">
<cfreturn session>
</cffunction>
Call the cfc with http://localhost:8500/CFCs/your.cfc?method=test and you will see the session id will remain constant. Call it as http://localhost:8500/CFCs/your.cfc?method=test&username=bob and you will set the session variable, strip off the argument from the url and the session variable is persisted.
If you are calling the remote cfc without using a browser, you will need to "manually" pass in the sessionid as discussed here

Remote calls to a cfc don't have any sense of session. It's always a one shot deal.
If you access the cfc via the url as you have above, you'll gets session because it's like accessing it as a page. The web server will pass through all the elements, such as session cookies, through to the server making the session scope available to the cfc.
If you access the cfc remotely none of this will be available to the component because of the way it was requested.
You should never rely on transient scope variables inside of service methods. Either inject them using something like coldspring to provide dependancy on a "configuration" service or pass values in as arguments.
To be blunt with you, the session scope is absolutely not the right place to be storing datasource names. Given that you're on ColdFusion 9, you might be interested in looking at the application wide datasource setting under Application.cfc

The session isn't the proper scope for variables like a datasource unless you have different datasources for different users. The application scope is the proper location for application-wide variables. I would first try using the application scope and see if you are still having issues. Also check things like variable name spelling, and try to hit that function locally from within the application via a CFINVOKE call (set the function to public if you need to) to see if it works fine locally. Then you know it's probably something with the way you are calling it remotely.

Related

CF10 websocket p2p can invoke any public functions in any CFC from JavaScript. How is this Not a security risk?

In Using WebSocket in point-to-point communication in Adobe ColdFusion 10 Dev Guide, the javascript object mysocket created by <cfwebsocket> can call an invoke() method that can literally invoke Any public method on Any CFC from JavaScript.
How is this Not a security risk? How shall a cfc / function protect against being invoked by websocket?
1. Create a CFM page index.cfm.
<script type="text/javascript">
function msgHandler(msgobj){
var txt = document.getElementById("myDiv");
var message = ColdFusion.JSON.encode(msgobj);
txt.innerHTML += message + "<br >" + "<br>";
}
function invokecfcfn(){
var fname= document.getElementById("fnname").value;
if (fname == "f2") {
alert("f2 selected");
mysocket.invoke("mycfc", "f2", ["echo"]);
}
else
mysocket.invoke("mycfc", fname);
}
</script>
<cfwebsocket name="mysocket" onmessage="msgHandler"/>
<form>
<select id="fnname">
<option>f1</option>
<option>f2</option>
<option>f3</option>
</select>
<input id="invokefn" name="invokefn" value="Invoke CFC function " type="button" onclick="invokecfcfn();">
<div id="myDiv">
</div>
</form>
2. Create a CFC mycfc.cfc that contains the function called from the client page.
<cfcomponent>
<cffunction name="f1" >
<cfreturn "Message returned from f1">
</cffunction>
<cffunction name="f2" returntype="string" >
<cfargument name="arg1" type="string" required="true" >
<cfset msg= "Message from wsssendmessage of f2 which you called with arg " & arg1>
<cfset wssendMessage(msg)>
<cfreturn "Message returned from f2">
</cffunction>
<cffunction name="f3" >
<cfthread action="run" name="t1" >
<cfloop index="i" from="1" to="10">
<cfset sleep(20000)>
<cfset wssendMessage("Message #i# from wsssendmessage of f3 #now()#")>
</cfloop>
</cfthread>
<cfreturn "Thread initiated in f3">
</cffunction>
</cfcomponent>
EDIT: not Any function, private function returns:
{
"clientid":39550088,
"ns":"coldfusion.websocket.channels",
"reqType":"invoke",
"code":4001,
"type":"response",
"msg":"The method f1 was not found in component mycfc.cfc."
}
UPDATE:
I tried moving mycfc.cfc to /com (outside of webroot) and added a mapping to /com and the functions can STILL be successfully invoked.
UPDATE: July 3, 2013
The Adobe Product Security Incident Response Team (PSIRT) is aware of
this issue and is actively engaged with the ColdFusion Product Team to
release a fix.
http://blogs.coldfusion.com/post.cfm/coldfusion-10-websocket-vulnerebility
UPDATE: July 9, 2013
Adobe has released a security hotfix for ColdFusion 10 for Windows,
Macintosh and Linux. This hotfix addresses a vulnerability
(CVE-2013-3350) that could permit an attacker to invoke public methods
on ColdFusion Components (CFC) using WebSockets.
http://www.adobe.com/support/security/bulletins/apsb13-19.html
I don't think you can fix this with ColdFusion as it currently stands (update: this was written prior to ColdFusion 10.0.11 being released; the issue has now been resolved by 10.0.11). I don't think Bruce's CFML-based answer - whilst it or a variation thereof would work - is really feasible in the real world.
I would probably fall back to using firewall rules: web socket requests come in on a specific port, so you could have a set of rules around requests on that port, and which methods are allowable over it.
This is not a great solution, but it's probably the most expedient given the situation.
I pointed to my research on the CF side of things in a comment to your original question, but it's probably better being linked to from here: "Web socket security issue: risk assessment & findings"
Coldfusion 10 websockets invoke feature does seem broken to me after actual testing and further investigation of the new documentation pages and other projects (this thing is complicated!). I spent over an hour trying to get something to execute before the invoked function is run. I can't!
There are new "channel listener functions" documented here:
http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSe61e35da8d318518767eb3aa135858633ee-7ff9.html
However, the documentation clearly states that the "invoke" feature doesn't have a listener function. It also appears Application.cfc or the cfc listener don't execute on each request at all when invoke is run.
This seems like a design flaw. The language needs more event listeners or you can't use websockets without adding security to every function in your application.
The security within each function could be done like the code below, but it is not very practical to modify every function in an application:
<cfscript>
local.meta=GetMetaData(this[url.method]);
if(not structkeyexists(local.meta, 'access') or local.meta.access NEQ 'remote'){
throw("Function access must be set to remote.");
}
</cfscript>
You could also consider using a web server proxy in front of Coldfusion and use regular expressions to verify the request information so that only the websocket portion of your application has to be open on the public websocket port. Nginx 1.4+ has support for websocket proxying now: http://nginx.org/en/docs/http/websocket.html
Note: I have not tested using nginx websocket proxy yet. If it works, this would be a far easier solution.
Adobe has released a security hotfix for ColdFusion 10 for Windows,
Macintosh and Linux. This hotfix addresses a vulnerability
(CVE-2013-3350) that could permit an attacker to invoke public methods
on ColdFusion Components (CFC) using WebSockets.
http://www.adobe.com/support/security/bulletins/apsb13-19.html
Invoking public method after Update 11 is applied will return "code":4001 & "msg":"The method f1 in component mycfc cannot be accessed remotely."
It is certainly not a security risk for Javascript, or any other client for that matter, to be able to invoke any public method on any CFC. That is the expected behaviour for interfaces that you choose to expose as public. To solve this, the ColdFusion Team has to return to their original design of Websocket and redo it.

Force coldfusion 8 to reload component cache?

ColdFusion 8 is caching my cfcs. Development is at a stand-still. I don't have access to the admin panel. What are my options?
1) Get access to CF Administrator.
Really. I wouldn't want to host anywhere where I didn't have control over this.
2) Programmatically clear the cache.
Using the Admin API:
createObject("component","cfide.adminapi.runtime").clearTrustedCache()
Of course, if you don't have access to the CFAdmin, you might not have access to this either, but is worth trying.
According to this blog entry from Ray Camden you'll need to login to the admin via the API before running the above command, which of course suggests it's not going to work without already having access.
<cfset API = createObject("component","cfide.adminapi.runtime") />
<cfset API.login(adminPassword="password") />
<cfset API.clearTrustedCache() />
I use application.cfc to clear all of the cfc cache.
<!--- *****************************************************************
Run before the request is processed
************************************************************--->
<cffunction name="onRequestStart" returnType="boolean" output="false">
<cfargument name="thePage" type="string" required="true">
<cfscript>
if (structKeyExists(url,'reinit')) {
structClear(application);
structClear(session);
onApplicationStart();
onSessionStart();
}
</cfscript>
<cfreturn true>
</cffunction>
The idea is to pass a url variable called "reinit". Whenever this variable is defined in the URL, the application is started.
In order to test this:
1. make a change to cfc
2. call a cfm page by xxx.cfm?reinit=1
3. observe the changes in the cfc are reflected.
hope it helps...
I know that this post is old, but I needed to do this for a (more) modern version of ColdFusion (2016) and the answer from Peter wouldn't work on CF 2016. Not looking to be the answer, just a footnote for newer versions of CF.
Here is a version that will work with CF 2016:
<cfscript>
variables['adminPW'] = "my cf admin password";
cfAdminAPIAdmin = createObject("component", "cfide.adminapi.administrator");
cfAdminAPIAdmin.login(variables.adminPW);
cfAdminAPIRuntime = createObject("component", "cfide.adminapi.runtime");
// clear the component and trusted (template) caches
cfAdminAPIRuntime.clearComponentCache();
cfAdminAPIRuntime.clearTrustedCache();
</cfscript>
Adobe appears to have separated the CF admin functionality from the runtime component. That's really the only difference. The version above shows how to clear the component cache too.
NOTE: I had been doing something very similar to CFNinja's answer, but one site (out of about 25 similar sites) just wouldn't clear the application scope components, the old version remained in a cache somehow.

Can the Coldfusion onRequestEnd handler read or write the client bound response stream?

Given a Coldfusion page generates some content (html, xml, json, whatever) to satisfy a client request, can the onRequestEnd handler read (or write) the content in the response stream? If so, how?
If it matters assume Coldfusion 8 on IIS 6.
Thanks for looking
Adrian
GetPageContext().getCFOutput() seems to do what I need e.g.
<cfset oldContent = GetPageContext().getCFOutput().getString()>
<cfset GetPageContext().getCFOutput().clearBuffer()>
<cfset newContent = ModifyContent(oldContent)>
<cfset GetPageContext().getCFOutput().print(newContent)>
Yes,
According to the docs: ColdFusion 8 onRequestEnd
This method has the same purpose as the onRequestEnd.cfm page. (You
cannot use an onRequestEnd.cfm page if you have an Application.cfc
file for your application.) This method runs before the request
terminates; therefore, it can access the page context, and can
generate output.
This method can access the requested page’s Variables scope only if
the Application.cfc file includes an onRequest method that calls the
page. You can use Request scope variables to share data with the
requested page, even if the Application.cfc file does not have an
onRequest method.

How do I secure CFID for PCI compliance?

We've been failing our PCI scans because ColdFusion has predictable CFIDs. The exact FAIL we get is "Predictable Cookie Session IDs". Now the CFTOKEN is no longer predictable since I've configured CF to use UUID for CFTOKEN, however, the CFID is still predictable and unaffected by any changes in CF Admin.
I don't really know why the CFID being predictable is a threat, but they want us to fix it.
I have been unable to find anything on the matter by googeling, and I'm really not sure what else to do.
Has anyone else dealt with something like this? Any suggestions?
EDIT:Here is what my Application.cfc file looks like:
<cfcomponent output="false">
<cfset this.name="DatabaseOnline">
<cfset this.sessionManagement=true>
<cfset this.setDomainCookies=true>
<cfset this.setClientCookies=true>
<cfset this.sessionTimeOut=#CreateTimeSpan(0,20,0,0)#>
</cfcomponent>
And my CF admin looks like this: http://i.imgur.com/k9OZH.png
So how do I disable CFID?
Using J2EE session variables should address that problem.
To do that go to CF Administrator. Server Settings --> Memory Variables and check the 'Use J2EE session variables' check box.
You can find some more information here http://helpx.adobe.com/coldfusion/kb/predictable-cookie-session-ids-reported.html
Explain to the scanning agent that the CFID is sequential, but is not valid without a corresponding CFTOKEN cookie which is randomized. Since the session cannot be hijacked with the ID alone, it mitigates the reason for the scan failure. Their automated test assumes that the CFID cookie controls the session on its own, which is not the case. Every scanning vendor that I've worked with has accepted this as a mitigating factor and either disabled or overridden that specific test for me on CF-based sites.
Alternately, if none of the sites on the CF server use session variables, you can disable session management entirely and CF won't issue the cookies at all. If they are needed, the above explanation of how CF sessions are managed should get you through.

Coldfusion uses wrong (cached?) variables at random

We have a dedicated server running CentOS and Coldfusion 8.
All cfmail email is routed through Google with cfmail and smtp.
Every now and then, when cfmail is used, the 'FROM' field uses an address from a totally different website.
For instance:
Use form on Site A
Get an email: "Subject: On Site A From: siteb#siteb.com"
Where the from is a completely different variable in another set of code on another part of the server- there is no reason it should see this.
On the other side, sometimes sending an email to sitea#sitea.com has email wind up in Site B inbox, a completely different Google account.
What causes this to happen? Some kind of memory/cache issue? Or is there a funky DNS record causing issue?
Example:
Application.cfm (starts with some UDF includes, and then):
<cfinvoke component="#request.componentPath#.variables" method="getGlobal" />
Variables.cfc (a lot of variables defined within, but here is the cfmail vars):
<cffunction name="getGlobal" access="public" output="false" returntype="void">
<cfscript>
request.siteEmail = "email#mysite.com";
request.siteMailServer = "smtp.gmail.com";
request.siteMailUsername = "root#mysite.com";
request.siteMailPassword = "[redacted]";
</cfscript>
</cffunction>
It sounds like it's possible it could be a var scoping issue, but we can't know for sure until you share some code...
Looks like you're running multiple sites? there's a setting in the CF caching page in admin to do with caching web server paths:
From http://help.adobe.com/en_US/ColdFusion/9.0/Admin/WSc3ff6d0ea77859461172e0811cbf3638e6-7ffc.html :
Disabling the cacheRealPath attribute To ensure that ColdFusion always returns pages from the correct server, disable Cache Web Server Paths in the Caching page of the ColdFusion Administrator. (When you use the multiserver configuration, set the cacheRealPath attribute to false for the ProxyService in the jrun_root/servers/servername/SERVER-INF/jrun.xml file.)
Might not be it, but it's at least quick to try out.