Блог

DarkReplica (CVE-2026-23631): как Redis отдал RCE через механизм репликации

DarkReplica-CVE-2026-23631-redis
CVE / Linux / Базы данных / Безопасность

DarkReplica (CVE-2026-23631): как Redis отдал RCE через механизм репликации

Redis стоит за половиной современного веба — кэш сессий, очереди задач, rate limiting, pub/sub. Именно поэтому уязвимость в нём редко остаётся теоретической. CVE-2026-23631 по имени DarkReplica — use-after-free в подсистеме репликации, которая в определённых условиях открывает путь к выполнению произвольного кода на сервере. Исследователь Yoni Sherez нашёл её на соревновании ZeroDay.Cloud 2025 в Лондоне в декабре прошлого года и получил за это $30 000. Патч вышел 5 мая 2026 года. Если вы ещё не обновились — читайте дальше.

ЧТО ПРОИЗОШЛО

CVE-2026-23631 — use-after-free уязвимость в механизме репликации Redis. CVSS 6.1 (Medium по CVSSv4.0), CWE-416. Официальное описание от Redis: аутентифицированный пользователь может эксплуатировать механизм синхронизации master-replica и вызвать use-after-free в движке Lua-функций, что потенциально ведёт к удалённому выполнению кода. Уязвимость затрагивает все версии Redis с поддержкой Lua scripting — то есть практически все вообще. Ограничение одно: нужна аутентификация в Redis. PoC опубликован в writeup исследователя.

Примечание по поводу оценки CVSS: в некоторых источниках указывается оценка 8,5 (High) — это устаревшее значение по CVSS v2, взятое из вторичного источника. Официальный балл от Redis и NVD по CVSSv4.0 составляет 6,1 (средний), с высокой сложностью атаки (AC:H). Это не означает, что уязвимость безвредна. Это означает, что для успешной эксплуатации должны совпасть несколько условий — но Йони Шерез продемонстрировал, что это возможно.

ЧТО ТАКОЕ РЕПЛИКАЦИЯ В REDIS И LUA-ДВИЖОК

Redis поддерживает репликацию по схеме master-replica: один сервер назначается главным, остальные — репликами. Реплика подключается к мастеру, получает полную синхронизацию при старте, а затем принимает поток команд в реальном времени. Для назначения мастера используется команда SLAVEOF. Это стандартный механизм для высокой доступности и масштабирования чтения.

Параллельно Redis имеет встроенный Lua-движок — точнее, два. Первый — scripting engine (команды EVAL, EVALSHA, SCRIPT LOAD) — старый механизм для запуска произвольных Lua-скриптов. Второй — functions engine (команды FUNCTION LOAD, FCALL) — более новый, позволяет регистрировать именованные библиотеки функций, которые сохраняются в RDB/AOF и синхронизируются между узлами кластера. Именно functions engine стал точкой входа для DarkReplica.

КАК РАБОТАЕТ БАГ

Redis — однопоточный сервер. Когда Lua-функция выполняется долго (по умолчанию дольше 5 секунд), сервер не может обрабатывать новые запросы в обычном режиме. Чтобы не зависнуть полностью, Redis перед запуском Lua-кода устанавливает хук через lua_sethook — он срабатывает каждые 100 000 Lua-инструкций и вызывает processEventsWhileBlocked(). Эта функция обрабатывает ожидающие события из event loop — так сервер остаётся отзывчивым даже во время долгой Lua-функции.

Критически важная деталь: processEventsWhileBlocked() обрабатывает не только запросы обычных клиентов, но и все I/O-события — включая команды от мастер-сервера в репликации. И вот здесь ничего не проверяет, выполняется ли в данный момент Lua-функция. Для обычных клиентов Redis блокирует неразрешённые команды во время выполнения скрипта: команда вроде FUNCTION FLUSH вернёт ошибку BUSY Redis is busy running a script. Но команда FUNCTION FLUSH, пришедшая от мастера через канал репликации — пройдёт.

Результат: Lua-движок удаляется из памяти командой мастера прямо в тот момент, когда функция продолжает выполняться. Lua-окружение освобождено — но выполнение продолжает обращаться к уже освобождённой памяти. Это классический use-after-free: freed Lua engine, который ещё используется. CWE-416 в чистом виде.

КАК ЭТО ЭКСПЛУАТИРУЕТСЯ

Атакующий, имеющий аутентифицированный доступ к Redis-серверу, выполняет следующую последовательность. Сначала он запускает медленную Lua-функцию через FCALL — такую, которая будет работать достаточно долго, чтобы Redis вошёл в режим timeout и начал вызывать processEventsWhileBlocked(). Затем через канал репликации — то есть настроив подконтрольный «мастер» — отправляет команду FUNCTION FLUSH. Redis принимает её и уничтожает Lua-движок прямо во время выполнения функции.

После получения use-after-free Yoni Sherez разработал набор техник для чтения и записи произвольной памяти процесса. По его словам, эксплуатация потребовала глубокого понимания внутреннего устройства Redis и виртуальной машины Lua 5.1 — это не тривиальный one-click exploit. Тем не менее результат достигнут: выполнение системных команд на целевом сервере от имени процесса Redis. Полный writeup с техническими деталями опубликован на ZeroDay.Cloud.

ЧТО ПРОИСХОДИТ ДАЛЬШЕ — ЗАВИСИТ ОТ КОНФИГУРАЦИИ

Уязвимость срабатывает только при одновременном выполнении нескольких условий: аутентифицированный доступ к Redis, возможность настроить канал репликации, включённый Lua scripting (по умолчанию активен), и реплика с отключённым replica-read-only. Если Redis вообще не использует репликацию — вектор атаки через мастер-канал недоступен. Если Redis доступен только с localhost или из приватной сети с жёстким контролем доступа — риск существенно снижается.

Максимально уязвимы конфигурации, где Redis доступен нескольким клиентам, используется репликация, и аутентификация слабая или отсутствует. Именно такие настройки нередко встречаются в dev-окружениях и на серверах, которые «быстро подняли» без следования hardening-гайдам. Redis Cloud-инстансы защищены — провайдер уже применил патчи.

РЕАЛЬНАЯ ЦЕПОЧКА АТАКИ

Реалистичный сценарий выглядит так. Веб-приложение использует Redis для кэша и сессий. Redis настроен с паролем, но он слабый или утёкший. Атакующий подключается к Redis напрямую — например, через открытый порт 6379 или через уязвимость в приложении, позволяющую делать произвольные Redis-запросы. Версия Redis — 7.4.8, обновление не делали с момента установки. Атакующий запускает медленную Lua-функцию через FCALL, одновременно поднимает подконтрольный Redis-инстанс и через SLAVEOF назначает его мастером для целевого сервера. Когда timeout Lua срабатывает и Redis входит в processEventsWhileBlocked(), команда FUNCTION FLUSH от мастера уничтожает Lua-движок. Use-after-free открывает путь к RCE. Redis работает от пользователя redis — атакующий получает shell с его привилегиями, читает данные из памяти, получает доступ к данным сессий и кэша приложения.

ТАЙМЛАЙН

Декабрь 2025 года. Соревнование ZeroDay.Cloud 2025 в Лондоне. Yoni Sherez выбирает Redis как цель — «из-за сложной и интересной attack surface», как он написал в writeup. Находит DarkReplica. Получает $30 000. Январь 2026 года — CVE зарезервирован. 5 мая 2026 года — Redis выпускает патч сразу для всех пяти поддерживаемых веток в один день. 2 июня 2026 года — Yoni Sherez публикует полный технический writeup на ZeroDay.Cloud. Между находкой и публичным раскрытием — шесть месяцев. Патч успел выйти за месяц до того, как детали стали публичными. Так и должно работать responsible disclosure.

ПОЧЕМУ ЭТО ВАЖНО

Redis — не экзотика. Это кэш за вашим nginx, хранилище сессий вашего WordPress, очередь задач вашего приложения. Он есть почти на каждом production-сервере, который делает что-то серьёзнее статического сайта. DarkReplica затрагивает все версии Redis с Lua scripting — то есть все версии, которые реально стоят на серверах. Именно поэтому CVSS 6.1 не должен усыплять бдительность: «Medium» это оценка сложности атаки, а не её последствий. RCE есть RCE, независимо от того, сколько условий нужно сложить.

Отдельная история — Redis без аутентификации или со слабым паролем, доступный напрямую из интернета. Для таких инстансов условие «нужна аутентификация» просто исчезает из уравнения. DarkReplica при наличии репликации превращается в прямой путь к RCE. И таких серверов больше, чем хотелось бы думать — Redis исторически проектировался для работы в доверенной сети, и многие администраторы до сих пор об этом забывают.

ОБНОВЛЕНИЕ

Патч вышел 5 мая 2026 года для всех поддерживаемых веток. Проверьте текущую версию Redis — первая команда покажет версию клиента, вторая запросит версию запущенного сервера. Если Redis защищён паролем, подставьте его через флаг -a; если без пароля — уберите -a и аргумент:

redis-cli --version
redis-cli INFO server | grep redis_version
# если Redis с паролем:
redis-cli -a ВАШ_ПАРОЛЬ INFO server | grep redis_version

Затем сверьтесь с таблицей патченных версий. Если ваша версия входит в диапазон затронутых — обновляйтесь немедленно.

Затронутые ветки и патченные версии по официальному advisory Redis:

  • Redis 7.2.x: затронуты 7.2.0 – 7.2.13, исправлено в 7.2.14
  • Redis 7.4.x: затронуты 7.4.0 – 7.4.8, исправлено в 7.4.9
  • Redis 8.2.x: затронуты 8.2.0 – 8.2.5, исправлено в 8.2.6
  • Redis 8.4.x: затронуты 8.4.0 – 8.4.2, исправлено в 8.4.3
  • Redis 8.6.x: затронуты 8.6.0 – 8.6.2, исправлено в 8.6.3

Обновление на Ubuntu/Debian зависит от источника установки. Если Redis устанавливался из официального репозитория redis.io — убедитесь что репозиторий подключён, затем обновляйте. Если репозиторий ещё не добавлен, официальная инструкция redis.io:

sudo apt-get install -y lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis

Если репозиторий уже был подключён — достаточно обновить пакет:

sudo apt-get update
sudo apt-get install redis
redis-cli --version

Важно: Ubuntu и Debian из своих стандартных репозиториев дают устаревшую версию Redis (обычно 6.x или 7.0). Команда sudo apt install redis-server без официального репозитория redis.io не даст нужной версии — только packages.redis.io содержит актуальные ветки 7.2, 7.4, 8.x. После обновления перезапустите службу:

sudo systemctl restart redis-server
sudo systemctl status redis-server

Если обновление невозможно прямо сейчас, Redis официально описывает два workaround’а. Первый — запретить выполнение Lua-скриптов: ограничьте команды EVAL, EVALSHA, FCALL и FCALL_RO через механизм ACL для всех пользователей, которым не нужна эта функциональность. Конкретный синтаксис зависит от версии Redis и конфигурации ACL — обратитесь к официальной документации Redis по ACL. Второй workaround — убедиться, что все реплики работают с replica-read-only yes. Это значение по умолчанию, но его стоит проверить явно. На каждой реплике выполните:

redis-cli CONFIG GET replica-read-only

Если вывод показывает no — реплика уязвима. Включите обратно:

redis-cli CONFIG SET replica-read-only yes

Чтобы изменение сохранилось после перезапуска, добавьте в /etc/redis/redis.conf:

replica-read-only yes

Оба workaround’а снижают риск, но не устраняют уязвимость — обновление остаётся единственным полным решением.

Независимо от статуса обновления, убедитесь что Redis не доступен из интернета напрямую. Порт 6379 должен быть закрыт на firewall для всех, кроме доверенных IP. Проверьте через nftables:

sudo nft list ruleset | grep 6379

Если вывод пустой — правило для порта отсутствует, и Redis либо защищён bind-address в конфигурации, либо открыт для всех. Проверьте:

grep -E "^bind|^protected-mode" /etc/redis/redis.conf

Значение bind 127.0.0.1 означает, что Redis слушает только localhost. protected-mode yes — дополнительная защита, блокирующая внешние подключения без пароля. Оба должны быть настроены корректно.

ВЫВОДЫ

DarkReplica — хороший пример того, что post-authentication уязвимость это не повод расслабляться. Аутентификация в Redis нередко означает один пароль в строке подключения приложения, а не полноценную изоляцию. Механизм репликации — часть Redis, которую редко рассматривают как attack surface. Именно там Yoni Sherez нашёл use-after-free, которого никто не ждал. Обновите Redis до патченной версии: 7.2.14, 7.4.9, 8.2.6, 8.4.3 или 8.6.3 — в зависимости от вашей ветки. Закройте порт 6379 от интернета, проверьте настройки репликации — и этот вектор атаки для вас закрыт.

Leave your thought here

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Select the fields to be shown. Others will be hidden. Drag and drop to rearrange the order.
  • Image
  • SKU
  • Rating
  • Цена
  • Stock
  • Availability
  • Add to cart
  • Description
  • Content
  • Weight
  • Dimensions
  • Additional information
Click outside to hide the comparison bar
Compare