AccessController.doPrivileged 是否为 JavaScript 线程提供了已签名 Applet 的权限?

发布于 2024-09-17 07:13:45 字数 1796 浏览 4 评论 0原文

我正在查看一个经过 JavaScript 大量调用的签名 Applet。显然,源自 JavaScript 的线程比直接从 Java 内部启动的任何线程受到更严格的沙箱化。例如,如果 JavaScript 线程调用 Applet 并记录导致日志文件滚动的内容,则会引发安全异常。直接在 Applet 内启动的任何线程都不会遇到此安全异常。 log4j 的解决方案是使用异步附加器。

但对于其他安全异常(例如在签名的 Applet 中但在 JavaScript 线程中使用 Apache Axis),没有明显的方法来拥有一些异步线程。假设我有以下代码,如果从 Java 线程调用,则该代码可以工作,如果通过 JavaScript 调用,则将失败并出现 SecurityException:

public void someMethodCalledFromJavaScript() {
  // Stuff that would throw a SecurityException
}

我看到以下三个选项,但它们可能并非全部有效。为了便于讨论,请忽略执行是同步还是异步,因为这很容易管理。我很难理解安全模型的细节。以下是我的三个可能的选择:

  • 启动一个新线程(这个可以工作吗?):

    public void someMethodCalledFromJavaScript() {
      新线程(新可运行(){
        公共无效运行(){
          // 会抛出 SecurityException 的东西
        }
      })。开始();
    }
    
  • 让 Applet 有一个随时可用的线程,通过 JavaScript 源线程触发(这里是高度简化的代码) :

    私有易失性布尔 doit = false;
    
    // 这段代码在一个线程中运行,在@Applet init 时间启动
    公共无效总是等待(){
      而(真){
        如果(做){
          做=假;
          // 会抛出 SecurityException 的东西
        }
      }
    }
    
    公共无效 someMethodCalledFromJavaScript() {
      做=真;
    }
    
  • 使用 AccessController.doPrivileged:

    public void someMethodCalledFromJavaScript() {
      AccessController.doPrivileged(new PrivilegedAction() {
        公共对象运行(){
          // 会抛出 SecurityException 的东西
          返回空值;
        }
      });
    }
    

根据我读到的 AccessController.doPrivileged,您使用当前安全权限和代码安全域的权限的交集运行你打电话来。这对我来说没有意义,就好像您在低安全域和高安全域的交集处运行一样,您只会拥有低安全域。很明显我不明白一些事情。

我看到的具体 SecurityException 是这样的:

java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)

但是我当然很好奇 JavaScript 调用签名 Applet 的上下文中的一般情况,以及如何允许 JavaScript 发起的线程使用已签名 Applet 的权限运行,就好像它是纯粹源自 Applet 内的线程一样。

上述哪些选择有效,哪些比其他选择更好,以及为什么。

I'm looking at a signed Applet that is heavily called from JavaScript. Obviously, the threads that originate from JavaScript are more heavily sandboxed than any thread started directly from within Java. For example, if a JavaScript thread calls into the Applet and logs something that causes the log file to roll, a security exception is thrown. Any thread started directly within the Applet will not experience this security exception. The solution here with log4j is to use the asynchronous appender.

But with other security exceptions (for example making use of Apache Axis in the signed Applet but in a JavaScript thread) there is no obvious way to have some asynchronous thread. Let's say I have the following code that if called from a Java thread will work and if called via JavaScript will fail with a SecurityException:

public void someMethodCalledFromJavaScript() {
  // Stuff that would throw a SecurityException
}

I see three following options, but they may not all be valid. For the sake of this discussion, ignore whether or not the execution will be synchronous or asynchronous, as that's easily managed. I am having a difficult time understanding the details of the security model. Here are my three potential choices:

  • Start a new Thread (will this one even work?):

    public void someMethodCalledFromJavaScript() {
      new Thread(new Runnable() {
        public void run() {
          // Stuff that would throw a SecurityException
        }
      }).start();
    }
    
  • Have the Applet have a thread ready to go at all times, triggered via the JavaScript-origin thread (highly simplified code here):

    private volatile boolean doit = false;
    
    // This code is running in a Thread, started @ Applet init time
    public void alwaysWaiting() {
      while (true) {
        if (doit) {
          doit = false;
          // Stuff that would throw a SecurityException
        }
      }
    }
    
    public void someMethodCalledFromJavaScript() {
      doit = true;
    }
    
  • Use AccessController.doPrivileged:

    public void someMethodCalledFromJavaScript() {
      AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
          // Stuff that would throw a SecurityException
          return null;
        }
      });
    }
    

According to what I read of AccessController.doPrivileged, you run with the intersection of the current security privs and the privs of the security domain of the code you're calling. This doesn't make sense to me, as if you're running with the intersection of a low and a high security domain, you'll just have the low security domain. So clearly I'm not understanding something.

The specific SecurityException I'm seeing is this one:

java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)

but of course I'm curious about the general case in the context of JavaScript calling into a signed Applet, and how I can allow a JavaScript-originated thread to run with the priv's of the signed Applet as if it were a thread that originated purely within the Applet.

Which choices above will even work, and which are better than others, and why.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烏雲後面有陽光 2024-09-24 07:13:45
  • “启动一个新线程(这个能工作吗?)”

由于下面提到的原因而无法工作

  • 让 Applet 随时准备好一个线程,通过 JavaScript 源线程触发

当然会工作,但这更痛苦与调用 doPrivileged 相比,但在语义上具有相同的效果。

  • 使用 AccessController.doPrivileged

是的,这可以工作。

每个访问控制检查都会检查当前线程堆栈上所有堆栈帧的集合(包括导致当前线程实例化的堆栈帧,递归地)。如果存在 doPrivileged 帧,则指向该帧的帧不包含在集合中(但包含实际的 doPrivileged)。

如果所检查的权限不在该集合中的每个帧中,则检查失败。

换句话说,线程的当前权限是该集合中权限的交集。

因此,例如,如果特权代码 doPrivileged 是一些尝试打开文件的非特权代码,则检查将失败。同样,如果非特权代码doPrivileged打开文件的特权代码,检查将失败。但是,如果非特权代码调用特权代码,而特权代码又调用doPrivileged来打开文件,则检查将成功。

理论上,您应该只能授予您的Java代码库所需的权限(可能访问某些独立目录),然后向JavaScript代码授予相同权限它将使用这个特权代码,但我怀疑任何浏览器都有这样的功能。令我惊讶的是 JavaScript 甚至运行在与 Java 不同的保护域中。

我从未做过 JavaScript<->Java 互操作,但似乎无论如何您都必须使 JavaScript 调用的方法在其整个主体上使用 doPrivileged 块。


编辑:正如萨米所说,在特权代码中调用 doPrivileged 块时要小心(并阅读他的答案)。

  • "Start a new Thread (will this one even work?)"

Wont work because of reasons mentioned below

  • Have the Applet have a thread ready to go at all times, triggered via the JavaScript-origin thread

Will work of course, but that's more painful than calling doPrivileged, yet has the same effect semantically.

  • Use AccessController.doPrivileged

Yes this will work.

Every access control check inspects the set of all stack frames on the stack of the current thread (including the stack frame leading up to the instantiation of the current thread, recursively). If there is a doPrivileged frame, frames leading up to that frame are not included in the set (but the actual doPrivileged frame is included).

If the privilege being checked is not in every single frame in that set, the check fails.

In other words, the current privileges of a thread are the intersection of privileges in this set.

So for example if privileged code doPrivilegeds some unprivileged code which tries to open a file, the check will fail. Likewise if unprivileged code doPrivilegeds privileged code that opens a file, the check will fail. But if unprivileged code invokes privileged code and the privileged code in turn calls doPrivileged to open a file, the check will succeed.

In theory, you should be able to only grant your Java codebase the privileges it needs (perhaps access to some isolated directory), and then grant the same privileges to the JavaScript code that will use this privileged code, but I doubt any browser has such features. I'm surprised JavaScript even runs in another protection domain than Java.

I've never done JavaScript<->Java interop, but it seems no matter what you are going to have to make the methods that are invoked by JavaScript use doPrivileged blocks on their entire body.


EDIT: As Sami said, be careful when invoking doPrivileged blocks within the privileged code (and read his answer).

葬心 2024-09-24 07:13:45

我会选择 doPrivileged。请注意,每个有权访问您的小程序的人都可以下载它并将其放在自己的网站上,并让自己的恶意 JavaScript 以您无法想象的方式调用它。

其他解决方案的安全隐患几乎相同(编辑:尽管创建新线程不起作用,正如 Longpoke 指出的那样),但它们更复杂。所以我看不出他们有什么优势。

AccessController.doPrivileged 仅考虑直接调用者的保护域。在您的示例中,定义了方法 someMethodCalledFromJavaScript 的类。如果这是签名 jar 中的受信任类,则不受信任的 Javascript 调用它并不重要。

I'd go with the doPrivileged. Just be aware that everybody that has access to your applet can download it and put it on their site and have their own malicious javascript call it in ways you didn't imagine.

The security implications of the other solutions are pretty much the same (EDIT: although creating a new Thread doesn't work, as Longpoke pointed out), but they are more complicated. So I don't see any advantage with them.

The AccessController.doPrivileged considers the protection domain of just the immediate caller. In your example, the class where your method someMethodCalledFromJavaScript is defined. If this a trusted class in the signed jar, it doesn't matter that the untrusted Javascript is calling it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文