Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Help with sandboxing getfenv()?

Asked by
LuaQuest 450 Moderation Voter
8 years ago

So i'm trying to improve my sandbox a little bit at a time, and i think the first thing i need to fix is getfenv(). So, here's my "sandbox" so far:

function saferun(func)
    setfenv(func,setmetatable({},{
        __index = function(t,k)
            if k == 'getfenv' then -- if getfenv is indexed, then...
                return -- don't know yet
            else
                return getfenv()[k] -- if not, just return it from the old environment.
            end
        end
    }))() -- run the function
end

saferun(function()
    print(getfenv) -- > nil
end)

However, i don't want to just disable the ability to use getfenv, it's just so easy to bypass the sandbox with it. For example, if i said something like:

var = 'protected'

function saferun(func)
    setfenv(func,setmetatable({},{
        __index = function(t,k)
            if k == 'var' then -- blocking "var" instead of getfenv
                return 'blocked'
            else
                return getfenv()[k]
            end
        end
    }))() -- run the function
end

saferun(function()

    print(var)  -- > "blocked"

    -- But using getfenv, i can easily bypass the sandbox like this:

    setfenv(1,getfenv(print))

    print(var) -- > "protected"

end)

So, i know the problem is with getfenv, i just have no idea how i could attempt to modify it. I've tried a few ways, none in which where close to succeeding:

var = 'nope'

function saferun(func)
    setfenv(func,setmetatable({},{
        __index = function(t,k)
            if k == 'getfenv' then
                return function(f) -- returns this function instead of getfenv
                    local env = {}
                    for i,v in pairs (getfenv(f)) do
                        env[i]=v
                    end
                    return env
                end
            elseif k == 'var' then
                return 'blocked'
            else
                return getfenv()[k]
            end
        end
    }))() -- run the function
end

saferun(function()
    setfenv(1,getfenv(print)) -- bypass
    print(var) -- prints "nope" instead of "blocked".
end)

So if anyone has some insight on how it would be possible to modify getfenv, or maybe even another way of preventing this, i'd really appreciate it. Thanks.

Answer this question