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

4

14

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

Chartres answered 27/6, 2013 at 19:2 Comment(26)
Good spot! I would have assumed that access=remote would have been required for a remote invocationOrientate
Silly question ... are you saying it still works when you explicitly set the methods to private? (I cannot test it right now)Thorrlow
@Thorrlow Just tested, private cannot be invoked. Question updated.Chartres
Bug submitted to Adobe: "Thank you for submitting a bug. Due to security concerns, this bug will not be externally viewable."Chartres
Do you have an onCfcRequest() method in your Application.cfc?Stickle
@AdamCameron no I didn't. Just added and it does not guard requests from websocket invoke()Chartres
I wasn't expecting it to help, I was expecting it to be the cause of what you were seeing! Reading: cfmlblog.adamcameron.me/2013/04/…Stickle
@AdamCameron thx Adam, hope the mothership will get back to us soon. Websocket can't be enabled on a production server with this hole.Chartres
This seems - stress seems - like something that would be very hard to exploit. A) The CFC would need to be under web root. B) You would need to know the name of the method. To be clear, I'm not saying this shouldn't be fixed, but I'm not sure I'd go around disabling websockets.Gallinacean
The default for both Coldbox and FW/1 is for CFCs to be in the webroot - they can (and should) both be configured otherwise, but when (at least) two major frameworks do something by default, that means it affects a lot of people.Flavine
For those of us who would like to work around the bug (and keep websockets enabled) in the meantime, can you confirm that moving cfcs out of the web root mitigates the risk?Blok
Moving the cfc is ok if your app can't execute that URL afterwards. Rewrite rules, front controller and other things could be directly mapping CFC URLs to the "secure" web root, making no improvement to security in some apps. You need to verify the CFC isn't reachable in any way or secure all CFCs globally in application.cfc like I suggest in my answer. I add a layer of manually controlled security on top of the built-in security because you can handle exceptions differently and you don't have to worry about language bugs like this. Robots shouldn't be able to cause CFML exceptions either.Hendrix
@PeterBoughton, I've tried to convince ColdBox to NOT recommend installing that way, but the'd rather go for "doing it the easy way, despite it being a bad practice" over "encouraging their clients to do it the right way, even if it's slightly harder". This is very disappointing.Stickle
@AdamTuttle I'm gonna do proper investigation on this tomorrow. Will report back (via my blog). I'll give you a heads-up.Stickle
@RaymondCamden I've replied to your comment in the question above. Under webroot or not, it doesn't matter.Chartres
So, if not simply disabling websockets completely, it needs something like web server filtering to block non-whitelisted CFC requests?Flavine
Adam, I'd say even "slightly harder" is over-inflating the [lack of] difficulty; it's only a line or two of config? :/ Even if they didn't change the default but had one of the sample apps show how to do it, would be better than nothing.Flavine
I think cf 10 needs onWsCfcRequest() and default to allow remote method only is reasonable.Chartres
Geeze man a reply as a comment would have been fine enough. You felt the need to update the question to call me out??Gallinacean
I have to ask why this question has a bounty. If you are asking if it is a security risk, I think you already know. (Although the question is how much of one.)Gallinacean
@raymondcamden ok, question updated. Bounty was set so someone can come up with a legit workaround for this hole without switching off WS in CF 10, and also raise awareness for those who are running cf10 in production with WS switched on (default)Chartres
Henry, btw I've done some more investigations into this. too much for this question though: cfmlblog.adamcameron.me/2013/06/…Stickle
@Chartres - Have you heard anything back from Adobe on the bug that you entered for this? I guess we can't vote for it if it is hidden.Braze
@Braze no, I have not heard anything from Adobe.Chartres
"We are working on it and the fix will be available in next updater for CF10." @kawdhesh cfmlblog.adamcameron.me/2013/06/…Chartres
"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." - blogs.coldfusion.com/post.cfm/…Chartres
C
2

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."

Chartres answered 9/7, 2013 at 17:26 Comment(4)
Kudos to you Henry for bringing this to their attention and following up on it!Braze
@Braze I'm testing their patch. CFC is somehow cached in a way that even if I change the access level of a method to something else, WS still respond what the old CFC responded. I'm not sure if this is a bug.Chartres
@Braze I don't think it's refreshWSDL since this is not SOAP webservice cache. I just verified that the metadata of the CFC will be cached for one minute since last used by websocket invoke. So if access level is updated in the CFC, don't do anything and wait for a minute, then test and verify.Chartres
Oops, my apologies. Yes my comment was related to webservices not websockets. I will delete it to avoid confusion.Braze
S
7

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"

Stickle answered 30/6, 2013 at 11:39 Comment(3)
Yeah, I do not see a pure CF option either. I tried a number of options, but CF thwarted me at every turn. It clears the web socket headers, prevents the Application.cfc from being invoked, and even marks the request as not being remote. The only way I could tell it was a websocket request from the clientID. Funny thing is, there is an internal onWebSocketXXX method, but related to authentication. It really makes you wonder why they decided not to expose a similar method like Application.onWebSocketStart(..), then it would be a simple to fix.Thorrlow
@Thorrlow re "It really makes you wonder why they decided not to expose a similar method like Application.onWebSocketStart(..)". Lack of thinking it through, I think.Stickle
Note: This has now been fixed in CF10 Update 11: helpx.adobe.com/coldfusion/kb/coldfusion-10-update-11.html || More: adobe.com/support/security/bulletins/apsb13-19.htmlMuro
H
2

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.

Hendrix answered 29/6, 2013 at 17:24 Comment(4)
It seems to me like onRequestStart() is not actually called for web sockets requests. Did you test this?Stickle
@AdamCameron oh, if that's the case I would not have voted this up.Chartres
Well you can unvote. Hopefully Bruce will revise or remove the answer if he can't get it to work.Stickle
The answer is good. I will keep my up vote as is. Thx Bruce for your investigation effortChartres
C
2

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."

Chartres answered 9/7, 2013 at 17:26 Comment(4)
Kudos to you Henry for bringing this to their attention and following up on it!Braze
@Braze I'm testing their patch. CFC is somehow cached in a way that even if I change the access level of a method to something else, WS still respond what the old CFC responded. I'm not sure if this is a bug.Chartres
@Braze I don't think it's refreshWSDL since this is not SOAP webservice cache. I just verified that the metadata of the CFC will be cached for one minute since last used by websocket invoke. So if access level is updated in the CFC, don't do anything and wait for a minute, then test and verify.Chartres
Oops, my apologies. Yes my comment was related to webservices not websockets. I will delete it to avoid confusion.Braze
K
-3

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.

Kowloon answered 7/7, 2013 at 10:35 Comment(1)
"public" is not the same as "remote". You seem to be getting confused about this. PUBLIC methods should not be web-accessible. Only REMOTE ones should be. Reading: help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/…Stickle

© 2022 - 2024 — McMap. All rights reserved.