`Debug.setlocal()` 安全问题

debug.setlocal() 是否存在安全问题?如果有,请告诉我它是如何工作的。

点赞
用户12110258
用户12110258

Lua线程在“堆栈”上运行,这是支持该语言的大部分内存的列表。从“全局”变量到表,所有东西都坐在这个列表上。

当你创建一个本地变量并执行你的代码时,堆栈将看起来像这样:

local a = "the letter a"
STACK
+---+----------------+
| 1 | "the letter a" |
+---+----------------+

现在,假设我们是恶意代码。我们知道以下代码用于运行我们的程序:

local isAdministrator = false
local Code = "malicious code here!"
loadstring(Code)()

嗯,这意味着loader的堆栈看起来像这样:

+---+-------+
| 1 | false | isAdministrator
+---+-------+----------------+
| 2 | "malicious code here!" | Code
+---+---------------------+--+
| 3 | function loadstring |
+---+---------------------+--+
| 4 | function MaliciousCode |
+---+------------------------+

现在,假设更改isAdministrator对我们有一定的价值。让我们看看我们如何做到这一点。

1我们需要让lua修改我们函数上面的“堆栈”。想象一下,lua是一棵树,像这样:

otherScript
 + loader
    + maliciousCode

这个树中的每一步都有自己的堆栈,并且来自它上面的堆栈的每个变量都可以通过“调试”库访问到下面的堆栈。

如果我们当前所在的“堆栈”是#1(这总是正确的) 那么调用当前函数的函数就在#2的堆栈上(这几乎总是正确的)

现在,查看我们想要更改的函数的堆栈,isAdministrator在第一个槽中,即第一个。所以,为了改变这个,我们只需要:

debug.setlocal(2,1,true)

就这样。isAdministrator现在是“真的”了。我们有自由毁坏你的计算机!

别担心-有一种方法可以阻止这种情况。取走调试库非常容易:

local func = loadstring("malicious code!")
setfenv(func, {
    -- 在这里,我们插入我们的宝贝函数可以使用的函数。让我们提供字符串、表和数学库-这些都相当安全。
    math = math, table = table, string = string,
    -- 呃,让我们也给它`os.time`函数。
    os = { time = os.time }
})
func()

现在,函数就无法访问调试库,而您可以自由地在您的愚蠢的“isAdministrator”本地计算机上使用。

2020-12-28 00:43:34