所以Lua似乎是在我的应用程序中实现安全"用户脚本"的理想选择.
但是,嵌入lua的大多数示例似乎都包括加载所有标准库,包括"io"和"package".
所以我可以从我的解释器中排除这些库,但即使是基本库也包含访问文件系统的函数"dofile"和"loadfile".
如何删除/阻止这些不安全的函数,而不仅仅是一个甚至没有像"ipairs"函数这样的基本内容的解释器?
您可以通过setfenv()设置运行不受信任代码的功能环境.这是一个大纲:
local env = {ipairs} setfenv(user_script, env) pcall(user_script)
该user_script
功能只能访问其环境中的内容.因此,您可以显式添加您希望不受信任的代码可以访问的功能(白名单).在这种情况下,用户脚本只能访问ipairs
,但没有别的(dofile
,loadfile
,等).
有关lua沙盒的详细信息,请参阅Lua Sandboxes.
这是Lua 5.2的解决方案(包括也适用于5.1的示例环境):
-- save a pointer to globals that would be unreachable in sandbox local e=_ENV -- sample sandbox environment sandbox_env = { ipairs = ipairs, next = next, pairs = pairs, pcall = pcall, tonumber = tonumber, tostring = tostring, type = type, unpack = unpack, coroutine = { create = coroutine.create, resume = coroutine.resume, running = coroutine.running, status = coroutine.status, wrap = coroutine.wrap }, string = { byte = string.byte, char = string.char, find = string.find, format = string.format, gmatch = string.gmatch, gsub = string.gsub, len = string.len, lower = string.lower, match = string.match, rep = string.rep, reverse = string.reverse, sub = string.sub, upper = string.upper }, table = { insert = table.insert, maxn = table.maxn, remove = table.remove, sort = table.sort }, math = { abs = math.abs, acos = math.acos, asin = math.asin, atan = math.atan, atan2 = math.atan2, ceil = math.ceil, cos = math.cos, cosh = math.cosh, deg = math.deg, exp = math.exp, floor = math.floor, fmod = math.fmod, frexp = math.frexp, huge = math.huge, ldexp = math.ldexp, log = math.log, log10 = math.log10, max = math.max, min = math.min, modf = math.modf, pi = math.pi, pow = math.pow, rad = math.rad, random = math.random, sin = math.sin, sinh = math.sinh, sqrt = math.sqrt, tan = math.tan, tanh = math.tanh }, os = { clock = os.clock, difftime = os.difftime, time = os.time }, } function run_sandbox(sb_env, sb_func, ...) local sb_orig_env=_ENV if (not sb_func) then return nil end _ENV=sb_env local sb_ret={e.pcall(sb_func, ...)} _ENV=sb_orig_env return e.table.unpack(sb_ret) end
然后使用它,你会my_func
像下面这样调用你的函数():
pcall_rc, result_or_err_msg = run_sandbox(sandbox_env, my_func, arg1, arg2)
该Lua的现场演示中含有(专业)沙箱.所述源是免费提供的.
清除不良情况的最简单方法之一是首先加载您自己设计的Lua脚本,该脚本执行以下操作:
load = nil loadfile = nil dofile = nil
或者,您可以setfenv
用来创建一个受限的环境,可以在其中插入特定的安全功能。
完全安全的沙箱有点难。如果您从任何地方加载代码,请注意,预编译的代码可能会使Lua崩溃。如果没有关闭系统,甚至完全受限制的代码也可能陷入无限循环并无限期地阻塞。