Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Sandboxing eval'd code

Reply
Thread Tools

Sandboxing eval'd code

 
 
eastcoastcoder@gmail.com
Guest
Posts: n/a
 
      02-08-2006
I'm working on a web app with complicated and ever changing business
rules.

On any given day, a new rule may need to be introduced - quickly.
There's not enough commonality between them to factor out and just make
configuration changes. So the developers are always adding and
modifying, which of course makes reliability and testing difficult.

I thought of the following solution: New business rules can be coded in
Ruby and serialized into the database, along with configuration options
as to when they apply. (The rules look at a bunch of things and return
either continue or abort - so making hooks for them is easy. They
should never modify *anything* - just return a value.)
The app will load them and run them in a sandbox, catching all
exceptions and also timeing them out if they fail to return.
Developers can add/modify these rules easily, without touching the core
app, and, should one have a bug, although it may give the wrong result,
it won't bring the rest of the system down.

One concern I have is that I know that eval'd code can modify class
definitions, and access other objects via ObjectSpace. Is there anyway
to eval code so that it can't change Classes and the like? A true
Sandbox.

I'm not familiar enough with $SAFE to know what it can do (although
I've heard it is not reliable). http://tryruby.hobix.com/ probably
does this, but source doesn't seem available.
http://approximity.com/cgi-bin/rubyb...page.rb?nd=214 looks
relevant, but I can't figure it out.

In general, comments about this greatly appreciated.

 
Reply With Quote
 
 
 
 
Erik Veenstra
Guest
Posts: n/a
 
      02-08-2006
class String
def de_inspect
Thread.new do
$SAFE = 4

de_inspect_unsafe
end.value
end

def de_inspect_unsafe # But fast...
eval(self, Module.new.module_eval{binding})
end

def evil_eval # Don't use it !!!
eval(self)
end
end

def foo ; p [self, 1] ; end

foo

"def foo ; p [self, 2] ; end".evil_eval

foo

"def foo ; p [self, 3] ; end".de_inspect_unsafe

foo

"def foo ; p [self, 4] ; end".de_inspect # Will fail...

foo

 
Reply With Quote
 
 
 
 
m4dc4p
Guest
Posts: n/a
 
      02-08-2006
Could you elaborate a little more on what you are showing here?
Specifically, why is it called "de_inspect_unsafe" and what is the
array in "p [self, 1]", "p [self, 2]" etc for?

I have also wondered about this issue myself and would like to see what
people have done. I'd love to see why's "try ruby" code but that is
probably a pipe dream ...

Erik Veenstra wrote:
> class String
> def de_inspect
> Thread.new do
> $SAFE = 4
>
> de_inspect_unsafe
> end.value
> end
>
> def de_inspect_unsafe # But fast...
> eval(self, Module.new.module_eval{binding})
> end
>
> def evil_eval # Don't use it !!!
> eval(self)
> end
> end
>
> def foo ; p [self, 1] ; end
>
> foo
>
> "def foo ; p [self, 2] ; end".evil_eval
>
> foo
>
> "def foo ; p [self, 3] ; end".de_inspect_unsafe
>
> foo
>
> "def foo ; p [self, 4] ; end".de_inspect # Will fail...
>
> foo


 
Reply With Quote
 
Erik Veenstra
Guest
Posts: n/a
 
      02-08-2006
class String
def de_inspect
Thread.new do
$SAFE = 4

de_inspect_unsafe
end.value
end

def de_inspect_unsafe # But fast...
eval(self, Module.new.module_eval{binding})
end

def evil_eval # Don't use it !!!
eval(self)
end
end

def foo ; p [self, 1] ; end

foo

"def foo ; p [self, 2] ; end".evil_eval

foo

"def foo ; p [self, 3] ; end".de_inspect_unsafe

foo

"def foo ; p [self, 4] ; end".de_inspect # Will fail...

foo

 
Reply With Quote
 
konsu
Guest
Posts: n/a
 
      02-08-2006
hello,

i have been looking for a solution to almost the same problem. but have not
found anything yet except for a solution that uses threads. just like this
code. which i have doubts about because creating threads in a web
application does not seem to scale too much.

konstantin


"Erik Veenstra" <> wrote in message
news: ups.com...
> class String
> def de_inspect
> Thread.new do
> $SAFE = 4
>
> de_inspect_unsafe
> end.value
> end
>
> def de_inspect_unsafe # But fast...
> eval(self, Module.new.module_eval{binding})
> end
>
> def evil_eval # Don't use it !!!
> eval(self)
> end
> end
>
> def foo ; p [self, 1] ; end
>
> foo
>
> "def foo ; p [self, 2] ; end".evil_eval
>
> foo
>
> "def foo ; p [self, 3] ; end".de_inspect_unsafe
>
> foo
>
> "def foo ; p [self, 4] ; end".de_inspect # Will fail...
>
> foo
>



 
Reply With Quote
 
Michael Schilling
Guest
Posts: n/a
 
      02-08-2006
Hello everyone,

I'm fairly new to ruby and wanted to write a very simple cgi program,
which uploads a file and returns a converted file. Because it is so easy
(and I want to learn about ruby) I tried to do it with the standard
cgi.rb library. But I can't get the multipart_form (I need it for the
file upload) to work right. Everything works fine using the normal form
method, but with the multipart_form I always get an EOF Error 'no
content body' in the apache log. As soon as there is any input from an
multipart_form, an error occurs at: checkfile = CGI.new

Below you'll find my code (I boiled it down to the important stuff) and the
corresponding part of my apache2 error_log. I searched the web, several
mailing lists and the ruby docs, but couldn't find an answer. I also
asked on #ruby-lang in freenode, but no one there knew the cgi.rb
library very well.

Any help, on why this server error is happening, is very much
appreciated.

Bye,
Michael <-- who hopes, that this is the right list for the question



My code:
------------------------------------------------------------------
#!/usr/bin/ruby -w

require "cgi"

# make_form create a very simple html form
def make_form
make_form = CGI.new("html4")
make_form.out {
make_form.html {
make_form.body { "\n" +
# make_form.form{ "\n" + # everything works using the normal form
make_form.multipart_form{ "\n" + # but not with multipart_form to upload a file
make_form.file_field("filename",40,500000) + "\n" +
make_form.br +
make_form.submit("test it") + "\n"
}
}
}
}
end

# answer should show the filename of the uploaded file
def answer(file_in)

answer = CGI.new("html4")
answer.out {
answer.html {
answer.body{ "\n" +
answer.p{ "This should be the filename:" + file_in + "\n" } +
answer.br
}
}
}
end



begin
checkfile = CGI.new
parameter = checkfile['filename']
# parameter = checkfile.params['filename'][0] # this doesn't work either

rescue
answer("ERROR: " + $!.to_s) # send eror message to browser if possible
end


# create form if no data was send to the script, otherwise answer
if parameter == ""
make_form()
else
answer(parameter.to_s)
end
------------------------------------------------------------------


Apache log:
------------------------------------------------------------------
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] /usr/lib/ruby/1.8/cgi.rb:979:in `read_multipart', referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] : , referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] no content body, referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] (, referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] EOFError, referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] ), referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] \tfrom /usr/lib/ruby/1.8/cgi.rb:1104:in `initialize_query', referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] \tfrom /usr/lib/ruby/1.8/cgi.rb:2270:in `initialize', referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] \tfrom /home/httpd/cgi-bin/multiform-test.rb:25:in `answer', referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] \tfrom /home/httpd/cgi-bin/multiform-test.rb:52, referer: http://localhost/cgi-bin/multiform-test.rb
[Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] Premature end of script headers: multiform-test.rb, referer: http://localhost/cgi-bin/multiform-test.rb
------------------------------------------------------------------



--
Michael Schilling

eMail :
URL : http://glcu.sf.net/


"Change my name I remain the same." - Moloko


 
Reply With Quote
 
Erik Veenstra
Guest
Posts: n/a
 
      02-08-2006
On Wed, 08 Feb 2006 10:46:54 -0800, m4dc4p wrote:

> Could you elaborate a little more on what you are showing
> here?


I'm showing 3 ways of doing what you want to achieve, in
increasing order of safety. (Although the definitions of the
methods are in decreasing order of safety...) That' all.

> Specifically, why is it called "de_inspect_unsafe"


Because it's not as safe as "de_inspect". And I want to trigger
some alarm bells in case one want to use it...

> and what is the array in "p [self, 1]", "p [self, 2]" etc
> for?


If you don't get this, well, get any other string of Ruby code.
It's not important.

> I have also wondered about this issue myself and would like
> to see what people have done. I'd love to see why's "try
> ruby" code but that is probably a pipe dream ...


Just ask him...

gegroet,
Erik V. - http://www.erikveen.dds.nl/

 
Reply With Quote
 
konsu
Guest
Posts: n/a
 
      02-08-2006
hello,

try running your script from the command line. but set the url and method
environment variables first. on windows i do this:


set REQUEST_URI=/path
set REQUEST_METHOD=GET
ruby muscript.cgi .


this will allow you to avoid dealing with apache for a while, and will show
more errors too.

konstantin


"Michael Schilling" <> wrote in message
news:...
> Hello everyone,
>
> I'm fairly new to ruby and wanted to write a very simple cgi program,
> which uploads a file and returns a converted file. Because it is so easy
> (and I want to learn about ruby) I tried to do it with the standard
> cgi.rb library. But I can't get the multipart_form (I need it for the
> file upload) to work right. Everything works fine using the normal form
> method, but with the multipart_form I always get an EOF Error 'no
> content body' in the apache log. As soon as there is any input from an
> multipart_form, an error occurs at: checkfile = CGI.new
>
> Below you'll find my code (I boiled it down to the important stuff) and
> the
> corresponding part of my apache2 error_log. I searched the web, several
> mailing lists and the ruby docs, but couldn't find an answer. I also
> asked on #ruby-lang in freenode, but no one there knew the cgi.rb
> library very well.
>
> Any help, on why this server error is happening, is very much
> appreciated.
>
> Bye,
> Michael <-- who hopes, that this is the right list for the question
>
>
>
> My code:
> ------------------------------------------------------------------
> #!/usr/bin/ruby -w
>
> require "cgi"
>
> # make_form create a very simple html form
> def make_form
> make_form = CGI.new("html4")
> make_form.out {
> make_form.html {
> make_form.body { "\n" +
> # make_form.form{ "\n" + # everything works using the normal
> form
> make_form.multipart_form{ "\n" + # but not with multipart_form
> to upload a file
> make_form.file_field("filename",40,500000) + "\n" +
> make_form.br +
> make_form.submit("test it") + "\n"
> }
> }
> }
> }
> end
>
> # answer should show the filename of the uploaded file
> def answer(file_in)
>
> answer = CGI.new("html4")
> answer.out {
> answer.html {
> answer.body{ "\n" +
> answer.p{ "This should be the filename:" + file_in + "\n" } +
> answer.br
> }
> }
> }
> end
>
>
>
> begin
> checkfile = CGI.new
> parameter = checkfile['filename']
> # parameter = checkfile.params['filename'][0] # this doesn't work either
>
> rescue
> answer("ERROR: " + $!.to_s) # send eror message to browser if possible
> end
>
>
> # create form if no data was send to the script, otherwise answer
> if parameter == ""
> make_form()
> else
> answer(parameter.to_s)
> end
> ------------------------------------------------------------------
>
>
> Apache log:
> ------------------------------------------------------------------
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1]
> /usr/lib/ruby/1.8/cgi.rb:979:in `read_multipart', referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] : , referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] no content body,
> referer: http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] (, referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] EOFError, referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] ), referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] \tfrom
> /usr/lib/ruby/1.8/cgi.rb:1104:in `initialize_query', referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] \tfrom
> /usr/lib/ruby/1.8/cgi.rb:2270:in `initialize', referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] \tfrom
> /home/httpd/cgi-bin/multiform-test.rb:25:in `answer', referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] \tfrom
> /home/httpd/cgi-bin/multiform-test.rb:52, referer:
> http://localhost/cgi-bin/multiform-test.rb
> [Wed Feb 08 21:08:57 2006] [error] [client 191.168.1.1] Premature end of
> script headers: multiform-test.rb, referer:
> http://localhost/cgi-bin/multiform-test.rb
> ------------------------------------------------------------------
>
>
>
> --
> Michael Schilling
>
> eMail :
> URL : http://glcu.sf.net/
>
>
> "Change my name I remain the same." - Moloko
>
>



 
Reply With Quote
 
Bill Kelly
Guest
Posts: n/a
 
      02-08-2006
From: "konsu" <>
>
> i have been looking for a solution to almost the same problem. but have not
> found anything yet except for a solution that uses threads. just like this
> code. which i have doubts about because creating threads in a web
> application does not seem to scale too much.


time ruby -e '100000.times { Thread.new { }.join }'

real 0m1.130s
user 0m1.124s
sys 0m0.008s



Regards,

Bill




 
Reply With Quote
 
konsu
Guest
Posts: n/a
 
      02-08-2006
could you elaborate a bit? are these numbers good or bad? what about memory
consumption? may be i am missing something important about ruby threads, but
my impression was that spawning a thread on every request is bad.

konstantin


"Bill Kelly" <> wrote in message
news:08be01c62cf2$6bd84080$6442a8c0@musicbox...
> From: "konsu" <>
>>
>> i have been looking for a solution to almost the same problem. but have
>> not found anything yet except for a solution that uses threads. just like
>> this code. which i have doubts about because creating threads in a web
>> application does not seem to scale too much.

>
> time ruby -e '100000.times { Thread.new { }.join }'
>
> real 0m1.130s
> user 0m1.124s
> sys 0m0.008s
>
>
>
> Regards,
>
> Bill
>
>
>
>



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Reimporting modules, and sandboxing? Mark Lawrence Python 0 08-22-2012 08:13 AM
sandboxing python code Amit Sethi Python 0 06-03-2010 05:56 PM
Sandboxing a computation? Russell Wallace Java 20 09-21-2007 11:37 AM
Chroot Jail Not Secure for Sandboxing Python? gregpinero@gmail.com Python 16 07-03-2007 11:03 PM
Sandboxing librarys Dominik Werder Ruby 9 08-26-2004 08:48 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57