使用 AccessController 限制权限 [英] Using AccessController to limit permissions

查看:61
本文介绍了使用 AccessController 限制权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图阻止在主 Java 应用程序内部"运行的插件访问它们不应该访问的内容.我已经阅读了有关策略、AccessController 和 ProtectionDomains 的文章,但它们非常面向 JAR.

I'm trying to prevent plugins that run "inside" the main Java application from accessing things they shouldn't. I've read about Policies, and AccessControllers, and ProtectionDomains, but they're very oriented around JARs.

我已经试过了:

import java.nio.file.Files
import java.nio.file.Paths
import java.security.*


fun main(args: Array<String>) {
    Policy.setPolicy(object : Policy() {})
    System.setSecurityManager(SecurityManager())

    val domain = ProtectionDomain(null, Permissions() /* no permissions */)
    AccessController.doPrivileged(PrivilegedAction {
        untrusted()
    }, AccessControlContext(arrayOf(domain)))
}

fun untrusted() {
    try {
        // Works as expected
        Files.readAllBytes(Paths.get("build.gradle"))
        throw IllegalStateException("Was able to access file, but shouldn't have been able to")
    } catch (e: AccessControlException) {
    }
    try {
        // Should throw AccessControlException, but doesn't
        AccessController.doPrivileged(PrivilegedAction {
            Files.readAllBytes(Paths.get("build.gradle"))
        })
        throw IllegalStateException("Was able to access file, but shouldn't have been able to")
    } catch (e: AccessControlException) {
    }
}

即使我通过自定义受限的 ProtectionDomain 调用 untrusted(),它似乎也可以轻松突破它.我期待 untrusted 中的 doPrivileged 调用与最外层 ProtectionDomain(主程序,它具有所有权限)和调用者的 ProtectionDomain(没有权限),导致 untrusted 基本上拥有 0 权限.

Even though I'm invoking untrusted() via a custom limited ProtectionDomain, it seems it can trivially break out of it. I'm expecting the the doPrivileged call in untrusted to operate with the intersection of the permissions of the outermost ProtectionDomain (the main program, which has all permissions) and the caller's ProtectionDomain (which has no permissions), resulting in untrusted having essentially 0 permissions.

我也试过这样设置域:

val domain = ProtectionDomain(CodeSource(URL("http://foo"), null as Array<CodeSigner>?), Permissions() /* no permissions */)

但这也不起作用——Policy 是用主程序的 ProtectionDomain 而不是调用 untrusted() 的那个查询的.(显然我需要更新 Policy 以正确处理http://foo",但它甚至不检查 ProtectionDomain 反正)

but this also doesn't work -- the Policy is queried with the main program's ProtectionDomain and not the one calling untrusted(). (Obviously I'd need to update the Policy to handle "http://foo" correctly, but it doesn't even check that ProtectionDomain anyway)

那么我的理解哪里出了问题?

So where has my understanding gone wrong?

推荐答案

经过这方面的研究,我想我有了答案.我可以写一个更长的答案,但我想我会在这里切入正题.

After doing some research on this, I think I have an answer. I could write a significantly longer answer, but I think I'll just cut to the chase here.

ClassLoader 加载的每个类都有一个 ProtectionDomain+CodeSource 与它.这些有点粗糙——CodeSource 表示类的来源,但它不是指向单个 .class 文件或任何东西的指针——它是指向目录或 JAR.因此,同一 JAR 或目录中的两个类通常具有相同的权限.您的策略可以将任何具有可识别 ProtectionDomain+CodeSource 的类或脚本列入白名单/黑名单.

Each class loaded by a ClassLoader has a ProtectionDomain+CodeSource associated with it. These are somewhat coarse -- a CodeSource represents where a class came from, but it's not a pointer to an individual .class file or anything -- it's to a directory or a JAR. Thus two classes in the same JAR or directory will generally have identical permissions. Any class or script that has an identifiable ProtectionDomain+CodeSource can be whitelisted/blacklisted by your Policy.

当然,例外(有点)是 AccessController.doPrivileged 带有权限参数.这使您可以限制代码区域的权限.但是那个代码理论上可以只用回调调用AccessController.doPrivileged.该方法签名意味着不要检查我的整个调用堆栈的权限;只需在策略文件中查找我的 ProtectionDomain+CodeSource,看看它说了什么."因此,如果您正在运行真正不受信任的代码,则最好确保 a.它有一个与您信任的应用程序不同的 ProtectionDomain+CodeSource,并且 b.您的政策能够识别该代码并授予其适当限制的权限.

The exception (kinda) to this is, of course, is AccessController.doPrivileged with Permission arguments. This lets you clamp down the permissions of a region of code. But that code could, in theory, call AccessController.doPrivileged with just the callback. That method signature means "don't check my entire call stack for permissions; just look up my ProtectionDomain+CodeSource in the Policy file and see what it says." So if you're running truly untrusted code, you better make sure that a. it has a ProtectionDomain+CodeSource different from your trusted application, and b. that your Policy is able to identify that code and grant it appropriately-limited permissions.

这篇关于使用 AccessController 限制权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆