你 "sandbox" 如何运作?
How do you "sandbox" functions?
目前,我正在 Lua 中编写沙箱。到目前为止它一直在工作,但我可以使用 getfenv
来实现该功能以将范围置于沙箱之外。对于我的沙箱,我用受信任的函数和库填充了一个空的 table。但是,对于 print
等函数,您可以使用 getfenv
来获取该范围内的全局变量。例如:
asd = "asd"
assert(pcall(assert(load([[
print(getfenv(print).asd) -- "asd"
]], nil, "t", {print = print, getfenv = getfenv}))))
这显然可以让 "adversary" 绕过沙箱。
您需要为 getfenv
编写一个包装器,以防止泄漏非沙盒环境,就像 MediaWiki's Scribunto extension 所做的那样:
local function my_getfenv( func )
local env
if type( func ) == 'number' then
if func <= 0 then
error( "'getfenv' cannot get the global environment" )
end
env = old_getfenv( func + 1 )
elseif type( func ) == 'function' then
env = old_getfenv( func )
else
error( "'getfenv' cannot get the global environment" )
end
if protectedEnvironments[env] then
return nil
else
return env
end
end
其要点是检查returned 环境,如果它是受保护的环境(例如_G
),则拒绝return它。唯一的技巧是处理参数,因为它根据其类型表示不同的含义,并且它对调用堆栈中的额外函数很敏感。
目前,我正在 Lua 中编写沙箱。到目前为止它一直在工作,但我可以使用 getfenv
来实现该功能以将范围置于沙箱之外。对于我的沙箱,我用受信任的函数和库填充了一个空的 table。但是,对于 print
等函数,您可以使用 getfenv
来获取该范围内的全局变量。例如:
asd = "asd"
assert(pcall(assert(load([[
print(getfenv(print).asd) -- "asd"
]], nil, "t", {print = print, getfenv = getfenv}))))
这显然可以让 "adversary" 绕过沙箱。
您需要为 getfenv
编写一个包装器,以防止泄漏非沙盒环境,就像 MediaWiki's Scribunto extension 所做的那样:
local function my_getfenv( func )
local env
if type( func ) == 'number' then
if func <= 0 then
error( "'getfenv' cannot get the global environment" )
end
env = old_getfenv( func + 1 )
elseif type( func ) == 'function' then
env = old_getfenv( func )
else
error( "'getfenv' cannot get the global environment" )
end
if protectedEnvironments[env] then
return nil
else
return env
end
end
其要点是检查returned 环境,如果它是受保护的环境(例如_G
),则拒绝return它。唯一的技巧是处理参数,因为它根据其类型表示不同的含义,并且它对调用堆栈中的额外函数很敏感。