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

Posted

技术标签:

【中文标题】创建一个安全的 Lua 沙箱..?【英文标题】:Creating a secure Lua sandbox..? 【发布时间】:2016-03-27 02:11:01 【问题描述】:

现在我正在做很多事情。

local env = 
    print = print,

setfenv(函数,环境) 然后使用元方法来锁定Instances上的属性,但它确实效率低下并且有很多绕过。我用谷歌搜索了它,我发现的一切都与此相同:无法正常工作。

【问题讨论】:

您指的是什么“绕过”?沙盒意味着脚本只能访问您明确允许的内容。鉴于您显示的代码,func 将只能访问 print 以及您调用它时使用的任何参数。 “假设我也想授予对 getfenv() 的访问权限。”如果你不希望人们走进你的家,你就不要给他们钥匙。这里也是如此:如果您不希望人们突破沙盒,不要给他们这样做的工具。所以任何好的沙盒都会阻止你使用getfenv @Nicol 但更好的沙箱将允许沙箱化访问任何东西。当我想到沙盒时,我认为它就像是我自己的微型世界,在那里我可以安全地做事,而无需访问“父环境”。例如 getfenv(2) 会出错,因为“父环境”不存在。 (确实如此,但这不应该从沙箱内部看到。) 所以我认为对你的比喻的改进是如果你不希望人们走进你的家,不要告诉他们它在哪里。 我不用担心字节码; ROBLOX 已将其删除。 【参考方案1】:

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

local script = --Load the script via whatever means. DO NOT RUN IT YET!
setfenv(script, )

script 现在被沙盒化了。它不能访问您直接提供的值以外的任何内容。它创建的函数无法访问此沙盒环境之外的任何内容。您原来的全局环境与它们完全隔绝,除了您允许它访问的内容。

显然你可以在那个桌子上放任何你喜欢的东西;该表将包含您喜欢的任何全球可访问的东西。您可能应该让 Lua 脚本访问基本的 Lua 标准库函数;其中大部分是纯函数,不会做任何不愉快的事情。

如果您想保持沙箱的完整性,以下是您不得授予用户访问权限的 Lua 标准库内容列表:

getfenv。用户有正当理由可以setfenv,以便它可以在您的沙箱中创建自己的迷你沙箱。但是,如果您想维护沙盒的完整性,则不能允许访问您放入沙盒中的任何函数的环境。 getmetatable:同上推理;设置元表是可以的。虽然恶意代码可以通过更改元表来破坏对象,但恶意代码可以通过执行无限循环来破坏整个系统。 整个 debug 库。通过调试库,各种诡计都是可能的。

您显然还需要解决this problem that Lua 5.1 has with loading bytecode from within a Lua script。这可以用来打破沙盒。不幸的是,Lua 5.1 并没有很好的工具。在 Lua 5.2+ 中,您可以封装loadloadfile,这样无论用户提供什么,您都可以在内部传递“t”作为模式参数。但是在 Lua 5.1 中,你需要一些方法来封装 load et.al。这样您就可以分辨出数据何时是文本,何时不是。通过阅读 Lua 源代码,您可能会找到 Lua 用来区分字节码和文本的代码。

或者您可以完全禁止 load 及其朋友。

如果您想阻止用户对系统做丑陋的事情,请禁用 osio 库。

【讨论】:

我可能值得一提的是,在“不得授予访问权限”部分禁用loadstring 或至少使用loadstring 加载字节码:gist.github.com/corsix/6575486 @PaulKulchenko:感谢您的来信。我假设 LuaJIT 没有这个特定问题,因为使用了不同的字节码格式(尽管可能使用 LuaJIT 字节码来破坏沙箱)。 @NicolBolas 你的意思是这样吗? corsix.org/content/malicious-luajit-bytecode ;-) 没有加载库。 (除了 jit(用于 jit 编译),但它没有在代码中引用/使用。)对于任何类型的沙箱,请确保避免所有字节码加载。 除非您在操作系统级别设置时间限制,否则应该删除或限制的另一件事是访问字符串库的模式匹配函数(并记住字符串上的元表!)。 (debug.sethook for abort 无济于事,您需要停止长时间运行的 C 函数。)示例:function slow(i) return ("a"):rep(i):match(("a+"):rep(i-1)..'a') endslow( 26 ) 在我的计算机上大约需要 1.5 秒,每增加一倍时间就会加倍。 (所以slow(64) 已经运行了大约 13k 年……) getmetatable 可以暴露给沙箱,只要您不希望沙箱代码有权访问的元表具有非零 __metatable 字段。

以上是关于创建一个安全的 Lua 沙箱..?的主要内容,如果未能解决你的问题,请参考以下文章

错误 Paypal 沙箱:请求被中止:无法创建 SSL/TLS 安全通道

Android安全沙箱

Java沙箱安全机制介绍

在HDP KYLO沙箱中实现Kylo安全性?

JVM进阶之沙箱安全模型

JVM进阶之沙箱安全模型