jbarnette / johnson

Johnson wraps JavaScript in a loving Ruby embrace.
http://github.com/jbarnette/johnson/wikis
466 stars 33 forks source link

Security considerations #41

Open gdelugre opened 13 years ago

gdelugre commented 13 years ago

Hi guys,

I am the developer of a PDF manipulation framework (Origami) and I'm currently trying to integrate Johnson into it. My project is oriented on malicious PDF documents analysis for exploit analysts/writers. As many PDF exploits make use of embedded JavaScript code, being able to run the code in a clean and safe SpiderMonkey engine would be very nice.

I have started reimplementing the Adobe JavaScript API with Johnson, binding the calls to my PDF engine internals and it seems to work very nicely. However, I am running into one problem : the JavaScript code to be run is supposed to be totally untrusted, and as such it should not be possible to escape from the SpiderMonkey engine.

It is currently very easy to escape from JavaScript for two reasons:

  1. The Ruby Object namespace is directly included in the global scope.
  2. It is possible to make calls on internal Ruby methods from JavaScript.

For instance from JS:

js> Ruby.File.read("/etc/passwd")

If util is a defined Ruby Object accessible in JS scope:

js> util.send("system","/bin/sh")

Could it be possible that you introduce some sort of flag to prevent the Ruby Object namespace to be included in global ? Maybe also introduce some checks so that only user-defined methods are accessible from JS ?

I am not very familiar with your code base, but I was thinking about including those security checks into JSLandProxy::send_with_possible_block and modifying Runtime#initialize.

Would that be OK for you?

Thanks, Guillaume Delugré

matthewd commented 13 years ago

Sure!

I will note, however, that I think @cowboyd's therubyracer already has such controls built in, so that might be worth a look for your use case.

cowboyd commented 13 years ago

Hey guys,

therubyracer does start you out with an encapsulated JavaScript evironment that has no access to Ruby except for what you embed. Thera are also controls for setting memory constraints.

One area where you need to be careful if you're executing untrusted code is something hogging the CPU. The Ruby Racer does not currently support timeboxing operations. V8 does support this, but I have not yet wired it up because it involves some trickly locking shenanigans. It will eventually, but not yet, and I don't want to give you the impression that it does.

If JRuby is an option, then you might want to have a look at therubyrhino which does allow you to constrain both the memory AND the CPU.

@matthewd Thanks for the help on #rubinius the other day. I was wondering if you might want to compare notes on managing interaction between two garbage collectors at some point. I think it's a pretty niche area and I'd like to hear your thoughts.