In the first part we have set the stage for this series: the goal is to protect one shared hosting customer from an ‘inside attack’ by another shared hosting customer on the same ColdFusion instance. In the second part we have gone into the reason why we need ColdFusion Enterprise Edition to secure the filesystem from direct access through cffile and cfdirectory. In this part we will see why we need to take additional steps to secure the filesystem against the other languages we can use in / call from ColdFusion.
Since ColdFusion is written in Java the integration with Java is pretty tight and we can easily use Java code from ColdFusion. So what happens if we try not to use a CFML tag to access a file from some other customer, but use Java directly. You don’t need any Java knowledge to do so, if you Google for some code you will find plenty of examples. For this I downloaded the code from Ben Nadel’s Java Exploration in ColdFusion: java.io.LineNumberReader blogpost, changed the ExpandPath(”./data.txt”) to my template name and ran the code. It displayed the sourcecode of the template, so the code was good. Next I changed the code so the file it pointed to was “c:\\test\\secret.txt”, which is outside my Sandbox. And the code promptly returned an error.
So far so good: our Sandbox protects against reading files directly through Java.
So if we can’t read files from elsewhere on the filesystem directly, perhaps we can copy them to our Sandbox first using the native functionality of the operating system, and then read them once they are in our Sandbox. (And if you don’t know which files you need, just use xcopy and copy them all recursively.) For that we turn to the cfexecute tag. In the default form that tag would be used like this:
<cfexecute name="c:\windows\system32\cmd.exe" arguments="/c copy #source# #target#" />
But because we are in a Sandbox that will most likely not work because your Sandbox will not allow you to access the c:\windows\system32\cmd.exe file. To circumvent that, simply upload a copy of cmd.exe to your Sandbox and use that one. With that the code to copy files and then read them through cffile becomes:
So by now it should be clear that CFEXECUTE needs to be disabled to maintain security in a shared hosting environment. The bottom line is that with CFEXECUTE you start a process, that process runs as the same user as ColdFusion, the ColdFusion user by definition has access to the templates of other customers, so the process you started has access to them as well. And this means that useful functionality (albeit used by a limited number of users) needs to bes disabled.
COM, .NET and Java again
The problem is that CFEXECUTE is not the only way to start a new process. COM, .NET and Java can do so as well. Below is a simple code example that shows how to dynamically generate a batchfile, write that to the filesystem inside the Sandbox, execute it through Java, and read the result.
<!--- target file outside our Sandbox ---> <cfset secretFile = server.coldfusion.rootdir & "\lib\neo-datasource.xml" /> <!--- batch file inside our Sandbox ---> <cfset batchFile = ExpandPath("./copy.bat") /> <!--- location where we copy the file inside our Sandbox ---> <cfset readableCopyOfSecretFile = ExpandPath("./readableCopyOfSecretFile.xml") /> <!--- copy command for in our batchfile ---> <cfset batchFileContent = 'cmd /c "copy #secretfile# #readableCopyOfSecretFile#"' /> <!--- write the batchfile inside our Sandbox ---> <cffile action="write" file="#batchFile#" output="#batchFileContent#" /> <!--- execute the batchfile ---> <cfset CreateObject("java", "java.lang.Runtime").getRuntime().exec(batchFile) /> <!--- read the copy of file inside the sandbox ---> <cffile action="read" file="#readableCopyOfSecretFile#" variable="fileContent" /> <!--- display the contects of the file ---> <cfoutput>#HTMLCodeFormat(fileContent)#</cfoutput>
We can prevent this by modifying the Sandbox configuration and disabling the execute permission from the Sandbox, but since ColdFusion itself needs execute permissions to run CFML that will kill ColdFusion as well. Executing processes from COM works the same as from Java. From .NET it works slightly different because the actual .NET service runs in another process and could potentially have different permissions from the ColdFusion account, but the inability to differentiate the permissions between different users remains.
So the hoster is left with a hard choice: disable CFEXECUTE, CFOBJECT, CreateObject(.NET), CreateObject(COM) and CreateObject(JAVA) or accept that there is no security whatsoever in the shared hosting configuration. If you disable these tags a lot of applications and frameworks won’t work anymore. For instance Transfer ORM needs Java access, so any application build on top of it will not work in a secured shared hosting environment.
A long time ago I had some other code examples online that could be used to extend the functionality of a shared hosting environment. I have taken these examples down not just because with the arrival of the Admin API they are obsolete, but also because I was informed that somebody had wrecked a shared hosting server with them. So please before you start uploading and running these examples on your shared host, please take a moment to consider the following points:
- If you want to look further into this code, why not do that on your own development environment?
- In most jurisdictions accessing other peoples data / code is illegal.
- Some of the code examples (especially if you replace copy with xcopy) can consume lots of resources.
- You will never be able to test whether your hosting account is protected from others. You will only be able to test if others are protected from you. So really, why not on your own development environment?