[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Sandboxing eval'd code

eastcoastcoder

2/8/2006 5:43:00 PM

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.... probably
does this, but source doesn't seem available.
http://approximity.com/cgi-bin/rubybuch_wiki/wpage... looks
relevant, but I can't figure it out.

In general, comments about this greatly appreciated.

17 Answers

Erik Veenstra

2/8/2006 6:19:00 PM

0

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

jgbailey

2/8/2006 6:47:00 PM

0

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

Erik Veenstra

2/8/2006 7:10:00 PM

0

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

konsu

2/8/2006 8:04:00 PM

0

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" <google@erikveen.dds.nl> wrote in message
news:1139422614.523641.62400@g14g2000cwa.googlegroups.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
>


Michael Schilling

2/8/2006 8:35:00 PM

0

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 : ruby@untiefe.de
URL : http://gl...


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


Erik Veenstra

2/8/2006 8:44:00 PM

0

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.erikve...

konsu

2/8/2006 8:57:00 PM

0

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" <ruby@untiefe.de> wrote in message
news:20060208203511.GA16112@calvin.physik.uni-bielefeld.de...
> 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 : ruby@untiefe.de
> URL : http://gl...
>
>
> "Change my name I remain the same." - Moloko
>
>


Bill Kelly

2/8/2006 8:59:00 PM

0

From: "konsu" <konsu@hotmail.com>
>
> 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




konsu

2/8/2006 9:06:00 PM

0

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" <billk@cts.com> wrote in message
news:08be01c62cf2$6bd84080$6442a8c0@musicbox...
> From: "konsu" <konsu@hotmail.com>
>>
>> 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
>
>
>
>


Michael Schilling

2/8/2006 9:36:00 PM

0

Hi,

thank you for the suggestions. I set the variables as you suggested
(with export REQUEST_URI=/path in Linux) but always only get the form. I
don't exactly know how a string from the multipart_form looks like, so
I couldn't really test the behaviour.

When I use the normal form method, and do not set the variables as you
suggested, I get the expected result and no error from
'myscript.rb filename=something'. With the multipart_form I also get no
error, but also no output -> only the form.

I also thought, that this problem might be a misconfiguration of apache,
but a guy on #ruby-lang told me, that it is very unlikely when the
normal form method works fine.

So I can't reproduce the error without using the browser, but don't get
the expected result either.


Thanks for any help.


Bye, Michael




konsu wrote on thursday the 9th of February 2006:

> 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" <ruby@untiefe.de> wrote in message
> news:20060208203511.GA16112@calvin.physik.uni-bielefeld.de...
> > 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 : ruby@untiefe.de
> > URL : http://gl...
> >
> >
> > "Change my name I remain the same." - Moloko
> >
> >