如何实现“沙盒”函数?

我正在用 Lua 写一个沙盒。到目前为止,它一切正常,但我可以使用 getfenv 函数来获取沙盒外的作用域。对于我的沙盒,我用可信任的函数和库填充了一个空表。但是,对于像 print 这样的函数,您可以使用 getfenv 来获取该作用域中的全局变量。例如:

asd = "asd"
assert(pcall(assert(load([[
print(getfenv(print).asd) -- "asd"
]], nil, "t", {print = print, getfenv = getfenv}))))

这显然允许“对手”绕过沙盒。

点赞
用户7509065
用户7509065

你需要编写一个 getfenv 的包装器,以防止未经沙箱环境泄漏,就像 MediaWiki's Scribunto extension 那样:

    local function my_getfenv( func )
        local env
        if type( func ) == 'number' then
            if func <= 0 then
                error( "'getfenv'不能获取全局环境" )
            end
            env = old_getfenv( func + 1 )
        elseif type( func ) == 'function' then
            env = old_getfenv( func )
        else
            error( "'getfenv' 不能获取全局环境" )
        end

        if protectedEnvironments[env] then
            return nil
        else
            return env
        end
    end

其要点是检查返回的环境,如果它是受保护的环境(例如 _G),则拒绝返回它。唯一的技巧是处理参数,因为它根据其类型意义不同,并且对调用堆栈中的额外函数敏感。

2020-06-03 21:12:58