A couple of days ago I wrote a blog entry on ColdFusion 8's Ajax security features:
ColdFusion 8 Ajax Security Features
I did some more playing around with verifyClient and wanted to share a few interesting tidbits.
First - verifyClient runs where you put it in your file. Ok, that sounds obvious, but you want to remember to put it on top of your file. If you have...
<cfset doSomethingSecure()>
<cfset verifyClient()>
Then your doSomethingSecure() will run before the security check is made. Again - this is probably obvious, but you want to keep it in mind. As an interesting example, you can try/catch the check and log non-Ajax requests:
<cfoutput>hi, #cgi.query_string#</cfoutput>
<cftry>
<cfset verifyClient()>
<cfcatch>
<cflog file="ajaxsec" text="Requested ajax page in non ajax fashion">
<cfrethrow>
</cfcatch>
</cftry>
<p>
got past the VC
</p>
Notice the use of cfrethrow. This ensures the error gets fired again after I've done my log.
Now for the second item to note. I wanted to investigate a bit how secure the test is. The first thing I did was build a page using the code above as test.cfm. I then built test2.cfm as:
<cfdiv bind="url:test.cfm" />
I ran the code in Firefox and noted that it ran as expected. I then used Firebug to check out the HTTP request. It looked like so (I'm adding a space between the url params to help it wrap better):
http://localhost/test.cfm?_cf_containerId=cf_div1186500510058 &_cf_nodebug=true&_cf_nocache=true &_cf_clientid=143760EA10A0D8188ACF5DB88765663E &_cf_rc=0
So on a whim, I copied the URL and pasted it into a new tab. And it worked! That was surprising. I pasted the same URL into Safari and got the error I got before. I then pointed Safari at test2.cfm. I noticed that test.cfm was loaded with the same URL, but a different _cf_clientid. (There is no Firebug for Safari, so I just modified test.cfm to output the cgi.query_string.) I pasted this URL into Safari and it worked fine as well.
So the take away from this is - verifyClient will only be secure if a user does a "proper" Ajax request first. After that they can request the URL directly as long as their session is active. Considering the nature of HTTP in general I think this is fine, but wanted to be sure people were aware.
Archived Comments
Raymond,
I am planning to use more ajax/web 2.0 stuff in my developments and I was reading on the security measurs I can take on them.
IE: I am using cfgrid with binding to a query. Query will return sensative data (user ID's). The cfc that binds returns a structure back and it is remote for doing paging.
I also needed to remove my application.cfc (which included security) from that folder because the ajax binding request does not want anything running in between the cfc and the call.
I was reading on the VerifyClient. My session and client variables are enabled. <cfset verifyClient()> in my cfc does not fail. Also there is not a pwd change going on here I am just concerned that it can be hacked or accessed as a webservice since the method is remote.
Can you please advise... we have sensative researh data and I would not want a user act like someone else and see other patients data inexample.... Does that mean I should not use ajax functions just yet?
It is important to remember that verifyClient does one thing only. It tries to ensure you are coming in via an Ajax request. It secures the type of connection, but not the content at all.
You should be much more concerned with the content - ie, is this guy authenticated to retrieve the content he wants, as opposed to, where the guy is coming from.
I'm not saying you SHOULDN'T be concerned about that - just that it is secondary to the primary concern.
So with that being said, remember that there is no TRUE way to detect an AJAX request. An AJAX request is nothing more than a HTTP request by the browser. verifyClient works via a hack essentially. It isn't bad, and it blocks most folks, but I got around it in about 15 minutes.
You _do_ have to make a 'real' proper request first, but someone could write a robot to do this rather quickly. Ie, do the post to a non-ajax page, get the cookies needed to mark the session, then post again to the ajax page.
So again - focus more on the authentication/authorization as compared to the type of connection security.
Does this make sense?
Yes, it makes sense but I can not make the security module run between the grid and the cfc binding since ajax binding request does not want anything running in between the cfc and the call.
The application that the grid is included is secure. Through the application.cfc... So no unauthenticated and authorized user can get to the app. But I was afraid if they could call the cfc from somewhere else. I thought verifyClient() might prevent that.
Err, well, not sure I'm reading you quite right. verifyClient does try to prevent you from running the CFC from "somewhere else". It isn't perfect, but it does try to do that.