0

目前,我正在用 Lua 编写一个沙箱。到目前为止它正在工作,但我可以使用getfenv该功能来获取沙箱之外的范围。对于我的沙盒,我用可信函数和库填充了一个空表。但是,使用诸如 之类的函数print,您可以使用它getfenv来获取该范围内的全局变量。例如:

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

这显然可以让“对手”绕过沙箱。

4

1 回答 1

1

您需要编写一个包装器来getfenv防止泄漏未沙盒环境,就像MediaWiki 的 Scribunto 扩展一样:

    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

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

于 2020-06-03T21:12:58.797 回答