Свежая CVE-2026-31431 только набирает обороты, и тут я хочу показать, почему это не совсем обычная LPE.
Copy Fail как примитив Process Injection через Page Cache
Оригинальный PoC модифицирует setuid binary перед execve и получает root.
Второй публичный PoC подменяет id у текущего юзера на 0000.
Хорошие, рабочие LPE, дающие рута.
Но исследуя дополнительные свойства этого примитива я обнаружил несколько эффектов, не описанных в оригинальном disclosure:
Copy Fail позволяет модифицировать код уже запущенного процесса — без ptrace и без взаимодействия с процессом. Без execve для запуска кода.
Модификация невидима для inotify, не обновляет mtime файла, невидима для auditd и других стандартных инструментов отслеживания инжекта в процесс.
Модифицировать можно не только 4 байта, в цикле примитивами был модифицирован файл в 100 Кб данных за 6.5 секунд.
Live Code Injection в работающий процесс
Исполняемый файл загружается через mmap(file, MAP_PRIVATE, PROT_READ|PROT_EXEC).
.text segment доступен только на чтение — процесс в него не пишет, COW не происходит. PTE указывает на page cache page файла.
Copy Fail модифицирует эту page cache page через crypto subsystem (AF_ALG + splice + authencesn scratch write). Процесс видит изменённый код при следующем исполнении инструкции с модифицированной page.
Аналогичный механизм использовал Dirty Pipe (CVE-2022-0847) — запись в page cache через splice. Разница: Dirty Pipe модифицировал pipe buffer flags, Copy Fail использует scratch write в authencesn. Класс атаки один — эксплуатация разделяемости page cache между файловым кэшем и memory mappings процессов.
Max Kellerman ещё в 2022, раскрывая Dirty Pipe, отметил что page cache write позволяет «inject code into arbitrary processes».
На Copy.Fail это сработало на практике, и заодно обнаружилось, что стандартный Linux detection stack не очень готов к этому.
PoC
https://github.com/kvakirsanov/CVE-2026-31431-live-process-code-injection/blob/main/copy_fail_inject_poc.py
Результат на работающем процессе:
check() = 42 check() = 42 check() = 1337 ← код изменён без остановки процесса check() = 1337
Протестировано на Debian 6.1.0-25,x86_64 и aarch64
Процесс не останавливался, ptrace не использовался, /proc/PID/mem не открывался.
На уязвимых системах это рабочий способ инжекта в процесс в Linux.
Detection stack для process injection не покрывает этот случай.
Синие должны мониторить AF_ALG, не только ptrace.
Незаметный и необнаруживаемый, что немного усложняет и без того эпичный баг.
Какие механизмы защиты это обходит
Все задокументированные подходы (MITRE DET0203, DET0508, Tracee TRC-1024, Akamai guide) мониторят ptrace, /proc/PID/mem, process_vm_writev.
Page cache injection не использует ни один из этих механизмов — атакующий процесс работает только с файлом (AF_ALG socket + splice).
Теперь ловить нужно и AF_ALG сокет.
YAMA ptrace_scope — ограничивает ptrace. Не применимо, ptrace не используется.
Seccomp — зависит от профиля.
Docker default и Kubernetes PSS Restricted не блокируют AF_ALG (подтверждено Juliet Security). Профиль, явно блокирующий socket(AF_ALG, …), предотвращает атаку.
auditd ptrace/procfs rules — не срабатывают (ptrace и /proc/PID/mem не используются). Невидимость для файлового мониторинга
Copy Fail не вызывает write() на целевом файле.
Модификация page cache происходит внутри crypto subsystem через scatterwalk_map_and_copy(). inotify — не видит модификацию
$ inotifywait -m /tmp/copyfail_test.txt & $ python3 copy_fail_write.py /tmp/copyfail_test.txt 0 --text "PWND" /tmp/copyfail_test.txt OPEN /tmp/copyfail_test.txt ACCESS /tmp/copyfail_test.txt CLOSE_NOWRITE,CLOSE
Событие MODIFY не генерируется.
Зафиксированы только OPEN, ACCESS, CLOSE_NOWRITE — нормальные события чтения. Инструменты, зависящие от inotify (systemd path units, часть EDR), не получают уведомления об изменении. mtime/ctime — не обновляются
Modify: 2026-05-01 00:13:34 # до Copy Fail Modify: 2026-05-01 00:13:34 # после — без изменений
Обратимость
Модификация page cache обратима через posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED) — ядро сбрасывает страницы из кэша, следующее чтение загружает оригинальные данные с диска.
Это делается без привилегий.
После сброса: содержимое файла восстановлено, хэши совпадают с baseline, mtime не менялся, inotify не срабатывал.
Полный цикл (inject → use → erase) похоже не особо видим для средств мониторинга.
https://github.com/kvakirsanov/CVE-2026-31431-live-process-code-injection/blob/main/copy_fail_inject_poc.py
Telegram: https://t.me/secinfosex
Комментарии (4)

Xelld
01.05.2026 11:30А потом добавляем к атакам через общий page cache большие кластеры kubernetes в каком-нибудь enterprise, с одинаковыми базовыми образами у большинства сервисов - получается совсем неприятно.
После таких вот приколов kata/firecracker/etc уже не выглядят чем-то избыточным.
checkpoint
Весело у вас там.