Friday 14 March 2014

ColdFusion 11: More on this <cfinclude> thing

I've been thinking about this new <cfinclude> security feature some more, based in no small part on the excellent reader comments on my earlier article "Is Adobe knowingly leaving exploits in ColdFusion 9 and 10 unpatched?".

Firstly I'll repeat my response to one of Sean's comments, to contextualise a baseline:

If there's a case to address, and this is a sensible way of dealing with it: no problem. However we didn't know (beyond speculation) whether either of those is true. Rupesh has now clarified there is a case to address, but I remain skeptical as to whether this is at all a sensible approach.

It comes down to communication, and Adobe's seeming inability to do it coherently. On the face of it this was just a stupid thing to do, especially when the rationale was no more developed than "because security". Part of dealing with security responsibly is to communicate the situation. Not to detail the instructions of how to implement the exploit, but at least documenting what the issue is actually addressing. Even had Adobe implemented a more even-handed solution from the outset, without explaining the situation, the community cannot make an informed decision as to whether it's a ill-conceived annoyance that might as well be disabled, or the most critical and real threat ever. I still think this one falls closer to the former than the latter.

Furthermore, without discussion and input from the community, I will never be certain (nor should any of us be) that Adobe are actually addressing the issue sensibly, or just giving it a quick hack by way of lip-service. Let's face it: they do have a habit of doing the bare-minimum amount of work necessary to be able to look themselves in the mirror (although they set a low tide mark even for that).

And also - finally - a helpful comment from Adobe's technical mouthpiece, Rupesh:

Rupesh Kumar
6:51:43AM GMT+00:00 Mar 13, 2014
As I said earlier, this basically provides a way to you to decide what you want to compile and what not, when the file is being included. This was added after we saw few cases where an application included a file and somehow the bad guys were able to write to this file being included. The file in one of the case was actually a log file where the application was logging invalid user input apart from other errors/log messages. As you would figure, the bad input was actually some CFM code which went into the log file and when this got included, the user given code got executed. The application had not expected this file to be compiled. As we understand, there are many applications which use cfinclude to include static content.

This is a good change. You are getting a control to decide what to compile. You will also get some performance improvement because your JS, HTM, CSS files would not be compiled, loaded and processed by the server. If you don't need any of this and want to compile everything, you can always use "wildcard". 

To answer whether this should be given as an update to CF 9 & 10, we would not want to break applications while applying updates in their production servers. We can add this where by default we would allow all the extensions to be compiled which then does not fix anything immediately. So how do we go about it? Do you think it needs to be made available in CF 9 & CF 10?
There are some comments following that up, and you should read them.

But, anyway, it's as Aaron predicted. Well done Aaron (that might sound patronising, I mean it sincerely).

OK, so some modification of how code can be invoked might be in order here. But I really don't think what Adobe have done here is addressing the potential issue correctly. I think it's a knee-jerk, half-thought-through focus on a tangent than actually sensibly addressing the issue. So whilst we're in the business of half-thought-through solutions, here are my thoughts.

My problem with the approach Adobe are taking here is that it's addressing a problem after the fact. It's waiting until harmful code is already on the system, and then preventing it from running. What they should be doing is addressing how the code gets there in the first place, and also the ability for code to have impact outside its intended remit.

If this was one minor facet of a broader solution, and a couple of tweaks and augmentation were made to its implementation - and if Adobe explained themselves like professionals - I'd have no problem with it.

Let's look at the issue.

So the issue here is that it's been possible for baddies to gain access to a ColdFusion system, and then write code to the file system, and execute that code to exploit the server. This is very bad. And it is a real threat which has been exploited in the wild: "APSB13-13 / Security update: Hotfix available for ColdFusion".

So the issue here is this:
  1. baddies access the system via ColdFusion Administrator by circumventing login security
  2. baddies can write to files
  3. baddies can execute the files
Adobe have taken steps against the first one, by removing a security hole or two, and generally hardening access to the server. And to promote the idea of people following the Lockdown Guides (CF9, CF10).

Adobe have also taken some steps against the second one. I was surprised to find that there are vey few places in CF Administrator that allows one to write to the file system. But one place is via a scheduled task. A scheduled task can be configured to hit any URL (not just on the ColdFusion server), and the response from that URL can be written to file. This was a recipe for disaster, and it proved to be one. Adobe have changed this so that only .txt and .log files can be written. They can still be written to anywhere on the file system though, as far as I can tell. As .txt and .log files are not (unless specifically configured to do so) executable when browsed to, the risk here was perceived to be minimal. However one can still include a .txt or .log file, and the ColdFusion server will compile and execute it as if it is CFML code. Some people leverage this functionality: not as an exploit, but as a normal part of site operations, they might include a .js file to process some embedded CFML, or one organisation I know uses it to do "mail merges" on .docx templates. There are legit use cases for doing this (the latter is more legit than the former, IMO).

But still: they are allowing potential baddies to write to the file system whilst they are in CF Administrator.

And Adobe also allow baddies to place files where they can be executed. Either by being browsed to, or in theory, being included. The browsing risk is minimal unless the web server has been actively configured to pass .txt and/or .log files to CF, but I think that risk is minimal, and if the web admin has done this, they have probably done it for a reason.

This leaves the small risk that baddy-generated code could be executed via an existing CFM file, via <cfinclude> (or <cfmodule>, etc). However this would require one of two things to be true:
  1. The baddy has the ability to write their own CFM file to the file system, to include the nefarious code. If they can do that... they don't need the .log or .txt file, they can just use their own .cfm file;
  2. An existing application has <cfinclude> code in place which can be manipulated via the URL (or form, or some manner of external-user input) to directory-traverse to where the nefarious code is an inadvertently include it. Basically something like this:

    <cfinclude template="#URL.fileToInclude#">

    The weakness here is that someone might pass ../../../path/to/naughty/code.log, and ColdFusion will execute it. Obviously if one is doing something as ludicrous as that - without very strict validation - one one ought to be shot. But also validate the value of URL.fileToInclude so that it can only reference the intended range of files. But Adobe cannot control the crappy code developers will write.
All the focus here has been given to the last step of the exploit. Adobe's not worrying about where the baddy writes the file (or that they even can write the file!), nor are they focusing on whether the file can be accessed from another application. They're just addressing the last link of the chain. After most of the exploit has been allowed to succeed.

Now as I said in my reponse to Sean, I am completely fine with hamstringing <cfinclude> if there's been equal attention given to the other steps of the exploit.

Where scheduled tasks can write files

They could prevent scheduled tasks from writing anywhere except for one dedicated directory. Or at least have a configuration option to enforce this. This reduces the surface area of potential threats.

What scheduled tasks can write

Prevent them from saving CFML to the file system. Configurable. Or it could take a JSONP sort of approach and prepend any file with CFML in it with a <cfabort> to prevent it from running.

From where code can be included

Have an application setting that code can only be referenced via canonical paths that exist within the website, web application, and any mappings (or custom tag directories). Thus preventing traversal into areas that the application is not expecting.

How code is executed

Some talk regarding this modification to <cfinclude> behaviour is to unilaterally hamstring how it works when including not CFM files, in that it will basically work like a combination of <cffile> and <cfoutput>, rather than actually processing the file. This is just fucking stupid. If someone is <cfinclude>-ing a file, it's because they want it to be <cfinclude>-ed. Not because they want to <cffile> and <cfoutput> it. Because that's what they'd be doing if they wanted to do that. And it's quite rubbish to do this at file-extension-level, rather than slightly more thoughtfully.

A parameter could be added to <cfinclude> to alter the compilation / exeuction behaviour, eg:

<cfinclude template="foo.notCfm"><!--- process as per usual --->
<cfinclude template="foo.notCfm" compile="true"><!--- definitely compile it --->
<cfinclude template="foo.notCfm" compile="false"><!--- definitely don't compile it ---> 

And then have a setting in the secure profile which sets the default behaviour for non-CFML files. Or a range of specified file extensions (both whitelist and blacklist, and including wildcards).

The benefit here is that a developer on the Adobe ColdFusion Team is not unilaterally second-guessing how we write our code. Because let's not forget there: the issue is not how we write our code, it's how Adobe facilitates baddies writing their code.

Adobe are addressing this issue via lip-service, rather than via actually assessing how best to deal with the issue at hand. This is my problem with their approach here.