1

假设我想要一个由第三方提供的 Lua 表,但不完全可靠,来自文件或其他 IO 源。

我将表格作为字符串获取,例如“{['valid'] = 10}”,我可以将其加载为

externalTable = loadstring("return " .. txtTable)()

但这会破坏代码注入,即:txtTable = os.execute('rm -rf /')

所以我做了这个消毒功能:

function safeLoadTable(txtTable)
    txtTable = tostring(txtTable)
    if (string.find(txtTable, "(", 1, true)) 
        then return nil end
    local _start = string.find(txtTable, "{", 1, true)
    local _end = string.find(string.reverse(txtTable), "}", 1, true)
    if (_start == nil or _end == nil)
        then return nil end
    txtTable = string.sub(txtTable, _start,  #txtTable - _end + 1)
    print("cropped to ", txtTable)
    local pFunc = loadstring("return " .. txtTable)
    if (pFunc) then
        local _, aTable = pcall(pFunc)
        return aTable
    end
end

在最坏的情况下,它应该返回 nil。这可以被认为对“普通的坏人”是安全的吗:)

4

4 回答 4

1

我不认为这是安全的。试试这个:

print(safeLoadTable [[{ foo = (function() print"yahoo" end)() } ]])

编辑

或者这个,为了更有趣:

print(safeLoadTable [[{ foo = (function() print(os.getenv "PATH") end)() } ]])

os.getenv不过,我不会建议将其替换为os.execute. :-)

这个问题不容易解决。在这种情况下,避免代码注入一点也不简单,因为这样做时您正在执行一段 Lua 代码loadstring。没有简单的字符串匹配技术是真正安全的。唯一安全的方法是为 Lua 表语法的子集实现解析器,并在字符串上使用该解析器。

顺便说一句,甚至 Lua 团队也从 Lua 5.2 中剥离了字节码验证器,因为他们发现它容易受到攻击,而且字节码是一种比 Lua 源代码简单得多的语言。

于 2013-10-08T21:40:51.807 回答
1

您可以在沙箱中运行不安全的代码。

以下是 Lua 5.1 中简单沙箱的外观(为简洁起见,省略了错误处理):

local script = [[os.execute("rm -rf /")]]
local env = { print=print, table=table, string=string }
local f, err = loadstring(script)
if err then
   -- handle syntax error
end
setfenv(f, env)
local status, err = pcall(f)
if not status then
   -- handle runtime error
end

在 Lua 5.2 中,您可以使用该函数将脚本加载到它自己的环境中load

结果将是从以下位置返回的运行时错误pcall

attempt to index global 'os' (a nil value)

编辑

正如Lorenzo Donati在评论中指出的那样,这不是阻止流氓脚本的完整解决方案。它本质上允许您将批准用于用户脚本的函数和表列入白名单。

有关处理流氓脚本的更多信息,我会建议这个 SO 问题: 嵌入式 Lua - 超时流氓脚本(例如无限循环) - 任何人的例子?

于 2013-10-08T21:52:18.417 回答
1

我正是为此目的创建了 sandbox.lua。debug假设您的环境可以访问该设施,它将处理不安全的东西以及 DOS 类型的攻击。

https://github.com/kikito/sandbox.lua

请注意,目前它仅与 Lua 5.1 兼容。

于 2013-10-10T18:46:08.073 回答
0

在沙箱中运行并不安全,检查源代码也不是很简单。一个想法:检查字节码!

Emmm,其实这也不是很简单,但这里是一个懒惰的实现:http ://codepad.org/mGqQ0Y8q

于 2013-10-09T16:32:16.983 回答