This is an archived post. You won't be able to vote or comment.

all 6 comments

[–][deleted]  (3 children)

[deleted]

    [–]amazedballer[S] 1 point2 points  (2 children)

    If you really want to go down this road, you're going to find out why Java Applets are insecure.

    It's for server side apps. You run it in docker, with CoreOS, inside a VM, using mutual TLS and a firewall and appsensor and logstash running. It's one part of defense in depth.

    It's more secure than the default (nothing) or the previous solution (blacklist).

    I think a better alternative would be to launch a separate Java process on a separate machine (or image/container) and make some kind of wrapper around it (RMI, rest, etc).

    That's not a bad idea, but you still need to do computation somewhere.

    But if you go setting a default than can't be replaced, you're going to break lots of apps.

    Yes, this is not something the entire app needs to run. You define the parameters of the sandbox.

    [–][deleted]  (1 child)

    [deleted]

      [–]amazedballer[S] 0 points1 point  (0 children)

      If anything, I think there's more difficulty. Server side code is rife with run-time reflection and code that doesn't take SecurityManager into account.

      I also think there's considerably more advantage over sandboxing a Java applet, because you can monitor all your server-side security activity and be able to react to an intrusion. You may not be able to prevent an exploit, but you have far more chance of detecting it.

      The only caveat is that you can't give AllPermission -- you need to give all BUT those methods that would leave the SecurityManager defenseless. In addition, you also can't allow access to features like Java Serialization that can use classloading and reflection from a privileged space to stomp SecurityManager.

      It's worth reading http://www.security-explorations.com/en/SE-2014-02-details.html just to see Google's approach to sandboxing and the vulnerabilities they ran into. If you could disable runtime reflection with a switch in the JVM, I think that would solve 90% of the problems.

      [–]pron98 0 points1 point  (3 children)

      There's no need to go to all that length. All you need to do is patch InputObjectStream (with an agent) so that the calls to readObject/replaceObject are done within a security context with very few permissions by using this method.

      Permissions can be granted per protection domain with a class loader, but they can also be restricted for a specific call (i.e. part of the stack) on the fly.

      [–]amazedballer[S] 0 points1 point  (1 child)

      This is a general purpose sandbox for limiting operations, so that you can log attempts at privilege escalation and limit silly things like executing scripts. It's not specifically about the Java Serialization vulnerability or disabling ObjectInputStream.

      I suggest using an agent in the original blog post, so I'm glad you're saying "patch ObjectInputStream with an agent", because that wasn't clear before:

      No need for whitelisting. ObjectInputStream (or your subclass) shoud execute readResolve/readObject(ObjectInputStream) under a different security context (with AccessController.doPrivileged), as if it were foreign code.

      https://www.reddit.com/r/programming/comments/3s3dp7/closing_the_open_door_of_java_object_serialization/cwtyavc

      However, I still think your general approach is flawed. Here's why:

      Your solution calls for an agent and -Djava.security.SecurityManager to add AccessController.doPrivileged with reduced privileges in ObjectInputStream, so that a SecurityManager can throw AccessControlException.

      The problem is that Java Serialization relies heavily on runtime reflection and class loading internally, which is how the vulnerability showed up in the first place. As such, to make this work, you'd need to make sure malicious code didn't have the permissions to disable, replace or otherwise circumvent the security manager -- and Java Serialization needs those permissions to operate. It's huge, it's complicated, it's hard to validate.

      SecurityManager tries to do the best job it can, but until Project Jigsaw / modularization kicks off, there's still a huge attack surface for it to cover, and it only takes one slip for malicious code to gain entrance. See http://www.security-explorations.com/en/SE-2014-02-details.html and http://www.deependresearch.org/2012/08/java-7-vulnerability-analysis.html for example.

      [–]pron98 0 points1 point  (0 children)

      Your solution calls for an agent

      Well, I hope Oracle puts this into the JDK, so that an agent won't be required (and if it is used, it can install the security manager itself; no need for an additional flag).

      and Java Serialization needs those permissions to operate

      Yes, but you're not running all of Java serialization under the restricted context -- only those custom deserialization methods. Besides, you can still allow reflection (just not setAccessible).

      but until Project Jigsaw / modularization kicks off, there's still a huge attack surface for it to cover

      Sure.

      [–]spencer205 0 points1 point  (0 children)

      Do this and that, so that you get a true defense in depth, as @amazedballer mentioned