0Pricing
Lua Academy · レッスン

制限付きサンドボックスの構築

安全な_ENVのホワイトリストを作成し、load()で信頼できないコードを実行します。

「制限付きサンドボックスの構築」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

目標

制限付きサンドボックスを使用すると、信頼できないLuaコードを安全に実行できます。コードは計算や文字列、数学関数を使用できますが、ファイルシステム、OS、ネットワークにはアクセスできません。

ホワイトリスト方式

安全で動作を十分に把握している関数だけを含め、サンドボックス環境を最初から構築します。

local function makeSandbox()
  return {
    print   = print,
    type    = type,
    tostring = tostring,
    tonumber = tonumber,
    pairs   = pairs,
    ipairs  = ipairs,
    next    = next,
    select  = select,
    unpack  = table.unpack,
    error   = error,
    pcall   = pcall,
    xpcall  = xpcall,
    math    = math,
    string  = { format=string.format, find=string.find,
                match=string.match, gmatch=string.gmatch,
                gsub=string.gsub, sub=string.sub,
                len=string.len, byte=string.byte, char=string.char },
    table   = { insert=table.insert, remove=table.remove,
                concat=table.concat, sort=table.sort,
                unpack=table.unpack, move=table.move },
  }
end

サンドボックス内でのコード実行

サンドボックスを_ENVとして、ユーザーコードをロードして実行します。

local function runSandboxed(code, env)
  local fn, err = load(code, "user", "t", env)
  if not fn then return nil, err end
  return pcall(fn)
end
local env = makeSandbox()
local ok, err = runSandboxed("return 1+1", env)
print(ok, err)  -- true  2

出力の取得

printを、標準出力に書き込む代わりにバッファーへ追加するカスタム関数に置き換えます。

local output = {}
env.print = function(...)
  local parts = {}
  for i = 1, select("#", ...) do
    parts[i] = tostring(select(i, ...))
  end
  output[#output+1] = table.concat(parts, "\t")
end

値の返却

サンドボックス化したコードから値を返せるようにするには、コンパイル済みのチャンクを関数として呼び出し、その戻り値を取得します。

local fn = load("return math.sqrt(144)", "user", "t", env)
if fn then
  local ok, result = pcall(fn)
  print(ok, result)  -- true  12.0
end

メタメソッドの悪用の防止

フィールドの制限を回避されないよう、サンドボックス化したコードにメタテーブルやrawget、rawsetへの参照を渡さないでください。

文字列長の制限

文字列操作をオーバーライドして出力長を制限し、大きな文字列の割り当てによるDoSを防ぎます。

debug.sethookによるリソース制限

命令カウンターのフックを追加して、終了しないコードを停止します。

local function sandboxWithLimit(code, env, maxOps)
  local ops = 0
  debug.sethook(function()
    ops = ops + 1
    if ops > maxOps then error("Instruction limit exceeded") end
  end, "", 100)
  local result = table.pack(runSandboxed(code, env))
  debug.sethook()
  return table.unpack(result, 1, result.n)
end

サンドボックスのテスト

既知の脱出経路を試すテストを作成し、すべて失敗することを確認します。対象には_Gへのアクセス、loadの呼び出し、debugの使用が含まれます。

既知の脱出経路

一般的な脱出経路には、string.rep("x",2^30)(メモリDoS)、標準オブジェクトに対する({}).__index、文字列メタテーブル経由のdebug、package.loaded経由のioがあります。

サンドボックスに関する質問

サンドボックスにloadやdofileを含めてはいけないのはなぜですか。

振り返り: 制限付きサンドボックスの構築

カスタムenvテーブルには、安全な関数だけをホワイトリストとして登録します。load(code, name, "t", env)を使用します。debug.sethookで命令数のカウントを追加します。脱出経路をテストします。load、dofile、debug、またはグローバルテーブルへのアクセスは決して含めないでください。

よくある質問

「制限付きサンドボックスの構築」レッスンは無料ですか?

はい。「制限付きサンドボックスの構築」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「制限付きサンドボックスの構築」で何を学びますか?

安全な_ENVのホワイトリストを作成し、load()で信頼できないコードを実行します。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Lua Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「制限付きサンドボックスの構築」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLua Academyレッスンでコードを書いて実行できますか?

はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Lua 5.2以降の_ENVモデル
  2. 制限付きサンドボックスの構築
  3. サンドボックス脱出の防止
  4. リソース制限とインストルメンテーション
← Lua Academyに戻る