制限付きサンドボックスの構築
安全な_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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Lua 5.2以降の_ENVモデル
- 制限付きサンドボックスの構築
- サンドボックス脱出の防止
- リソース制限とインストルメンテーション