[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

code execution from file?

konsu

12/7/2005 11:33:00 PM

hello,

i have a text field in a database table (a text file, generally
speaking), with arbitrary Ruby code. i would like to execute this code
in my application's current environment. but i need to hide all my
variables except for some specific ones from this code.

so i was thinking to create a class with a static method that accepts
parameters and put the content of the file in to this method. and pass
the variables i want to expose as parameters.

how is this done in ruby? i have never done it.

in addition, how to execute this code with maximal security level?

also, what would happen if the code reopened classes that i have
created? is this possible? how to make it not do that?

basically i want the user to type some code in to my application and
run it but i want to protect against malicious users who want to erase
my hard disk, etc. ;-)

thanks for any help!
konstantin

10 Answers

konsu

12/7/2005 11:37:00 PM

0

please forgive the term "class with a static method", i meant "class
with a class method". my brain is still in this c++/java/c# rut.

Ara.T.Howard

12/8/2005 1:13:00 AM

0

konsu

12/8/2005 2:47:00 AM

0

thank you very much for your help.

my application runs inside a web browser process, and creating a thread
does not seem scalable.

i tried to evaluate a file from inside a lambda and it seems to work. i
also was able to set safety level for lambda locally which effectively
restores $SAFE when lambda finishes. the only drawback of this was that
my environment is still visible from lambdas.

code = <<CODE
v = MyClass.new('from text')
v.mymethod
CODE

class MyClass
def initialize(v) @v = v end
def mymethod() puts "SAFE=#{$SAFE}, value=#{@v}" end
end

p = eval <<LAMBDA
lambda {
module Mod
$SAFE = 3
#{code}
end
}
LAMBDA

v = MyClass.new('original')
v.mymethod
p.call
v.mymethod

rcoder@gmail.com

12/8/2005 3:03:00 AM

0

There are a number of mechanisms to "lock down" the execution for a
chunk of Ruby code, the most common being the built-in $SAFE global
variable. Unfortunately, due to a number of recently-published
vulnerabilities in the implementation of the $SAFE checks, it's
generally not considered a good way to insure that your application
will be protected from malignant users.

The best example I've seen to date of a truly safe Ruby interpreter has
to be why the lucky stiff's "Try Ruby" website
(http://tryruby....), which lets anyone interact with a
restricted IRb prompt via their browser and some slick Javascript. You
might email why_ directly, and see if he'd be willing to share some
tips with you (and the rest of us!).

At a bare minimum, you need to make sure the following built-in classes
and modules are either entirely hidden, or redefined to "safe"
versions:

Dir
File
FileStat
FileUtils
IO (at least methods like 'popen', 'fcntl', etc.)
ObjectSpace
Pathname
Process
GzipFile
Kernel ('fork', 'at_exit', 'caller', 'load', 'require', many more)

....and probaby others, as well. Really, it's a *hard* thing to make
arbitrary code execution safe, so unless you can re-use and share
effort with others, I'd caution you against doing this unless
absolutely necessary.

Good luck,

Lennon

Ara.T.Howard

12/8/2005 3:40:00 AM

0

konsu

12/8/2005 7:51:00 AM

0

putting aside security issues i think i was able to isolate my
environment and pass only desired variables in to the code. i create a
temporary module and evaluate my code in its context. then i remove
this module (that is why i needed the external module A, i could not
figure out how to remove a module otherwise). experts, does this look
feasible? i do not know though what to do to ensure security...

thanks
konstantin

module A
x = 'x'
y = 'y'

module T
class << self
def get_binding(p) binding end
end
end

# eval('puts x', T.get_binding(x)) -> # fails
puts eval('"variable #{p}"', T.get_binding(x))

remove_const :T

#puts eval('"variable #{p}"', T.get_binding(x)) -> # fails
end

Ara.T.Howard

12/8/2005 3:17:00 PM

0

konsu

12/8/2005 6:21:00 PM

0

i understand abouth threads. i think i am just researching the problem
so far. would you explain about Object?

i tried this:

module A
class Object
def mymethod(x) puts "#{x} in A" end
end

code = <<CODE
class Object; end
o = Object.new
#o.mymethod(p) # -> fails
class Object
def mymethod(x) puts "\#{x} in code" end
end
o = Object.new
o.mymethod(p)
CODE

x = 'x'
y = 'y'

module T
class << self
def get_binding(p) binding end
end
end

eval("#{code}", T.get_binding(y))

o = Object.new
o.mymethod(x)

remove_const :T
end

konsu

12/8/2005 6:33:00 PM

0

is there a way in ruby to set up a hook that would intercept calls to
any methods of a class?

vanekl

12/9/2005 1:14:00 PM

0