我有一个案例,当来自 DB 字段的文本应该在沙盒模式下“评估”时 - 使用方法和常量的白名单,允许调用。
gem https://github.com/tario/shikashi非常适合这个,但在我看来,它被遗弃了。
我什至不能运行 Basic Example 2
(只有 Basic Example 1
可以正常工作):
require "rubygems"
require "shikashi"
include Shikashi
def foo
# privileged code, can do any operation
print "foo\n"
end
s = Sandbox.new
priv = Privileges.new
# allow execution of foo in this object
priv.object(self).allow :foo
# allow execution of method :times on instances of Fixnum
priv.instances_of(Fixnum).allow :times
#inside the sandbox, only can use method foo on main and method times on instances of Fixnum
s.run(priv, "2.times do foo end")
因为它失败并出现错误 Cannot invoke method foo on object of class Object (SecurityError)
这个 gem 使用另一个 gem evalhook
来解决这个问题,它看起来很复杂。还有另一个像这个这样的 gem ,但它们被遗弃得更多。
据我所知,使用 $SAFE
并不是一个好主意,因为它存在漏洞。
是否有其他方法可以实现此类功能?也许使用 Binding
对象进行操作?
最佳答案
我的问题在没有任何 gem 的情况下并不难解决。这个想法是你有方法和常量的白名单 WHITELIST
并且这个类检查,如果所有的方法和常量都在白名单中
# gem install 'parser'
require 'parser/current'
class CodeValidator
attr_reader :errors, :source
WHITELIST = {:send => [:puts, :+, :new], :const => [:String]}
class Parser::AST::Node
def value
return children[1] if [:send, :const].include? type
fail NotImplementedError
end
end
def initialize(source)
@errors = []
@source = source
end
def valid?
!insecure_node?(root_node)
end
private
def exclude_node?(node)
blacklisted_node_types.include?(node.type) && !WHITELIST[node.type].include?(node.value)
end
def blacklisted_node_types
WHITELIST.keys
end
def insecure_node?(node)
return !!add_error_for_node(node) if exclude_node?(node)
node.children.each { |child_node| return true if child_node.class == Parser::AST::Node && insecure_node?(child_node) }
false
end
def root_node
@root_node ||= Parser::CurrentRuby.parse source
end
def add_error_for_node(node)
errors << "#{node.type} not allowed: #{node.value}"
end
end
c = CodeValidator.new("s = 'hello ' + String.new('world'); puts s.inspect")
p c.valid? # => false
p c.errors # => ["send not allowed: inspect"]
关于ruby-on-rails - Ruby\Rails 沙箱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32054127/