java中的SecurityManager有没有办法选择性地授予ReflectPermission(“suppressAccessChecks”)?
Java 中的 SecurityManager 有没有办法根据调用 setAccessible() 的详细信息选择性地授予 ReflectPermission("suppressAccessChecks") ?我看不出有什么办法可以做到这一点。
对于某些沙盒代码,允许调用 setAccessible() 反射 API 非常有用(例如运行各种动态 JVM 语言),但仅在方法上调用 setAccessible() 时/源自沙盒代码的类的字段。
如果不可能的话,除了选择性授予 ReflectPermission("suppressAccessChecks") 之外,还有其他建议吗?如果 SecurityManager.checkMemberAccess() 有足够的限制,也许在所有情况下授予权限都是安全的?
Is there any way for a SecurityManager in Java to selectively grant ReflectPermission("suppressAccessChecks") depending on the details of what setAccessible() is being called on? I don't see any way for this to be done.
For some sandboxed code, it would be very useful (such as for running various dynamic JVM languages) to allow the setAccessible() reflection API to be called, but only when setAccessible() is called on a method/field of a class that originates in the sandboxed code.
Does anyone have any alternative suggestions other than selective granting of ReflectPermission("suppressAccessChecks") if this isn't possible? Perhaps it would be safe to grant in all cases if SecurityManager.checkMemberAccess() is sufficiently restrictive?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
也许查看调用堆栈就足以满足您的目的?像这样的东西:
Maybe looking at the call stack would be enough for your purposes? Something like:
这可以通过使用字节码编织和 Byte Buddy 之类的库来实现。您可以创建自定义权限,并将
AccessibleObject.setAccessible
方法替换为使用 Byte 检查自定义权限的自定义方法,而不是使用标准ReflectPermission("suppressAccessChecks")
权限好友变身。此自定义权限工作的一种可能方法是使其基于调用者的类加载器和正在修改访问权限的对象进行访问。使用此功能允许隔离代码(使用自己的类加载器从单独的加载器加载的代码)在其自己的 jar 中的类(但不是标准 Java 类或您自己的应用程序类)上调用
setAccessible
。这样的权限可能看起来像:
这就是我选择实现此权限的方式,但它也可以是包或类白名单或黑名单。
现在,有了此权限,您可以创建一个存根类来替换
AccessibleObject.setAcessible
方法以改为使用此权限。有了这两个类,您现在可以使用 Byte Buddy 构建一个转换器来转换 Java
AccessibleObject
以使用您的存根。创建转换器的第一步是创建一个 Byte Buddy 类型池,其中包括引导类和包含存根的 jar 文件。
接下来使用反射来获取对 AccessObject.setAccessible0 方法的引用。这是一个私有方法,如果对
setAccessible
的调用通过了权限检查,它实际上会修改可访问性。用这两块就可以建造变压器了。
最后一步是安装 Byte Buddy Java 代理并执行转换。包含存根的 jar 还必须附加到引导类路径。这是必要的,因为
AccessibleObject
类将由引导加载程序加载,因此所有存根也必须加载到那里。当使用 SecurityManager 并将存根类和您要应用选择性权限的代码隔离在运行时加载的单独 jar 中时,这将起作用。必须在运行时加载 jar,而不是将它们作为标准依赖项或捆绑库,这会使事情变得有点复杂,但这似乎是使用 SecurityManager 时隔离不受信任代码的要求。
我的 Github 存储库 sandbox-runtime 有一个完整、深入的沙盒运行时环境示例,其中包含执行隔离的不可信代码和更具选择性的反射权限。我还有一篇博客文章,其中详细介绍了 选择性设置可访问权限件。
This is possible using byte code weaving with a library like Byte Buddy. Instead of using the standard
ReflectPermission("suppressAccessChecks")
permission, you can create a custom permission and replace theAccessibleObject.setAccessible
methods with custom methods that check your custom permission using Byte Buddy transformations.One possible way for this custom permission to work is for it to base access on the classloader of the caller and the object that access is being modified on. Using this allows isolated code (code loaded from a separate with it's own class loader) to call
setAccessible
on classes in its own jar, but not Standard Java classes or your own application classes.Such a permission might look like:
This is how I chose to implement this permission, but it could instead be a package or class whitelist or blacklist.
Now with this permission you can create a stub class that will replace the
AccessibleObject.setAcessible
method to instead use this permission.With these two classes in place you can now use Byte Buddy to build a transformer for transforming the Java
AccessibleObject
to use your stub.The first step to create the transformer is to create a Byte Buddy type pool that includes the bootstrap classes and a jar file containing your stubs.
Next use reflections to get a reference to the
AccessObject.setAccessible0
method. This is a private method that actually modifies the accessibility if the call tosetAccessible
passes permission checks.With these two pieces the transformer can be built.
The final step is to then install the Byte Buddy Java agent and perform the transformation. The jar containing the stubs must also be appended to the bootstrap class path. This is necessary because the
AccessibleObject
class will be loaded by the bootstrap loader, thus any stubs must be loaded there as well.This will work when using a SecurityManager and isolating both the stubs classes and the code that you are applying the selective permissions to in separate jars that are loaded at runtime. Having to load the jars at runtime rather than having them as standard dependencies or bundled libs complicates things a bit, but this seems to be a requirement for isolating untrusted code when using the
SecurityManager
.My Github repo sandbox-runtime has a full, in-depth, example of a sandboxed runtime environment with execution of isolated untrusted code and more selective reflection permissions. I also have a blog post with more detail on just the selective setAccessible permissions pieces.
FWI:由于 setAccessible 似乎只有一个有效的序列化用例,我认为您可能经常会直接否认它。
也就是说,我对一般如何做这类事情感兴趣,因为我也必须编写一个安全管理器来阻止动态加载的代码执行我们的应用程序容器代码需要能够执行的操作。
FWI: Since setAccessible seems only to have a valid use-case with serialization, I would think you might often get away with simply denying it outright.
That said, I am interested in how one does this sort of thing in general because I too have to write a security manager to block dynamically loaded code from doing things that our application container code needs to be able to do.