11

I want to create a secure ColdFusion environment, for which I am using multiple sandboxes configuration. The following tasks are easily achievable using the friendly administrator interface:

  • Restricting CFtags like: cfexecute, cfregistry and cfhttp.
  • Disabling Access to Internal ColdFusion Java components.
  • Access only to certain server and port ranges by third-party resources.

And the others using configuration of the web server accordingly.

The Problem:

So I was satisfied with the setup only to encounter later that regardless of the restriction applied to the cfexecute tag one can use java.lang.Runtime to execute system files or scripts easily;

String[] cmd = {"cmd.exe", 'net stop "ColdFusion 10 Application Server"'};
Process p = Runtime.getRuntime().exec(cmd);

or using the java.lang.ProcessBuilder:

ProcessBuilder pb = new ProcessBuilder("cmd.exe", 'net stop "ColdFusion 10 Application Server"');
....
Process myProcess = pb.start();

The problem is that I cannot find any solutions which allows me to disable these two classes: java.lang.Runtime & java.lang.ProcessBuilder for the createObject(). For the note: I have tried the file restriction in the sanbox and os permission as well, but unfortunately they seem to work on an I/O file operations only and I cannot mess with security policies of the system libraries as they might be used internally by ColdFusion.

Anurag
  • 1,018
  • 1
  • 14
  • 36
  • 1
    Can you disable the `CreateObject(Java)` function via the GUI or will that be too restrictive? What about the administrator setting under Settings `Disable access to internal ColdFusion Java components`? Did you check that. – Miguel-F Jun 09 '15 at 15:16
  • Oops! Never mind, I see you already mentioned disabling access to the internal ColdFusion Java components in your question. – Miguel-F Jun 09 '15 at 15:30
  • Disabling the `CreateObject(Java)` was my first thought in the after math, but then there is `CfObject` allowing the same functionality. And restricting both altogether would be indeed too much restrictive as they are used throughout the applications. If there is a way to disable only the `type=java` in both the cases, the issue will be solved. I am getting the feeling there might be some `JVM arguments` that might allow this restriction. – Anurag Jun 09 '15 at 16:39
  • The `internal ColdFusion Java Components` does not cover java native libraries and just only the ColdFusion implementation of them, for instance: `Coldfusion.server.SystemInfo`, as per the short description given on the `server settings page` below the option, which says: "_Disables the ability for CFML code to access and create Java objects that are part of the internal ColdFusion implementation._" – Anurag Jun 09 '15 at 16:56
  • 1
    I found a similar article. In it they are talking about security in a shared hosting environment but the issue mentioned is the same as you have found. Unfortunately they do not give a solution either. _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._ - http://jochem.vandieten.net/2008/12/09/cf-shared-hosting-security-java-cfexecute-com-net-and-java-again/ – Miguel-F Jun 09 '15 at 17:29
  • oh snap! This is so relevant scenario, but unfortunately no objective solution. Thanks for the resource @[Miguel-F](/users/1636917/miguel-f). I think I will start a bounty in 2 days. – Anurag Jun 09 '15 at 17:46
  • It does make me wonder how hosting providers are dealing with this issue. It has been around long enough. – Miguel-F Jun 09 '15 at 17:52
  • same here. I can't be more surprised with ColdFusion now. The hosting providers prefer multi-instance ColdFusion installation for better good, this might be one of the reasons why – Anurag Jun 09 '15 at 17:54
  • 1
    From what I have read, you would normally implement some sort of a [SecurityManager](http://docs.oracle.com/javase/8/docs/api/java/lang/SecurityManager.html). (That *might* even be how CF implements the sandbox functionality). However, I have no idea what impact, if any, a security policy would have on the rest of CF code. – Leigh Jun 09 '15 at 21:08
  • Clear idea on how to proceed with it, But what are the `Security Manager` internals and how would it integrate with ColdFusion application. Found [this](http://stackoverflow.com/a/1007583/3098962) answer which suggest using a custom java classloader, which gives only a fair enough idea to run your thoughts around. – Anurag Jun 09 '15 at 21:48
  • @[Leigh](/users/104223/leigh) I am going to go with the `Java Security Manager` approach. First step would be to handle permissions allowed for `java.lang.Runtime` using the `java.lang.RuntimePermission` object OR the second approach as I see a little clear now would be to modify `java.policy` file under `jre/lib/security` and remove permission mentioned there for the Runtime & ProcessBuilder classes. I too have no idea of the impact the security policy changes would have on the ColdFusion server itself and the application code. But I am going for trail and learn approach now. Thanks! – Anurag Jun 09 '15 at 22:14
  • *modify java.policy file under jre/lib* @AnuragMishra - Yep, that is what I was thinking of (I do not see how a custom class loader would work in the context of a CF app). Though again, no idea if it will negatively impact CF. I would be curious to hear what you discover. – Leigh Jun 09 '15 at 23:46
  • 2
    Just to clarify, yes ColdFusion uses the Security Manager when you enable the sandbox security. From the docs: _To use sandbox security in the J2EE editions, the application server must be running a security manager (java.lang.SecurityManager) and you define the following JVM arguments (for Tomcat, this is the java.args line in the cf_root/cfusion/bin/jvm.config file) - `-Djava.security.manager "-Djava.security.policy=cf_root/WEB-INF/cfusion/lib/coldfusion.policy" "-Djava.security.auth.policy=cf_root/WEB-INF/cfusion/lib/neo_jaas.policy"`_ – Miguel-F Jun 10 '15 at 14:41

1 Answers1

6

Following the useful suggestions from @Leigh and @Miguel-F, I tried my hands on implementing the Security Manager and Policy. Here's the outcome:

1. Specifying an Additional Policy File at runtime instead of making changes to the default java.policy file. To enable this, we add the following parameters to JVM arguments using CFAdmin interface or alternatively appending it to the jvm.args line in the jvm.config file :

-Djava.security.manager -Djava.security.policy="c:/policies/myRuntime.policy"

There is a nice GUI utility inside jre\bin\ called policytool.exe which allows you to manage policy entries easily and efficiently.

2. We have enforced the Security manager and provided our custom security policy file which contains:

    grant codeBase "file:///D:/proj/secTestProj/main/-"{
        permission java.io.FilePermission 
        "<<ALL FILES>>", "read, write, delete";
    };

Here we are setting FilePermission for all files to read, write, delete excluding execute from the list as we do not want any type of file to be executed using the java runtime.

Note: The codebase can be set to an empty string if we want the policy to be applied to all the applications irrespective of the source.

I really wished for a deny rule in policy file to make things easier similar to the grant rule we're using, but there isn't unfortunately. If you need to put in place a set of complex security policies, you can use Prograde library, which implements policy file with deny rule (stack ref.). You could surely replace <<ALL FILES>> with individual file and set permissions accordingly or for a better control use a combination of <<ALL FILES>> and individual file permissions.

References: Default Policy Implementation and Policy File Syntax, Permissions in JDK and Controlling Applications

This approach solves our core issue: denying execution of files using java runtime by specifying permissions allowed on a file. In other approach, we can implement Security Manager directly in our application to define policy file from there, instead of defining it in our JVM args.

//set the policy file as the system securuty policy
System.setProperty("java.security.policy", "file:/C:/java.policy");
// create a security manager
SecurityManager sm = new SecurityManager();
//alternatively, get the current securiy manager using System.getSecuriyManager() 
//set the system security manager
System.setSecurityManager(sm);

To be able to set it, we need these permissions inside our policy file:

permission java.lang.RuntimePermission "setSecurityManager";
permission java.lang.RuntimePermission "createSecurityManager";
permission java.lang.RuntimePermission "usePolicy";

Using Security Manager object inside an application has its own advantages as it exposes many useful methods For instance: CheckExec(String cmd) which checks whether a calling thread is allowed to create a sub-process or not.

//perform the check
try{
  sm.checkExec("notepad.exe");
}
catch(SecurityException e){
  //do something...show warning.
}
Community
  • 1
  • 1
Anurag
  • 1,018
  • 1
  • 14
  • 36
  • Great information. Thanks for posting it. I look forward to trying it out :) – Leigh Jun 16 '15 at 18:03
  • I still think there must a better way to achieve what we intend here, using the `Security Manager` and Policy files. I got around to using the `java.io.FilePermission` as there wasn't any target name available in [java.lang.RuntimePermission](http://docs.oracle.com/javase/7/docs/technotes/guides/security/permissions.html#RuntimePermission) to achieve such objective (which I initially expected to be found here). Another elegant solution would be to use custom _`ClassLoaders`_ to filter out the two classes we were initially concerned about: `java.lang.Runtime` & `java.lang.ProcessBuilder`. – Anurag Jun 16 '15 at 21:10
  • The problem I saw with using a custom ClassLoaders was I am not so sure you could work into the normal application flow as simply as with a policy file. That said, I have not done any experimentation with it, so I could be totally off base ... – Leigh Jun 16 '15 at 21:19
  • I agree, even if custom class loaders were a solution, they won't fit so normally as the policy mechanism and for that I too don't have any experience, another reason to keep this question open. A [good read](http://www.securingjava.com/chapter-three/chapter-three-7.html) on java security, I found just recently. And [this](http://stackoverflow.com/a/502388/3098962) answer on sandboxing in java application and [Access Controller](http://docs.oracle.com/javase/7/docs/api/java/security/AccessController.html) made me think there must be an alternate solution, if arguably not better and clean one. – Anurag Jun 16 '15 at 21:42
  • I wish someone could post a solution using custom class loaders. As I learn more and about it, I see the scope for the custom class loaders to be a good alternate solution as well. I still don't posses proper advanced java knowledge to go about that solution, but working on it. – Anurag Jun 22 '15 at 20:20
  • I do not see how you could implement it for a CF application - not cleanly/consistently/securely. The CF server already implements its own AccessControllers, and custom class loaders, as part of createObject. So you would have to hook into them somehow/override them without running afoul of CF's internal logic. Far from a trivial task. Also, given the complexity of the security specs, there is the potential to make things MUCH worse if you do not know what you are doing ;-) I would never apply it on a live system, but it would be interesting to experment with on a DEV box. – Leigh Jun 23 '15 at 20:17
  • *hook into them somehow/override them without running afoul of CF's internal logic* ... in such a way that it was always enforced for all createObject calls. Not sure that is possible without a brittle/ugly hack. – Leigh Jun 23 '15 at 20:21
  • I am going to mark the only answer as accepted, I wish the bounty points could be claimed before grace period. – Anurag Jun 29 '15 at 09:46
  • Though I would be happy to be proven wrong, I really think the custom class loader approach is not a feasible one for a *CF* application. There is just no clean way to enforce it that I can see ... – Leigh Jun 29 '15 at 12:51
  • I agree to that now. I tried my chances with it but only found complications but I attribute it to my lack of knowledge both the environments. Anyways, I am happy as I was able to get my hands on security management in ColdFusion and experiment with it to expand my knowledge base. I will get back to my answer to expand it in future. Thanks for all the guidance! – Anurag Jun 29 '15 at 13:42