18 April 2012

User level
Required products
Sample files
Adobe ColdFusion Enterprise Edition (2016 release) (Download trial) (ZIP, 4K)
(3 KB)
Note: Though this article talks about features in ColdFusion 8, it is applicable to the subsequent versions of ColdFusion, including ColdFusion 10.
Adobe ColdFusion 8 is certainly the most impressive release yet. While many new features were added to ColdFusion, one area that really got lots of lovin' was the Ajax department. On one hand you have some very handy Ajax-based UI tools, like windows and tabs. On the other hand you have amazingly powerful tags like <cfajaxproxy>, which make interaction between JavaScript and ColdFusion components (CFCs) incredibly easy.
One area you may not have heard much about are the helpful Ajax security features added in ColdFusion 8. Let's take a look at how ColdFusion can help secure your Ajax-based applications and what you can do as well.

Using the verifyClient function

The first feature look at is the verifyClient() function (see the documentation on this function). This is a pretty interesting function. It works in two places. For instance, you can use it as a simple function on a page, as follows:
<cfset verifyClient()>
Or you can use it as an attribute to the cffunction tag:
<cffunction name="discoverLastCylon" access="remote" verifyClient="true">
The function acts as a barrier to normal requests. As an example, create a new file named test1.cfm and paste in the following code:
<cfset verifyClient()> <cfoutput>The time is #now()#</cfoutput>
Running this code causes the error shown in Figure 1 to occur. What the function is doing is basically preventing any access outside of an Ajax-based access.
Error caused by using the verifyClient() function
Figure 1. Error caused by using the verifyClient() function
Now let's create a new file that demonstrates this behavior. Create a new file called pod1.cfm. This file creates a simple pod and points it back to the test1.cfm file created earlier. Place the following code inside pod1.cfm:
<cfpod source="test1.cfm" />
Next, I'll add a quick Application.cfc file. I'm not doing anything special in the file, so I won't show the code here (it's in the ZIP file), but I did enable session management. Now run pod1.cfm in your browser and you will see that test1.cfm loads just fine. If you go back to browsing test1.cfm directly, you continue to experience the error.
So what kind of voodoo is going on here? When ColdFusion creates the Ajax-based pod (or other controls) and then loads test1.cfm, it passes along particular information, including the use of session data, that bypasses the test1.cfm file.
You should use this function when you may have content that you intend to load only through Ajax. It's relatively simple to use tools like Firebug to see which HTTP requests are being made by your Ajax code and the attempts to open those URLs directly. The verifyClient() function can prevent that.
It's important to note that this protection isn't foolproof. It uses session-based variables and URL keys. If you use Firebug to monitor your ColdFusion requests, you can copy these URLs and load up the content yourself, but only after the first request has already been made. So while you shouldn't assume it completely block folks from requesting your content outside of an Ajax-based context, it will certainly go a long way to blocking most folks.
Let's look at one more example that uses a CFC method. The file, time.cfc, is a simple CFC that returns the current time:
<cfcomponent output="false"> <cffunction name="currenttime" access="remote" verifyClient="true" output="false"> <cfreturn now()> </cffunction> </cfcomponent>
This component has a simple method, currenttime, that returns the current time. The access attribute is set to remote to enable Ajax-based applications to retrieve the data, but note that verifyClient is set to true. If you run this method directly in your browser (using the name of the component and passing method=currenttime in the query string), you will get a similar error to the one you got above.
Now let's build a file to test this CFC via Ajax methods. The file, test2.cfm, uses the CFDIV tag bound to the CFC to display the results:
<cfdiv bind="cfc:time.currenttime()" />
When you run test2.cfm, you will see the time loaded inside the div. Again, ColdFusion performed all the security behind the scenes. The only real action on your part was adding the verifyClient attribute. One thing to keep in mind is that this change will prevent folks from using your CFC as a web service.

Using the JSON prefix

When ColdFusion uses Ajax-techniques to communicate between the client and server, this communication uses the JSON format to pass data back and forth over HTTP requests. What exactly is JSON anyway? JSON stands for JavaScript Object Notation. You can think of it like XML, which lets you take complex data and describe it in a simpler, string-based format.
JSON does the same, except it does so in quite a slimmer fashion. It also has a major benefit over XML in that JSON in the client acts like JavaScript statements. The data can be evaluated directly with no parsing needing to be performed. However, this has the nasty side effect of also being a prime target of attack, because the browser asks the server for data and trusts it to return data it can evaluate as is. As you can imagine, if someone were to muck with the data being returned, disastrous results could occur.
One way to prevent this style of attack is to prefix the JSON returned from the server. For example, if all JSON strings returned from the server began with "ray", the client could look for this string, confirm it is there, and then remove the string. ColdFusion provides multiple ways to add a prefix to JSON strings automatically. Best of all, when you use these features, ColdFusion generates the prefix when returning JSON data, and generates JavaScript code that will look for this prefix automatically.
There are multiple places where you can enable this feature. The first is in the ColdFusion Administrator, which will make it a global setting. Under the Settings page in the Administrator, look for the "Prefixed serialized JSON with" option (see Figure 2). Selecting this option enables the feature, and the text box allows you to specify the prefix.
Enabling and specifying the JSON prefix
Figure 2. Enabling and specifying the JSON prefix
Your second option is to specify settings within the Application.cfc file. You can specify both the secureJSON option as well as the prefix using secureJSONPrefix. Here is a simple example:
<cfset this.secureJSON = "true"> <cfset this.secureJSONPrefix = "//">
The third option is related to the second, but works with the cfapplication tag. While most people should upgrade to using an Application.cfc file, if you are still using the older Application.cfm file, this is an option for you. Simply add the secureJSON and secureJSONPrefix attributes to the tag, as follows:
<cfapplication name="dharma" secureJSON="true" secureJSONPrefix="//">
Lastly, a fourth option is to supply the secureJSON attribute to a CFC function:
<cffunction name="getTime" access="remote" secureJSON="true">
With this option, however, you cannot specify the prefix. The prefix defaults to what is specified in the cfapplication tag value or the This scope. If neither of these is used, the prefix defaults to the value specified in the ColdFusion Administrator.
Once again, what's really nice here is that once you use this option, you can forget about it. All the code that ColdFusion generates on the client side automatically notices the prefix and updates itself for it.

Some final thoughts

There are a few additional items to keep in mind when considering Ajax security. First, during my exploration of ColdFusion 8 and the new Ajax features, I discovered what could be a minor security issue. ColdFusion 8 ships with a specific Ajax debugger. This debugger has to be enabled within the ColdFusion Administrator before it is used. However, unlike other debug settings, the Ajax-based debugger will ignore the attribute cfsetting showdebugoutput="false". To be safe, you should disable debugging on a production machine anyway, but it is something to keep in mind.
Second, "Ajax" does not equal "hidden." Tools like Firebug make it very easy to monitor Ajax requests. Therefore, any actions that you would secure within a non-Ajax context would obviously also need to be protected within an Ajax environment.