2013-10-08 90 views
1

假設我想要一個由第三方提供的Lua表,而不是完全可靠的從一個文件或其他IO源提供的。消毒一個Lua表輸入

我得到的表作爲一個字符串,如「{[‘有效’] = 10}」我可以加載它作爲

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

但是,這將打開一個突破口代碼注入,即:txtTable = os.execute( '室射頻/')

所以我這樣做消毒功能:

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 

在它應該返回零的最壞情況。 這可以被認爲是安全的反對「經常惡意的人」:)

回答

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指出,在評論這不是一個完整的解決方案,以阻止惡意腳本。它基本上允許您列出爲用戶腳本批准的功能和表格。

有關處理惡意腳本的詳細信息,我建議這太問題: Embedded Lua - timing out rogue scripts (e.g. infinite loop) - an example anyone?

+0

這不會避免DOS類型的攻擊:嘗試'local script = [[local x = 1; for i = 1 ,1e100 do x = x + 1 end]]' –

1

我不認爲這是安全的。試試這個:

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

編輯

或此,更多的樂趣:

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

我不會建議更換的替代方案,os.getenvos.execute,雖然。 :-)

問題不容易解決。在這種情況下代碼注入避免並不簡單,因爲您在執行loadstring時正在執行一段Lua代碼。沒有簡單的字符串匹配技術真的很安全。唯一可靠的方法是爲Lua表語法的子集實現解析器,並在字符串上使用該解析器。

順便說一句,即使Lua團隊從Lua 5.2中剝離了字節碼驗證器,因爲他們發現它適合於攻擊,字節碼是比Lua源代碼更簡單的語言。

+0

如果(string.find(txtTable,「(」,1,真)) \t \t然後返回零年底 –

+0

但是這將阻止用戶把帶括號的字符串 - 你能想到一個簡單的解決方案的無等限制性? –

+0

我可以打碎它:print(safeLoadTable [[{foo = print「badcode」}]]) –

0

在沙箱中運行不安全,檢查源代碼是不是很簡單。一個想法:檢查字節碼!

Emmm,其實,這不是很簡單的兩種,但這裏是一個懶惰的實現:http://codepad.org/mGqQ0Y8q

+0

如果你想這樣,試試我的[bytecode inspector library](http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/) #lbci) – lhf

+0

我的不好,我完全忘了沒有必要重塑任何東西 – mpeterv

+0

沒問題,重新創造輪子很有趣。 – lhf

1

我創建sandbox.lua出於這樣的目的。假設您的環境可以訪問debug工具,它會處理不安全的東西以及DOS類型的攻擊。

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

注意,現在它是Lua的5.1兼容只。