如何在某些 java 类或包上限制 createObject()?

Posted

技术标签:

【中文标题】如何在某些 java 类或包上限制 createObject()?【英文标题】:How to restrict createObject() on certain java classes or packages? 【发布时间】:2015-08-24 10:17:09 【问题描述】:

我想创建一个安全的 ColdFusion 环境,为此我使用了多个沙箱配置。使用友好的管理员界面可以轻松完成以下任务:

限制 CFtag,例如:cfexecute、cfregistry 和 cfhttp。 禁用对内部 ColdFusion Java 组件的访问。 第三方资源只能访问某些服务器和端口范围。

而其他人则相应地使用 Web 服务器的配置。

问题:

所以我对设置很满意,只是后来遇到了,不管cfexecute标签有什么限制,都可以使用java.lang.Runtime轻松执行系统文件或脚本;

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

或使用java.lang.ProcessBuilder:

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

问题是我找不到任何允许我禁用这两个类的解决方案:createObject()java.lang.Runtimejava.lang.ProcessBuilder。 注意:我也尝试过 sanbox 和 os 权限中的文件限制,但不幸的是,它们似乎只适用于 I/O 文件操作,我不能弄乱系统库的安全策略,因为它们可能在内部使用由 ColdFusion 提供。

【问题讨论】:

您可以通过 GUI 禁用 CreateObject(Java) 功能还是限制性太强?设置Disable access to internal ColdFusion Java components下的管理员设置呢?你检查了吗? 糟糕!没关系,我看到您已经在问题中提到禁用对内部 ColdFusion Java 组件的访问。 我找到了一篇类似的文章。他们在其中谈论共享托管环境中的安全性,但提到的问题与您发现的相同。不幸的是,他们也没有给出解决方案。 所以主机商面临一个艰难的选择:禁用 CFEXECUTE、CFOBJECT、CreateObject(.NET)、CreateObject(COM) 和 CreateObject(JAVA),或者接受共享主机配置中没有任何安全性。 - jochem.vandieten.net/2008/12/09/… 根据我的阅读,您通常会实现某种SecurityManager。 (这可能甚至是 CF 实现沙盒功能的方式)。但是,我不知道安全策略会对 CF 代码的其余部分产生什么影响(如果有的话)。 澄清一下,是的,当您启用沙盒安全性时,ColdFusion 会使用安全管理器。来自文档:要在 J2EE 版本中使用沙盒安全性,应用程序服务器必须运行安全管理器 (java.lang.SecurityManager) 并且您定义以下 JVM 参数(对于 Tomcat,这是 java.args 行在 cf_root/cfusion/bin/jvm.config 文件中) - -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" 【参考方案1】:

根据@Leigh 和@Miguel-F 的有用建议,我尝试实施Security ManagerPolicy。结果如下:

1. 在运行时指定附加策略文件,而不是更改默认的java.policy 文件。为此,我们使用 CFAdmin 接口将以下参数添加到 JVM 参数,或者将其附加到 jvm.config 文件中的 jvm.args 行:

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

jre\bin\ 中有一个不错的 GUI 实用程序,名为 policytool.exe,它允许您轻松有效地管理策略条目。

2.我们已强制执行安全管理器并提供了我们的自定义安全策略文件,其中包含:

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

在这里,我们将所有文件的 FilePermission 设置为 read, write, delete,但列表中不包括 execute,因为我们不希望使用 java 运行时执行任何类型的文件。

注意:如果我们希望将策略应用于所有应用程序而不考虑来源,则可以将代码库设置为空字符串。

我真的希望在策略文件中有一个 deny 规则,以使事情变得更容易,类似于我们正在使用的 grant 规则,但不幸的是没有。如果您需要制定一套复杂的安全策略,您可以使用Prograde 库,它实现了带有拒绝规则(stack ref.)的策略文件。 您当然可以将&lt;&lt;ALL FILES&gt;&gt; 替换为单个文件并相应地设置权限,或者为了更好地控制使用&lt;&lt;ALL FILES&gt;&gt; 和单个文件权限的组合。

参考:Default Policy Implementation and Policy File Syntax、Permissions in JDK 和 Controlling Applications

这种方法解决了我们的核心问题:通过指定文件允许的权限来拒绝使用 java 运行时执行文件。在其他方法中,我们可以直接在我们的应用程序中实现Security Manager 以从那里定义策略文件,而不是在我们的 JVM 参数中定义它。

//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);

为了能够设置它,我们需要在我们的策略文件中获得这些权限:

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

在应用程序中使用Security Manager 对象有其自身的优势,因为它公开了许多有用的方法例如:CheckExec(String cmd) 检查是否允许调用线程创建子进程。

//perform the check
try
  sm.checkExec("notepad.exe");

catch(SecurityException e)
  //do something...show warning.

【讨论】:

很好的信息。感谢您发布它。我期待着尝试一下:) 我仍然认为必须使用Security Manager 和Policy 文件来实现我们在这里的意图。我开始使用java.io.FilePermission,因为java.lang.RuntimePermission 中没有任何可用的目标名称来实现这样的目标(我最初预计会在这里找到)。另一个优雅的解决方案是使用自定义 ClassLoaders 过滤掉我们最初关注的两个类:java.lang.Runtime & java.lang.ProcessBuilder 我看到使用自定义类加载器的问题是我不太确定您是否可以像使用策略文件一样简单地进入正常的应用程序流程。也就是说,我还没有对它进行任何实验,所以我可能完全脱离了基地...... 我同意,即使自定义类加载器是一种解决方案,它们也不会像策略机制那样正常,因此我也没有任何经验,这是保持这个问题开放的另一个原因.我最近发现了一个关于 java 安全性的good read。 this 对 java 应用程序中的沙盒的回答和 Access Controller 让我认为必须有一个替代解决方案,如果可以说不是更好的解决方案。 我希望有人可以使用自定义类加载器发布解决方案。随着我对它的了解越来越多,我看到自定义类加载器的范围也是一个很好的替代解决方案。我仍然不具备适当的高级 Java 知识来解决该解决方案,但正在努力。

以上是关于如何在某些 java 类或包上限制 createObject()?的主要内容,如果未能解决你的问题,请参考以下文章

无法解析类或包 H2

在Android上捕获某些进程或包的数据包[关闭]

JVM 性能排查 自己做的笔记

仅对某些类允许 System.exit

如何使 DefaultValueHandling 仅适用于某些类或成员?

使用 FolderBrowserDialog 限制对某些文件夹的访问