沙盒

lua-users home
wiki

此页面在示例中使用 setfenv,setfenv 在 Lua 5.2 及更高版本中不再可用,因此需要更新。如果您使用 Lua 5.2,请勿使用此代码。我本来想自己更新,但我没有沙盒方面的经验。

此页面讨论与沙盒相关的议题:在受限的 Lua 环境中运行不受信任的 Lua 代码。

警告!

沙盒很棘手,一般来说很难做好 [3]。您应该从不信任任何东西开始,只允许您绝对确信安全的项目(即白名单而不是黑名单方法)。在没有深入了解语言和实现的情况下,很难确定某些代码是安全的(例如,哈希表性能在极少数情况下可能表现不佳 [4])。Lua 实现中也可能存在错误(参见 [bugs]),因此您应该监控邮件列表上的错误报告,并在发生此类漏洞时可能采取额外的隔离措施,例如操作系统级别的隔离机制(如受限用户帐户或 [chroot 监狱])。您还应该通过防火墙等方式保持操作系统修补和安全。可能还需要操作系统级别的资源限制 [5]。限制 Lua 语言的子集可以缓解其中一些问题。

LibrariesAndBindings 的“沙盒”章节中查看一些库。

以下说明可能不完整,仅作为起点。

一个简单的沙盒

以下是最简单的沙盒之一。它也是最严格的沙盒之一,除了它不处理资源耗尽问题。

-- make environment
local env = {} -- add functions you know are safe here

-- run code under environment [Lua 5.1]
local function run(untrusted_code)
  if untrusted_code:byte(1) == 27 then return nil, "binary bytecode prohibited" end
  local untrusted_function, message = loadstring(untrusted_code)
  if not untrusted_function then return nil, message end
  setfenv(untrusted_function, env)
  return pcall(untrusted_function)
end

-- run code under environment [Lua 5.2]
local function run(untrusted_code)
  local untrusted_function, message = load(untrusted_code, nil, 't', env)
  if not untrusted_function then return nil, message end
  return pcall(untrusted_function)
end

-- test
assert(not run [[print(debug.getinfo(1))]]) --> fails
assert(run [[x=1]]) --> ok
assert(run [[while 1 do end]]) --> ok (but never returns)

此沙盒中的代码可以在沙盒环境中创建变量,创建原始类型的值(从而分配内存),并执行计算。内存使用和计算没有限制,因此不受信任的代码仍然可能严重影响系统性能,除非进行进一步的限制。沙盒无法访问 I/O 以及其环境之外的函数和变量。沙盒与外部世界通信的唯一方式是影响其环境(例如,获取和设置环境中的变量以及调用该环境中的函数),假设沙盒外部的代码也能够访问这些变量和函数。

您可以编写一个解析器,它接受 Lua 语言的子集(例如,防止循环),但这可能仍然不足以完全防止 CPU 耗尽。

变量表

以下是 Lua 5.1 变量列表,以及它们在沙箱环境中使用的安全性描述。请注意,变量是否安全可能**取决于您的特定应用程序的安全要求**和您的 Lua 状态。以下列表不保证完整或正确,仅供参考。要创建沙箱,您应该从一个空环境开始,只引入您确定安全的函数 [1](即白名单而不是黑名单)。您不应该依赖手册提供完整的函数列表(例如 HiddenFeatures)。

注意:以下列表尚未更新到 Lua 5.2。

local oldloadstring = loadstring
local function safeloadstring(s, chunkname)
  local f, message = oldloadstring(s, chunkname)
  if not f then
    return f, message
  end
  setfenv(f, getfenv(2))
  return f
end
也不安全。例如,pcall(safeloadstring, some_script) 将在全局环境中加载 some_script。--SergeyRozhenko

--DavidManura

旧评论

匿名:要考虑的攻击

参见


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2023 年 12 月 12 日下午 6:04 GMT (差异)