lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hello,

I have some questions regarding sandboxing in Lua 5.1.

Besides the functions tagged "SAFE" on the Wiki
(http://lua-users.org/wiki/SandBoxes), I would like to provide
sanitized versions of `get/setfenv`, `module`, `require` (no C libs),
and `load/dofile`.

The latter three are based on a safe, private `loadstring` version (no
bytecode, `setfenv(f,sandbox)`) and only have access to their own file
system root.

`require` and `module` work with `sandbox.package.loaded`, not the
global one a, and `sandbox.package.seeall` set `sandbox` as the index
of the module. The other package fields are not be exposed. (the code
is not shown here).

I also put guards around what get/setfenv can do, preventing _G and
its subfilelds to be get, and all functions whose environment are a _G
or a subfield to be the target of setfenv.

Am I covered?

```
local function each_in_tree (obj, fn, index,...)
  index = index or {}
  if index[obj] then return end
  index[obj]=true
  fn(obj,...)
  if type(obj)=="table" then
    for _,v in pairs( obj ) do
      treemap(v,fn,index,...)
    end
  end
end

local forbidden_env={}

each_in_tree(_G, function(t)
  if type (t) == "table" then
    forbidden_env[t]=true
  end
end )

--[[ A priori not needed
local forbidden_func={}

each_in_tree(_G, function(f)
  if type(f)=="function" then
    forbidden_func[f]=true
  end
end )
--]]

local sandbox={
  -- all safe fields
  table = {
    concat = table.concat,
    ...
  }
}


local _getfenv = getfenv
local _setfenv = setfenv
local _loadstring = loadstring
local _G = _G


setfenv(1,sandbox)

function sandbox.getfenv (...)
  local env = _getfenv(...)
  if forbidden_env[env]
  then return nil
  else return env
  end
end



function sandbox.setfenv (f,e)
  if forbiddent_env[_getfenv(f)]
  -- or forbidden_func[f] -- This should be covered by the above.
  -- or forbiden_env[e] -- It should be impossible to get a forbidden
environment.
  -- or f == 0 -- Safe too, I guess, since no dangerous env is available
  then return 0
  else return _setfenv(f,e)
  end
end


-- based on the "even this is not safe "version of the Wiki
local function safe_loadstring (s,chunkname)
  if s:match"^%.Lua" then
    return false, "Attempt to load bytecode." -- are there other
bytecode signatures?
  end
  local f, message = _loadstring(s, chunkname)
  if not f then
    return f, message
  end
  _setfenv(f, sandbox)
  return f
end

-- require and module implementations go here.

_setfenv(1,_G)
local f = loadfile"file"
setfenv(f,sandbox)
f()
```

-- Pierre-Yves