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.