Somewhat hacked-together eval jail

Discussion in 'Ruby' started by Jonathan Nielsen, Dec 28, 2009.

  1. Hi everyone,

    I'm working on a program where a lot of externally loaded scripts will
    be run. Although the scripts will all be written by trusted (or
    mostly trusted) sources, I want to implement some form of jail that is
    at least somewhat difficult to break out of to eval these scripts.

    So far, I've tried this:
    --------------
    jail = Module.new {
    def self.remove_const (...)
    def self.parent (...)
    def self.const_missing (...)
    }
    (Module.constants.collect{|c|c.to_sym} - ScriptJailWhitelist).each { |const|
    jail.const_set(const,nil)
    }
    --------------
    which adds local constants to my jail module that 'override' the
    global ones that would allow someone to break out (for example,
    TOPLEVEL_BINDING) with the exception of a whitelist that I have
    defined (Array, Date, Hash, etc) In the initial declaration for the
    jail Module I also add methods for self.remove_const, self.parent that
    simply raise an exception. Lastly I add a method for
    self.const_missing because I have ActiveSupport loaded.

    I then populate the jail module with methods needed for the script
    running and do jail.module_eval in a new thread with safe_level 3.
    (all this work because safe_level 4 was too restrictive for what I
    needed... heh)

    As far as possible security problems, perhaps there is a way to get
    the Object class (some_instance.class) that would allow access to the
    TOPLEVEL_BINDING constant once again... but I couldn't find a way in
    my quick experiments.

    I'm sure there are some holes in this design, but so far I can't find
    any playing around in irb with a binding inside this Module. I'm
    hoping someone here might know the language a little better than me
    and point out anything obvious I might be missing. Again, this
    doesn't need to be 100% secure, but hey if it is then that's a bonus
    :)

    Or if there's a better way to do this that I somehow missed, please
    enlighten me.


    Thank you for your time,
    -Jonathan Nielsen
    Jonathan Nielsen, Dec 28, 2009
    #1
    1. Advertising

  2. On Mon, Dec 28, 2009 at 9:58 AM, Jonathan Nielsen <> wrote=
    :
    > Hi everyone,
    >
    > I'm working on a program where a lot of externally loaded scripts will
    > be run. =A0Although the scripts will all be written by trusted (or
    > mostly trusted) sources, I want to implement some form of jail that is
    > at least somewhat difficult to break out of to eval these scripts.
    >

    You may want to take a look at why_sandbox if you are on 1.8 MRI ruby.


    > So far, I've tried this:
    > --------------
    > =A0 =A0jail =3D Module.new {
    > =A0 =A0 =A0def self.remove_const (...)
    > =A0 =A0 =A0def self.parent (...)
    > =A0 =A0 =A0def self.const_missing (...)
    > =A0 =A0}
    > =A0 =A0(Module.constants.collect{|c|c.to_sym} - ScriptJailWhitelist).each=

    { |const|
    > =A0 =A0 =A0jail.const_set(const,nil)
    > =A0 =A0}


    Not a bad start.

    When I tried to use a collection to contain malicious code in Try
    Ruby, I had my rear end handed to me.
    It was about as secure as allowing a printer read and write to your
    password file.

    Also, it was slow. There are a lot of dirty ways to execute system commands=
    andrew mcelroy, Dec 28, 2009
    #2
    1. Advertising

  3. On Mon, Dec 28, 2009 at 9:41 AM, andrew mcelroy <> wrote:
    > You may want to take a look at why_sandbox if you are on 1.8 MRI ruby.
    >


    That's actually what I found first, but I'd like my app to be ruby
    1.8.7 compatible... it looked like that required a patched version of
    1.8.6? I also looked into jruby which appeared to have a similar
    feature in the mainstream distribution, but I couldn't get it to
    work...

    >
    > Not a bad start.
    >
    > When I tried to use a collection to contain malicious code in Try
    > Ruby, I had my rear end handed to me.
    > It was about as secure as allowing a printer read and write to your
    > password file.
    >
    > Also, it was slow. There are a lot of dirty ways to execute system commands.
    >
    > $SAFE isn't used all that often anymore, but it may help in your case.
    >

    Yeah, setting $SAFE to 3 stopped every attempt at executing system
    commands that I tried. I wanted to set it to 4, but that proved to be
    too restrictive. Due to the nature of my program it was possible to
    create scripts that ran at a lower safe level if the safe level was
    set to 3 alone, so I hope that keeping people out of all classes
    except some whitelisted ones will solve that problem.

    Thanks for the reply!


    Is there a way in ruby of calling up a class without the constant that
    refers to it being accessible? If so, that would blow a big hole in
    my method here...

    -Jonathan Nielsen
    Jonathan Nielsen, Dec 28, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?cmVyZGF2aWVz?=

    CultureInfo getting hacked during page load.

    =?Utf-8?B?cmVyZGF2aWVz?=, Apr 30, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    387
    Natty Gur
    May 2, 2004
  2. Replies:
    16
    Views:
    1,457
    Paul Boddie
    Jul 4, 2007
  3. ffxff
    Replies:
    0
    Views:
    297
    ffxff
    Jul 12, 2008
  4. Replies:
    1
    Views:
    97
    William James
    Jan 17, 2009
  5. Grant Edwards

    Using ssl.wrap_socket() in chroot jail

    Grant Edwards, May 7, 2014, in forum: Python
    Replies:
    4
    Views:
    79
    Grant Edwards
    May 8, 2014
Loading...

Share This Page