lua: sandbox: relax the sandbox to allow more functionality in scripts

This enables the debug and coroutine libraries and some more functions
that are not really so risky to have around

Related to #121
This commit is contained in:
George Kiagiadakis
2022-04-06 18:05:26 +03:00
parent 9387ce0d95
commit 031bc65c20
2 changed files with 43 additions and 70 deletions

View File

@@ -11,72 +11,51 @@
local SANDBOX_CONFIG = ...
local SANDBOX_ENV = {}
local function populate_env(id)
local module, method = id:match('([^%.]+)%.([^%.]+)')
if module then
SANDBOX_ENV[module] = SANDBOX_ENV[module] or {}
SANDBOX_ENV[module][method] = _G[module][method]
else
SANDBOX_ENV[id] = _G[id]
function create_sandbox_env()
local function populate_env(id)
local module, method = id:match('([^%.]+)%.([^%.]+)')
if module then
SANDBOX_ENV[module] = SANDBOX_ENV[module] or {}
SANDBOX_ENV[module][method] = _G[module][method]
else
SANDBOX_ENV[id] = _G[id]
end
end
end
-- List of safe functions and packages
if SANDBOX_CONFIG["minimal_std"] then
-- minimal list, used for config files
([[
_VERSION ipairs pairs select tonumber tostring type
if not SANDBOX_ENV._VERSION then
-- List of exported functions and packages
([[ _VERSION assert error ipairs next pairs tonumber
pcall select print tostring type xpcall require
table string math package utf8 debug coroutine
os.clock os.difftime os.time os.date os.getenv
]]):gsub('%S+', populate_env)
table
string.byte string.char string.find string.format string.gmatch
string.gsub string.len string.lower string.match string.reverse
string.sub string.upper
]]):gsub('%S+', populate_env)
else
-- full list, used for scripts
([[
_VERSION assert error ipairs next pairs print
pcall select tonumber tostring type xpcall require
table utf8
math.abs math.acos math.asin math.atan math.ceil
math.cos math.deg math.exp math.tointeger math.floor math.fmod
math.huge math.ult math.log math.maxinteger math.mininteger math.max
math.min math.modf math.pi math.rad math.random
math.sin math.sqrt math.tan math.type
string.byte string.char string.find string.format string.gmatch
string.gsub string.len string.lower string.match string.reverse
string.sub string.upper
os.clock os.difftime os.time os.date os.getenv
]]):gsub('%S+', populate_env)
end
-- Additionally export everything in SANDBOX_EXPORT
if type(SANDBOX_EXPORT) == "table" then
for k, v in pairs(SANDBOX_EXPORT) do
SANDBOX_ENV[k] = v
end
end
-- Additionally protect packages from malicious scripts trying to override methods
for k, v in pairs(SANDBOX_ENV) do
if type(v) == "table" then
SANDBOX_ENV[k] = setmetatable({}, {
__index = v,
__newindex = function(_, attr_name, _)
error('Can not modify ' .. k .. '.' .. attr_name .. '. Protected by the sandbox.')
-- Additionally export everything in SANDBOX_EXPORT
if type(SANDBOX_EXPORT) == "table" then
for k, v in pairs(SANDBOX_EXPORT) do
SANDBOX_ENV[k] = v
end
})
end
end
end
populate_env("package")
-- Additionally protect packages from malicious scripts trying to override methods
for k, v in pairs(SANDBOX_ENV) do
if type(v) == "table" then
SANDBOX_ENV[k] = setmetatable({}, {
__index = v,
__newindex = function(_, attr_name, _)
error('Can not modify ' .. k .. '.' .. attr_name .. '. Protected by the sandbox.')
end
})
end
end
end
-- chunk's environment will be an empty table with __index
-- to access our SANDBOX_ENV (without being able to write it)
return setmetatable({}, {
__index = SANDBOX_ENV,
})
end
if SANDBOX_CONFIG["isolate_env"] then
-- in isolate_env mode, use a separate enviornment for each loaded chunk and
@@ -84,11 +63,7 @@ if SANDBOX_CONFIG["isolate_env"] then
SANDBOX_ENV_LIST = {}
function sandbox(chunk, ...)
-- chunk's environment will be an empty table with __index
-- to access our SANDBOX_ENV (without being able to write it)
local env = setmetatable({}, {
__index = SANDBOX_ENV,
})
local env = create_sandbox_env()
-- store the chunk's environment so that it is not garbage collected
table.insert(SANDBOX_ENV_LIST, env)
-- set it as the chunk's 1st upvalue (__ENV)
@@ -100,9 +75,7 @@ else
-- in common_env mode, use the same environment for all loaded chunks
-- chunk's environment will be an empty table with __index
-- to access our SANDBOX_ENV (without being able to write it)
SANDBOX_COMMON_ENV = setmetatable({}, {
__index = SANDBOX_ENV,
})
SANDBOX_COMMON_ENV = create_sandbox_env()
function sandbox(chunk, ...)
-- set it as the chunk's 1st upvalue (__ENV)

View File

@@ -24,7 +24,7 @@ _wplua_openlibs (lua_State *L)
static const luaL_Reg loadedlibs[] = {
{"_G", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
/* {LUA_COLIBNAME, luaopen_coroutine}, */
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
/* {LUA_IOLIBNAME, luaopen_io}, */
{LUA_OSLIBNAME, luaopen_os},