Eval in ruby​​有安全的方法吗?或者更好的方法吗?

时间:2014-05-27 08:27:55

标签: ruby-on-rails ruby eval code-injection

当用户使用我的应用程序时,他们会在某一时刻得到一个数组数组,如下所示:

results = [["value",25], ["value2",30]...]

子阵列可能更大,并且将采用类似的格式。我想允许我的用户编写自己的自定义转换函数,它将获取一个数组数组,并返回一个数组,一个字符串或一个数字。函数应如下所示:

def user_transform_function(array_of_arrays)
  # eval users code, only let them touch the array of arrays
end 

是否有一种安全的方法来沙箱此功能和eval,以便用户无法尝试执行恶意代码?例如,没有Web标注,没有数据库标注等等。

2 个答案:

答案 0 :(得分:2)

首先,如果您使用eval,它将永远不会安全。您至少可以查看taint方法的方向。

我建议为此创建自己的DSL。 Ruby中有一个很棒的框架:http://treetop.rubyforge.org/index.html。当然,它需要您的一些努力,但从用户的角度来看,我认为它可能会更好。

答案 1 :(得分:1)

警告:我无法保证这是真正安全的!

您可以将它作为一个单独的进程运行并使用ruby $SAFE,但这并不能保证您获得的是安全的,但这会让事情变得更加困难。

你接下来会做的是这样的事情:

script = "arr.map{|e| e+2}" #from the user.
require "json"

array = [1, 2, 3, 4]
begin
    results = IO.popen("ruby -e 'require \"json\"; $SAFE=3; arr = JSON.parse(ARGV[0]); puts (#{script}).to_json' #{array.to_json}") do |io|
        io.read
    end 
rescue Exception => e
    puts "Ohh, good Sir/Mam, your script caused an error."
end

if results.include?("Insecure operation")
    puts "Ohh, good Sir/Mam, you cannot do such a thing"
else
    begin
        a = JSON.parse(results)
        results = a
    rescue Exception => e
        puts "Ohh, good Sir/Mam, something is wrong with the results."
        puts results
    end
end

       conquer_the_world(results) if     results.is_a?(Array)
do_not_conquer_the_world(results) unless results.is_a?(Array)

你可以这样做,它出现了:

def evaluate_user_script(script)
  Thread.start {
    $SAFE = 4
    eval(script)
  }    
end

但是又一次:我不知道如何从那里获取数据。