Redisに存在する深刻な脆弱性 CVE-2026-23631(通称「DarkReplica」)は、レプリケーションサブシステムに潜む複雑なuse-after-free(UAF)の条件を通じて、認証済みの展開環境をリモートコード実行(RCE)の脅威にさらすものです。この脆弱性は、セキュリティ研究者のYoni SherezがZeroDayにおいて発見しました。
Cloud 2025コンペティションにおいて、この欠陥はRedisの内部Lua実行モデルとレプリケーションロジックを連鎖させることで、サーバーを完全に侵害できることを示しています。
Redisの深刻な脆弱性
この脆弱性は、攻撃者が有効な認証情報をすでに保有しているRedis環境を特定の標的とします。攻撃者はSLAVEOFコマンドを悪用することで、対象のRedisインスタンスを悪意のあるコントローラーサーバーのレプリカとして機能させることができます。
これにより、同期プロセスを操作してRedisのLua関数エンジン内で安全でないメモリ処理を引き起こし、攻撃の足がかりを作ることができます。
Redisは2つのLua実行モデルをサポートしています。従来のスクリプトエンジン(EVAL/EVALSHA)と、新しい関数エンジン(FUNCTION LOAD/FCALL)です。この脆弱性の中心となるのは後者です。
このエンジンを通じて登録された関数はクラスターノード間で持続的に同期される性質を持つため、強力な攻撃対象領域となります。Redisはサンドボックス化と実行制約を適用していますが、シングルスレッドアーキテクチャの特性により、長時間実行されるスクリプトの処理においてエッジケースが生じます。
ブロッキングを防ぐため、Redisはタイムアウトを定期的にチェックし、processEventsWhileBlocked()を通じて保留中のイベントを処理するLuaフックメカニズムを使用しています。
このメカニズムにより、スクリプトの実行中でも限定的なコマンド実行が可能です。しかし、重大な見落としが存在します。この状態ではほとんどのクライアントコマンドが制限されている一方、コントローラーサーバーからのレプリケーショントラフィックは、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を使って実行が継続され、典型的なuse-after-free状態が発生します。この脆弱性の原始的な性質により、攻撃者はメモリを破損させ、最終的に任意のコード実行を達成できます。
Redisはjemallocを使用しているため、悪用には慎重なヒープ操作が必要です。攻撃者はtostring()などのLuaプリミティブを活用してヒープアドレスをリークし、制御された割り当てによって解放済みメモリ領域を再取得します。たとえば、コルーチンオブジェクトを解放し、攻撃者が制御するデータに置き換えることができます。
local a = coroutine.create(function() end)
local addr = tostring(a)
a = nil
collectgarbage("collect")
a = "AAAAAA..." -- Reallocates at same address
実行を安定させるため、攻撃者はコルーチンを使って別のLuaステートに移行し、制御された環境で操作を行います。その後、Luaテーブルの内部構造を悪用して任意の読み書きプリミティブを構築し、最終的に重要な関数ポインタの操作を可能にします。
信頼性の高い攻撃経路の一つとして、カスタムメモリアロケーターとして機能する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()
Redisは2026年5月5日にこの脆弱性に対処し、サポートされているすべてのバージョンにパッチをリリースしました。影響を受けるバージョンは、Redis 7.2.0〜7.2.13、7.4.0〜7.4.8、8.2.0〜8.2.5、8.4.0〜8.4.2、8.6.0〜8.6.2です。修正済みバージョンは7.2.14、7.4.9、8.2.6、8.4.3、8.6.3です。
本番環境でRedisを運用している組織は、早急にパッチ適用を優先すべきです。また、レプリケーション設定の制限、不要なLua機能の無効化、厳格な認証制御の実施によってリスクを軽減できます。
Redisはクラウドネイティブおよびマイクロサービスアーキテクチャで広く使用されているため、この脆弱性が放置されると、横展開(ラテラルムーブメント)やインフラ侵害という重大なリスクをもたらします。
翻訳元: https://gbhackers.com/critical-redis-vulnerability/