使用 AccessController 限制权限 [英] Using AccessController to limit permissions
问题描述
我试图阻止在主 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屋!