最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - Does AccessController.doPrivileged give JavaScript threads the permissions of the signed Applet? - Stack Overflow

programmeradmin4浏览0评论

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.

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.

Share Improve this question asked Sep 3, 2010 at 0:39 EddieEddie 54.4k22 gold badges129 silver badges146 bronze badges 3
  • Every access control check inspects the intersection of all stack frames (including the stack frame leading up to the instantiation of the current thread, recursively). If the privileged being checked is not in every single frame in that intersection, it fails. If there is a doPrivileged frame, all frames leading up to that frame are ignored. So for example if you doPrivileged some unprivileged code which tries to open a file, the check will fail. Likewise if unprivileged code doPrivileges trusted code that opens a file, the check will fail. – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ Commented Sep 3, 2010 at 2:54
  • But if untrusted code invokes trusted code and the trusted code in turn calls doPrivilege to open a file, the check will succeed. – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ Commented Sep 3, 2010 at 2:54
  • @Longpoke: Why don't you write that as an answer? – Eddie Commented Sep 3, 2010 at 3:44
Add a comment  | 

2 Answers 2

Reset to default 11
  • "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).

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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论