沙盒

lua-users home
wiki

此頁面在範例中使用 setfenv,但 setfenv 在 Lua 5.2 中已不再可用因此需要更新。如果您使用 Lua 5.2 請勿使用此程式碼,我原本想要親自更新,但對於沙盒我沒有任何經驗。

此頁面會針對沙盒議題進行討論:在受限的 Lua 環境中執行不可信任的 Lua 程式碼。

警告!!!

沙盒很棘手,而且一般來說很難做對 [3]。您一開始不應該信任任何事物,只允許您絕對確定安全的事物(例如白名單而非黑名單的做法)。如果對於語言和實作沒有深入了解,便很難確保某段程式碼是安全的(例如哈希表效能可能在少數狀況下出現不佳效能 [4])。Lua 實作中也可能存在錯誤(請參閱 [bugs]),因此您應該監控郵件清單中的錯誤報告,若發生這類漏洞,可能需要採取進一步的隔離措施,例如作業系統等級的隔離機制(例如受限使用者帳戶或 [chroot 監獄])。您也應該保持作業系統的修補程式更新,並透過防火牆等方式強化安全性。 作業系統等級的資源限制可能也有必要 [5]。限制使用 Lua 語言的子集可以緩解其中的部分疑慮。

請參閱 LibrariesAndBindings 的「Sandboxing」章節中的部分函式庫。

以下註解可能不完整,且僅供作起點。

簡單沙盒

以下是最簡單的沙盒之一。它也是其中限制最多的沙盒,除了不處理資源耗盡問題之外。

-- make environment
local env = {} -- add functions you know are safe here

-- run code under environment [Lua 5.1]
local function run(untrusted_code)
  if untrusted_code:byte(1) == 27 then return nil, "binary bytecode prohibited" end
  local untrusted_function, message = loadstring(untrusted_code)
  if not untrusted_function then return nil, message end
  setfenv(untrusted_function, env)
  return pcall(untrusted_function)
end

-- run code under environment [Lua 5.2]
local function run(untrusted_code)
  local untrusted_function, message = load(untrusted_code, nil, 't', env)
  if not untrusted_function then return nil, message end
  return pcall(untrusted_function)
end

-- test
assert(not run [[print(debug.getinfo(1))]]) --> fails
assert(run [[x=1]]) --> ok
assert(run [[while 1 do end]]) --> ok (but never returns)

此沙盒中的程式碼可以在沙盒環境中建立變數、建立基本型別的值(因此會配置記憶體),以及執行運算。對於記憶體用量和運算沒有限制,因此若未採取進一步限制,不可信賴的程式碼仍然可能嚴重影響系統效能。沙盒無法存取環境外的 I/O、函式和變數。沙盒要與外部世界溝通的唯一途徑是影響其環境(例如在該環境中取得及設定變數,以及呼叫函式),假設沙盒外的程式碼也可以存取那些變數和函式。

您可以撰寫一個剖析器,接受 Lua 語言的子集(例如禁止迴圈),但這可能仍然不足以完全防止 CPU 耗盡。

變數表

以下是 Lua 5.1 變數的清單,說明了它們在沙盒環境中使用的安全性。請注意,變數是否安全可能會**取決於特定應用程式的安全需求**及您的 Lua 狀態。不保證以下清單完整或正確,但這只是一個指南。要建立沙盒,您應從一個空的環境開始,然後只擷取您確定為安全的函式 [1](即白名單非黑名單)。您不應該依賴手冊提供函式的完整清單(例如 HiddenFeatures)。

注意:以下清單尚未針對 Lua 5.2 更新。

local oldloadstring = loadstring
local function safeloadstring(s, chunkname)
  local f, message = oldloadstring(s, chunkname)
  if not f then
    return f, message
  end
  setfenv(f, getfenv(2))
  return f
end
也不安全。例如,pcall(safeloadstring, some_script) 會在全域環境中載入 some_script。 --SergeyRozhenko

--DavidManura

舊意見

匿名者:應考量的攻擊

另請參閱


RecentChanges · 偏好設定
編輯 · 記錄
最後編輯時間 2023 年 12 月 12 日格林威治標準時間下午 6:04 (差異)