Security Alert: Overloading CFINCLUDE in CF 4.0 & 4.5
by Michael Dinowitz
CFINCLUDE is a rather useful tag for taking ColdFusion templates (and other pages) and including them into other templates. There's just one small problem; CFINCLUDE can be overloaded and can be used by a visitor to call files from
the system other than those expected. While this is not a security hole in
ColdFusion itself, it is a security hole in the way people write their code.
A Standard CFINCLUDE will look like this:
|
<CFINCLUDE TEMPLATE="location.cfm">
|
This will take a file called location.cfm and include it into the 'calling' template (The template that contains the CFINCLUDE). The included file will exist in the same directory as the 'calling' template.
CFINCLUDE can also use relative paths to retrieve a file:
|
<CFINCLUDE TEMPLATE="queries/location.cfm">
|
This does the same thing as above, but the included file is in a subdirectory called queries. This subdirectory is in direct relation to the calling template. Now let's take this a step further. If we want to include a file from a directory above the calling template, we can use the '../' syntax, which says to go up one level to the calling template's parent directory and get a file:
|
<CFINCLUDE TEMPLATE="../location.cfm">
|
This says go up a directory and include a file called location.cfm. So far we're not doing anything special here. Everything you see here conforms to the standard for relative paths in HTML. Now let's look where it changes.
Relative Paths
In standard HTML, the relative paths assume the webserver root as the 'highest' level you can go using the '../' syntax, basically the ultimate parent directory. For example, this will not work (assuming the webserver root is HTDocs and the calling template is in the webserver root):
|
<IMG SRC="../JRun/bank.gif">
|
HTML just can't go outside of the web path as defined by the webserver. ColdFusion isn't bound by this. CFINCLUDE either has an error or a feature that says that the 'root level' is not the webserver root, but the drive root (normally c:\). This means that I can access ANY FILE on the same drive using CFINCLUDE.
Making it work
Let's assume a template is in the root of the webserver and the webserver root is actually in
E:\HTDOCS. Additionally, let's assume we have a normal CFusion directory at
E:\CFusion (See graphic above). If I wanted to call a ColdFusion template sitting in the customtags directory (which is not in the webserver root) from a template that's at the top of the webserver root, I can use the following syntax:
|
<CFINCLUDE TEMPLATE="../cfusion/customtags/file.cfm">
|
Now this looks like a useful piece of information. You can include any file you want now. Well, with a little work, this can be used to gain access to files that shouldn't be accessed.
|
<cfinclude template="../../../../../../../htdocs/cfide/administrator/security/index.cfm">
|
Here's the problem. If I use a bunch of '../', it will tell the CFINCLUDE to go all the way up to the drive root (
E:\). From there, I can call any directory I want. If I know the webserver root (easy to find out) then I can call it all the way down to the CFIDE/Administrator directory. Now you're thinking that this is something that has to be hard-coded onto a webpage and you're safe. Wrong! Most people use the following piece of code in their applications somewhere:
|
<cfinclude template="#passedvar#.cfm">
|
This normally assumes that the passedvar will be passed on the url and the result will be a normal call. If I sent my own string on the url, I could still get admin access:
|
http://127.0.0.1/testtemplate.cfm?passedvar=../../../../../../../webroot/cfide/administrator/security/index
|
But there's more. The multiple '../' will also 'escape' any path information you happen to have on the include. This means that the 'allaire/' path information will not help you and will effectively ignored:
|
<cfinclude template="allaire/#passedvar#.cfm">
|
There's more here. I've got a way to use this to turn off your CF security or do a lot of other things, but I'm not going to tell you how. Instead I'm going to tell you how to fix this.
A Few Fixes
While discussing this with fellow Team Allaire members, a few suggestions have come up (as well as a few more evil uses for this). The first thing to do is to rename your Administrator directory. This hole is based on knowledge of a persons system. If you have a non-standard setup for Admin and docs, you've got some safety. Another suggestion is to use following code:
|
<cfinclude template="#Replace(passedvar, '.', ',', 'all')#.cfm">
|
This will replace all periods (.) with a comma (,) which will kill the problem. Unfortunately, these are really the only fixes that exists at the moment (other than advanced security). As new ideas come up, I'll post them.