为了账号安全,请及时绑定邮箱和手机立即绑定

如何检查 SecurityManager 中的调用者类来源?

如何检查 SecurityManager 中的调用者类来源?

不负相思意 2023-06-14 14:35:26
我有一个用于受信任的应用程序代码的 ClassLoader 和一个用于用户提交的(不受信任的)代码的单独的 ClassLoader。我希望安全管理器限制用户提交的代码。如何从 SecurityManager 中检查调用方来源?查看伪代码:System.setSecurityManager(new SecurityManager() {    public void checkPermission(Permission permission) {        if (/*caller class is not loaded by the trusted classloader*/) {            throw new SecurityException("You do not have permissions.");        }    }});我已经尝试过的:StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass().getClassLoader()首先检查权限,以便它给出堆栈溢出异常。Thread.currentThread().getStackTrace()[2].getClassLoaderName()是不安全的,因为它只提供类加载器名称而不是类对象,如果不受信任的加载器的规范名称与受信任的加载器相同,那么这是一个安全问题。
查看完整描述

2 回答

?
慕姐8265434

TA贡献1813条经验 获得超2个赞

首先,SecurityManager 有一个受保护的方法getClassContext()。
您的代码如下所示:

System.setSecurityManager(new SecurityManager() {

    public void checkPermission(Permission permission) {

        Class<?> caller = getClassContext()[1];

        ClassLoader ccl = caller.getClassLoader();

        if (ccl != null || ccl != getClass().getClassLoader()) {

            throw new SecurityException("You do not have permissions.");

        }

    }

});

其次,如果要使用 a StackWalker,建议您复用StackWalker实例:


StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);

System.setSecurityManager(new SecurityManager() {

    public void checkPermission(Permission permission) {

        Class<?> caller = walker.getCallerClass();

        ClassLoader ccl = caller.getClassLoader();

        if (ccl != null || ccl != getClass().getClassLoader()) {

            throw new SecurityException("You do not have permissions.");

        }

    }

});

第三,这很可能不会做你想做的。安全检查在整个 JDK 中完成,因此调用者可能在任意数量的堆栈级别之外,需要您检查整个堆栈(提示:在您第二次访问堆栈中的 SecurityManager 时中断)。


相反,定义一个策略(创建一个 java 策略文件),您可以在其中授予您的代码所有权限并使用 java.lang.SecurityManager。


如果无法编写您自己的策略文件,您也可以使用Policy.setPolicy()安装您自己的java.security.Policy.


一些实现 a 的提示java.security.Policy:

  • 覆盖implies和两种getPermissions方法。严重地。

  • 赶上你自己ProtectionDomain的政策类。( private static final ProtectionDomain MY_PD = MyPolicy.class.getProtectionDomain())

  • 如果检查是针对您自己的 ProtectionDomain,请使用快速路径。


查看完整回答
反对 回复 2023-06-14
?
慕后森

TA贡献1802条经验 获得超5个赞

我找到了一个临时解决方案,但它并不完美:


System.setSecurityManager(new SecurityManager() {

    public void checkPermission(Permission permission) {

        Class<?> caller = SecurityManager.class;

        Class<?>[] classContext = this.getClassContext();

        int loopAmount = 0;


        while (caller.getCanonicalName() == null

                 || !caller.getCanonicalName().startsWith("nl")) {

            caller = classContext[loopAmount];

            loopAmount++;

        }


        if (caller.getClassLoader() != trustedClassLoader) {

            throw new SecurityException("You do not have permissions.");

        }

    }

});

所有不受信任的类的规范名称都必须以“nl”开头。这是 afaik 从类上下文中获取调用者类的唯一方法,因为调用者类的数组位置未知,上下文数组的最后一个元素始终是具有 main 方法的类。


查看完整回答
反对 回复 2023-06-14
  • 2 回答
  • 0 关注
  • 120 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信