Critical Redis Vulnerability Could Let Attackers Execute Code and Hijack Servers
2026/06/08 gbhackers — Redis で発見された深刻な脆弱性 CVE-2026-23631 に、DarkReplica という名称が付けられた。この脆弱性を悪用する攻撃者は、レプリケーション・サブシステムにおける複雑な解放後メモリ使用 (use-after-free) 条件を操作することで、認証済み環境に対するリモート・コード実行 (RCE) を可能にする。

この脆弱性は、ZeroDay.In the Cloud 2025 のコンペティション中に、セキュリティ研究者 Yoni Sherez により発見されたものである。彼が実証したのは、Redis の内部 Lua 実行モデルとレプリケーション・ロジックを連鎖させることで、サーバ全体の完全な侵害につながる可能性である。
Redis の深刻な脆弱性
この脆弱性を悪用する認証済みの攻撃者は、SLAVEOF コマンドを悪用することで、標的とする Redis インスタンスを悪意のコントローラ・サーバのレプリカへと強制的に変更する。それにより同期プロセスを操作し、Redis の Lua 関数エンジン内で安全でないメモリ処理を誘発し、攻撃の足掛かりを構築できる。
Redis がサポートする 2 種類の Lua 実行モデルは、従来のスクリプト・エンジン (EVAL/EVALSHA) と、新しい関数エンジン (FUNCTION LOAD/FCALL) であり、この脆弱性は後者に存在する。
この関数エンジンを通じて登録された関数は永続化され、クラスタ・ノード間で同期されるため、強力な攻撃対象となる。Redis はサンドボックス化と実行制約を適用しているが、シングル・スレッド・アーキテクチャにおいては、長時間にわたり実行されるスクリプトの処理時に例外的なケースが発生する。
Redis はブロックを防ぐために、Lua フック・メカニズムを使用して定期的にタイムアウトをチェックし、processEventswhileBlocked() 経由で保留中のイベントを処理する。この仕組みにより、スクリプト実行中であっても限定的なコマンド実行が許可されるが、深刻な設計上の欠陥を引き起こす。
その一方で、通常のクライアント・コマンドの実行は制限されるが、コントローラ・サーバからのレプリケーション・トラフィックは、Lua 関数の実行中であっても検証されることなく処理される。その結果、レース・コンディションが発生する。
無限ループなどの Lua 関数を実行する攻撃者は、意図的に遅延を引き起こすことで、悪意のマスターから FULLRESYNC をトリガーできる。同期処理中における Redis は、functionsLibCtxClearCurrent() を使用して既存の関数コンテキストをクリアし、最終的にグローバル lua_State オブジェクトを解放する。
void functionsLibCtxClearCurrent(int async) { functionsLibCtxFree(curr_functions_lib_ctx); dictRelease(engines); // Frees lua_State functionsInit();}
その後に、制御が実行中の Lua 関数へ戻ると、解放済みの lua_State を使用する状態で処理が継続され、典型的な解放後メモリ使用の状態が発生する。このプリミティブにより、メモリ破壊が発生し、最終的には任意のコード実行へと至る。
ただし、Redis は jemalloc を使用しているため、エクスプロイトには慎重なヒープ操作が必要となる。攻撃者の戦術として挙げられるのは、tostring() などの Lua プリミティブを利用してヒープ・アドレスをリークし、制御された割り当てにより解放済みメモリ領域を再利用する手法である。それにより、解放後のコルーチン・オブジェクトを、攻撃者が制御するデータへと置き換えることが可能になる。
local a = coroutine.create(function() end)local addr = tostring(a)a = nilcollectgarbage("collect")a = "AAAAAA..." -- Reallocates at same address
攻撃者は実行を安定化させるために、コルーチンを悪用して別の Lua 状態へピボットし、制御された環境で処理を継続する。そこから Lua テーブルの内部構造を操作して任意の read/write プリミティブを構築し、重要な関数ポインタの操作を可能にする。その他にも、lua_State->l_G->frealloc ポインタを上書きするという、信頼性の高い手法もある。
このポインタを system() にリダイレクトし、その引数を制御することで、コマンド実行を実現できる。
write(fake_l_G + offsetof(global_State, frealloc), system);write(fake_l_G + offsetof(global_State, ud), command_payload_addr);coroutine.resume(co); // Triggers system()
2026年5月5日の時点で Redis は、サポート対象の全バージョンに対してパッチをリリースし、この問題に対処している。
影響を受けるバージョンは以下の通りである。
- Redis 7.2.0 ~ 7.2.13
- Redis 7.4.0 ~ 7.4.8
- Redis 8.2.0 ~ 8.2.5
- Redis 8.4.0 ~ 8.4.2
- Redis 8.6.0 ~ 8.6.2
修正済みバージョンは以下の通りである。
- Redis 7.2.14
- Redis 7.4.9
- Redis 8.2.6
- Redis 8.4.3
- Redis 8.6.3
本番環境で Redis を運用する組織に対して強く推奨されるのは、速やかなパッチの適用である。それに加えて、レプリケーション設定の制限/不要な Lua 機能の無効化/厳格な認証制御の適用などによりリスクを軽減できる。
クラウド・ネイティブおよびマイクロ・サービス・アーキテクチャで利用される Redis の脆弱性が、未対策の状態で放置されると、広範囲に影響が及ぶ可能性がある。具体的には、横方向への移動やインフラ侵害につながる深刻なリスクがもたらされる。
訳者後書:脆弱性 CVE-2026-23631 は、単純な入力検証の不備ではなく、Redis の内部機能における想定外の相互作用から生じる欠陥です。問題の中心となるのは、Lua 関数の実行中にもレプリケーション処理が進行できる設計です。本来は制限されるべき処理がありますが、レプリケーション・トラフィックは十分な状態確認なしに処理されるため、レース・コンディションが発生し、使用中の lua_State が解放される状況が生まれます。その結果、解放後メモリ使用が発生し、最終的には任意のコード実行へ発展します。ご利用のチームは、ご注意ください。よろしければ、Redis での検索結果も、ご参照ください。
You must be logged in to post a comment.