创建一个安全的 Lua 沙箱..?

use*_*868 1 lua sandbox roblox

现在我正在做很多事情。

local env = {
    print = print,
}
Run Code Online (Sandbox Code Playgroud)

setfenv(func, env),然后使用元方法来锁定实例上的属性,但它确实效率低下,并且有很多绕过。我用谷歌搜索了它,我发现的一切都与此相同:不起作用。

Nic*_*las 7

在 Lua 5.1 中,沙箱非常简单。如果某个文件中有一个 Lua 脚本,并且您想阻止它访问除您提供的参数之外的任何函数或任何内容,您可以这样做:

local script = --Load the script via whatever means. DO NOT RUN IT YET!
setfenv(script, {})
Run Code Online (Sandbox Code Playgroud)

script现在已沙盒化。除了您直接提供的值之外,它无法访问任何其他内容。它创建的函数无法访问此沙箱环境之外的任何内容。你原来的全球环境与它们完全隔绝,除非你允许它访问。

显然,您可以在该表中放置任何您喜欢的内容;该表将包含您喜欢的任何全局可访问的内容。你或许应该让 Lua 脚本访问基本的 Lua 标准库函数;其中大部分都是纯函数,不能做任何令人不快的事情。

如果你想保持沙箱的完整性,这里有一个 Lua 标准库内容的列表,你不能给用户访问这些内容:

  • getfenv。用户有充分的理由能够setfenv在您的沙箱中创建自己的迷你沙箱。但是,如果您想维护沙箱的完整性,则不能允许访问您放入沙箱中的任何函数的环境。
  • getmetatable:与上面的推理相同;设置元表就可以了。虽然恶意代码如果更改其元表就可以破坏对象,但恶意代码只需执行无限循环就可以破坏整个系统。
  • 整个图书馆 debug。通过调试库可以进行各种欺骗。

显然,您还需要解决Lua 5.1 从 Lua 脚本中加载字节码的问题。这可以用来破坏沙箱。不幸的是,Lua 5.1 并没有真正为此提供好的工具。在Lua 5.2+中,您可以封装load和loadfile,这样无论用户提供什么,您都可以在内部传递“t”作为模式参数。但对于 Lua 5.1,你需要一些方法来封装loadet.al。这样您就可以辨别数据何时是文本,何时不是。通过阅读 Lua 源代码,您可能会找到 Lua 用于区分字节码和文本的代码。

或者你可以完全禁止load和它的朋友。

如果你想阻止用户对系统做一些丑陋的事情,那么就禁止os和io库。

  • 除非您在操作系统级别设置时间限制,否则应该删除或限制的另一件事是对字符串库的模式匹配函数的访问(并记住字符串上的元表!)。(用于中止的 debug.sethook 没有帮助,您需要停止长时间运行的 C 函数。)示例: function Slow(i) return ("a"):rep(i):match((" a+"):rep(i-1)..'a') end` – `slow( 26 )` 在我的计算机上大约需要 1.5 秒,每增加一,时间就会增加一倍。(所以 `slow(64)` 已经运行了大约 13k 年……) (2认同)