How to restrict createObject() on certain java classes or packages?

1.1k Views Asked by At

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.

1

There are 1 best solutions below

10
On BEST ANSWER

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.
}