Статья CVE-2026-31431 «Copy Fail»: разбор Linux privilege escalation без race condition

Плата одноплатного компьютера на чёрном антистатическом коврике: поднятый чип с обгоревшими контактными площадками, щуп у пустого сокета. Гравировка на текстолите — CVE-2026-31431 · COPY FAIL.


Приведённые ниже идентификаторы, оценки CVSS и CWE основаны на данных disclosure-отчёта и могут быть уточнены после официальной регистрации.

732 байта Python-кода, один промпт ИИ-системе Xint Code от Theori - и детерминистический root на каждом крупном дистрибутиве Linux, выпущенном после 2017 года. CVSS 7.8 (HIGH), CWE-1288 (Incorrect Resource Transfer Between Spheres), Metasploit-модуль опубликован в день раскрытия. На момент публикации CVE-2026-31431 не зарегистрирован в NVD - все идентификаторы и оценки взяты из disclosure-отчёта и могут измениться. Для пентестера, привыкшего бороться с KASLR, race window и нестабильными PoC под каждую версию ядра, Copy Fail - событие уровня Dirty Pipe, только масштабнее. Разберём механику бага, пошаговую эксплуатацию и конкретные действия по обе стороны баррикады.

Место Copy Fail в цепочке атаки​

Copy Fail - local privilege escalation, техника T1068 (Exploitation for Privilege Escalation) по MITRE ATT&CK, с маппингом на T1548.001 (Setuid and Setgid): эксплойт злоупотребляет setuid-бинарём для получения root. В реальном пентесте уязвимость занимает чёткую позицию между initial access и полным контролем над хостом: Подробнее - в нашем статье о linux для пентестера.
  1. Initial access - атакующий получает low-privilege shell (RCE в веб-приложении, SSH с утечённым паролем, скомпрометированный CI/CD-раннер).
  2. Linux privilege escalation через Copy Fail - скрипт превращает www-data или nobody в root за секунды. Ни race condition, ни per-distro offsets.
  3. Post-exploitation - дамп credentials, lateral movement, persistence.
Критический момент для контейнерных сред: page cache - общесистемный ресурс. Контейнер с shared kernel разделяет page cache с хостом. Copy Fail - не только LPE внутри хоста, но и потенциальный container escape. PoC для Kubernetes с escape на уровень ноды опубликован на GitHub (Percivalll/Copy-Fail-CVE-2026-31431-Kubernetes-PoC, 147 звёзд - валидирован на Alibaba Cloud ACK, Amazon EKS и Google GKE).

Что не затронуто: микроВМ (AWS Firecracker, Fargate), gVisor, V8-изоляты (Cloudflare Workers). Устоявшая граница - та, где у каждого tenant своё ядро.

Когда проверять Copy Fail первым​

На внутреннем пентесте после получения shell проверка Copy Fail занимает меньше времени, чем перебор SUID-бинарей или разбор cron jobs. Decision tree для выбора вектора linux privilege escalation на хосте с ядром 2017+:

УсловиеДействие
Модуль algif_aead загружен или built-in, ядро не пропатченоCopy Fail - root за секунды
algif_aead заблокирован через initcall_blacklistПереход к классике: SUID, capabilities, cron, sudo misconfig
gVisor / kata / microVMCopy Fail неприменим, искать другие векторы
SELinux enforcing с нестандартной политикойМожет заблокировать AF_ALG - нужна проверка

Анатомия бага: AF_ALG, page cache и четыре байта​

Чтобы понять, почему Copy Fail работает детерминистически на любом дистрибутиве, разберём три компонента ядра, которые эксплойт связывает в одну цепочку.

AF_ALG и userspace crypto API​

Ядро предоставляет внутренний крипто-API для kTLS, IPsec и других подсистем. Пользовательские программы обращаются к нему через семейство сокетов AF_ALG - и это доступно непривилегированным процессам. Модуль algif_aead даёт интерфейс для AEAD-шифров (Authenticated Encryption with Associated Data).

Непривилегированный процесс создаёт сокет AF_ALG, выполняет bind() к AEAD-шаблону (authencesn(hmac(sha256),cbc(aes))), устанавливает ключ через setsockopt(), передаёт данные через sendmsg() или splice() и запускает крипто-операцию вызовом recvmsg().

Критический элемент - splice(). Этот системный вызов (T1106, Native API) передаёт данные через ссылки на страницы page cache, не копируя их. Вот тут и зарыта собака.

Page cache и setuid-бинари​

Page cache - общесистемный кеш содержимого файлов в оперативной памяти. Когда процесс читает /usr/bin/su, ядро загружает страницы с диска в page cache. Последующие обращения - от любого пользователя, включая execve() - читают те же закешированные страницы.

Если атакующий модифицирует страницу page cache, принадлежащую setuid-бинарю, при следующем запуске этого бинаря загрузится изменённый код - с привилегиями владельца файла (root). На диске файл остаётся нетронутым.

Оптимизация 2017 года и out-of-bounds write​

В 2017 году algif_aead получил оптимизацию in-place операций: destination и reference pages объединялись в единый scatterlist. Код не проверял, допустима ли запись алгоритмом за пределы выделенного output-региона. Девять лет никто этого не заметил.

Шаблон authencesn при расшифровке выполняет 4-байтовую запись scratch-данных по фиксированному смещению:
C:
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
Через splice() атакующий подключает страницы page cache целевого файла в scatterlist. Четыре «мусорных» байта authencesn записываются не в буфер пользователя, а в page cache произвольного read-only файла. Атакующий контролирует: какой файл модифицируется, смещение и конкретные 4 байта. Функция возвращает -EBADMSG (ошибка аутентификации), но запись уже произведена.

По данным Bugcrowd, баг прятался девять лет потому, что подсистему crypto/ ревьюили как криптографы: IND-CPA, side channels, валидация параметров. Вопрос «должна ли эта страница памяти вообще быть writeable» - из другой дисциплины, и он просто выпал из поля зрения.

Пошаговая эксплуатация Copy Fail​

Требования к окружению​

ПараметрЗначение
СценарийВнутренний пентест, post-exploitation с low-priv shell
Целевые ОСЛюбой Linux с ядром от 2017 г.: Ubuntu, RHEL, Amazon Linux, SUSE, Debian
ПривилегииНепривилегированный локальный пользователь
ЗависимостиPython 3 (стандартная библиотека) или Go/Rust; модуль algif_aead загружен
RAMОт 512 МБ (page cache должен вместить целевой бинарь)
Race conditionНе требуется
Per-distro offsetsНе требуются
КонтейнерыРаботает при shared kernel (Docker default). Не работает из gVisor, kata, microVM

Последовательность шагов​

По техническому описанию из disclosure Xint Code и анализу Cloudflare:
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Ограничения техники​

ОграничениеДетали
Только локальный доступCopy Fail не эксплуатируется удалённо - нужен shell
Модуль algif_aead заблокированWorkaround через initcall_blacklist закрывает вектор
gVisor / microVM / kataНе работает - отдельное ядро на tenant
AppArmor / SELinux enforcingМогут ограничить AF_ALG или splice(), но default-политики дистрибутивов этого не делают
Hardened kernels (grsecurity)С ограничениями на AF_ALG - вектор заблокирован

Copy Fail vs Dirty COW vs Dirty Pipe​

Три уязвимости работают через один примитив - запись в page cache read-only файлов - но фундаментально различаются в механике:

ХарактеристикаDirty COW (CVE-2016-5195)Dirty Pipe (CVE-2022-0847)Copy Fail (CVE-2026-31431)¹
CVSS7.0 NVD / 7.8 Red Hat (HIGH)7.8 (HIGH)7.8 (HIGH, заявленный)
CWECWE-362 (Race Condition)CWE-665 NVD / CWE-908 Red Hat (Improper Initialization / Use of Uninitialized Resource)CWE-1288 (Incorrect Resource Transfer)
Тип багаRace condition в mm/gup.cНеинициализированные флаги pipe bufferLogic flaw в algif_aead
СтабильностьНестабильный, зависит от timingСтабильныйДетерминистический
Per-distro offsetsЧасто требуютсяНе требуютсяНе требуются
Окно уязвимости2007-2016 (9 лет)2020-2022 (2 года)2017-2026 (9 лет)
CISA KEVДа (2022-03-03)Да (2022-04-25)Да (2026-05-01)
EPSS0.9418 (Top 1%)0.8121 (Top 1%)0.0257 (85-й перцентиль)
Container escapeНетОграниченноДа (shared kernel)

Dirty COW требовал гонки потоков и мог уронить систему. Dirty Pipe работал стабильнее, но затрагивал узкий диапазон ядер (5.8 - 5.16.11). Copy Fail берёт детерминизм Dirty Pipe и добавляет покрытие всех ядер 2017+ (чего у Pipe не было), плюс минимальный форензик-след.

По данным SafeBreach: эксплойт использует только стандартные системные вызовы (socket, setsockopt, splice, sendmsg, recvmsg) и стандартную библиотеку Python - отпечаток минимальный. Помимо Python-скрипта, на GitHub доступны реализации на Rust (iss4cf0ng/CVE-2026-31431-Linux-Copy-Fail, 50 звёзд) и минимальный ELF без libc (Crihexe/copy-fail-tiny-elf-CVE-2026-31431, 61 звезда).

Что увидит и не увидит защита​

Поведенческий детект​

По данным Cloudflare, их behavioral detection зафиксировал эксплуатацию в течение нескольких минут - без обновления сигнатур, без ручного вмешательства. Система связала цепочку: интерпретатор скрипта → крипто-подсистема ядра → запуск setuid-бинаря - и отметила как аномалию по fleet-wide паттернам. Это работает при масштабе телеметрии Cloudflare. На среднем Linux-хосте без EDR - картина совсем другая.

IoC для мониторинга​

Конкретные индикаторы:
  • Создание AF_ALG сокетов непривилегированными процессами (для большинства workloads это аномалия - кому в продакшене нужен userspace crypto через сокеты?).
  • splice() с файловым дескриптором setuid-бинаря в качестве источника.
  • Последовательность AF_ALG bindsplicerecvmsgexecve setuid-бинаря от одного PID/сессии.
Для auditd - мониторинг обращений к AF_ALG:
Bash:
auditctl -a always,exit -F arch=b64 -S socket -F a0=0x26 -k af_alg_access

Слепые зоны стандартного мониторинга

Файловый мониторинг (AIDE, Tripwire, inotify) тут бесполезен: Copy Fail модифицирует page cache, а не файл на диске. Хеши файлов остаются неизменными - можно хоть каждую минуту проверять, ничего не найдёшь. Auditd в default-конфигурации не логирует AF_ALG. Стандартные EDR без kernel-level телеметрии могут пропустить вектор, если не отслеживают крипто-подсистему.

По вендорам: CrowdStrike Falcon и SentinelOne с kernel-level телеметрией имеют больше шансов на детект по поведенческим паттернам, но конкретных подтверждений от этих вендоров на момент раскрытия не опубликовано. Для Elastic 8.x+ потребуется custom detection rule на цепочку syscalls - стандартные правила Elastic Security Labs покрывают linux privilege escalation через process capabilities, но Copy Fail эксплуатирует другой вектор. Kaspersky EDR Expert на Linux-агенте: публичных данных о детекте Copy Fail нет.

Митигация и чеклист реагирования​

Быстрая блокировка​

Отключение модуля algif_aead - самый быстрый workaround. По данным ThreatLocker:
Bash:
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
rmmod algif_aead 2>/dev/null || true
На RHEL/CentOS модуль встроен в ядро (built-in), rmmod не сработает. Red Hat рекомендует boot-параметры (RHSB-2026-002): initcall_blacklist=algif_aead_init (только AEAD-модуль), initcall_blacklist=af_alg_init (весь AF_ALG интерфейс) или initcall_blacklist=crypto_authenc_esn_module_init (конкретный алгоритм). Red Hat предупреждает о возможном влиянии на производительность kTLS и IPsec.

Статус патчей по дистрибутивам​

Upstream-фикс - коммит a664bf3d603d, откатывающий in-place оптимизацию 2017 года.

ДистрибутивAdvisoryВерсия ядраДата
RHEL 10RHSA-2026:13566kernel-0:6.12.0-124.55.1.el10_12026-05-04
Debian bookwormDSA-6243-1linux 6.1.170-12026-05-01
Debian trixieDSA-6238-1linux 6.12.85-12026-04-30
Ubuntu noble (NVIDIA)USN-8289-1linux-nvidia 6.8.0-1054.572026-05-20
Ubuntu focalUSN-8280-1linux 5.4.0-230.2502026-05-19
Ubuntu bionicUSN-8281-1linux 4.15.0-250.2622026-05-19

RHEL 6 и RHEL 7 не затронуты, согласно Red Hat Security Advisory.

Хронология раскрытия​

Для понимания окна экспозиции - ключевые даты по данным RHSB-2026-002:
  • 23 марта 2026 - исследователь связывается с upstream.
  • 1 апреля - патч принят в mainline.
  • 22 апреля - CVE опубликован.
  • 29 апреля - публичный блог, PoC, Metasploit-модуль.
  • 1 мая - CISA добавляет в KEV.
  • 4 мая - первый фикс для RHEL-9 выпущен.
Между публикацией PoC и первым патчем RHEL - пять дней. Пять дней, когда Metasploit-модуль уже работал, а фикса не было.

Чеклист для эксплуатации​

Для передачи в отдел эксплуатации - конкретные действия:
  1. Определить версию ядра на всех Linux-хостах: uname -r.
  2. Проверить наличие модуля: lsmod | grep algif_aead (loadable) или cat /proc/crypto | grep authenc (built-in).
  3. Если патч недоступен - применить initcall_blacklist=algif_aead_init в параметрах загрузки.
  4. Если модуль загружаемый - выгрузить через rmmod и заблокировать через modprobe.d.
  5. Настроить auditd-правило на AF_ALG (syscall socket с a0=0x26).
  6. Проверить kernel logs за последние 48 часов на следы эксплуатации.
  7. Для контейнерных сред - оценить runtime: shared kernel (Docker default) или изолированный (gVisor, kata, Firecracker).
  8. Применить патч ядра при первой возможности.
  9. Верифицировать: после обновления попытка bind() к authencesn через AF_ALG должна использовать safe path без in-place оптимизации.
Девять лет этот баг жил в ядре. Подсистему crypto/ ревьюили десятки разработчиков, и каждый смотрел как криптограф: корректность шифрования, побочные каналы, валидация параметров. Вопрос «а должна ли страница памяти, пришедшая через splice(), оказаться в writable-части scatterlist» - из другой дисциплины. И он не пришёл в голову никому. Copy Fail - не провал code review. Это системное слепое пятно на стыке крипто и управления памятью. И оно будет повторяться, потому что ядро Linux содержит десятки подобных стыков, где одна подсистема доверяет инвариантам другой без явной проверки.

Theori заявляет, что Xint Code нашёл баг за час с одного промпта. Если стоимость обнаружения kernel-grade linux privilege escalation упала на порядок - а публичные PoC-репозитории Copy Fail уже набрали суммарно более 800 звёзд на GitHub - бюджетирование ядерных LPE как «редких событий» больше не работает. EPSS Copy Fail пока 0.0257, намного ниже Dirty COW (0.9418) или Dirty Pipe (0.8121), но Metasploit-модуль с первого дня и CISA KEV не оставляют двусмысленности. Следующий Copy Fail - вопрос месяцев. Готовиться к нему стоит не патчами задним числом, а мониторингом крипто-подсистемы, которую большинство команд до сих пор считает «чужой территорией». Проверьте свои хосты по чеклисту из раздела выше - lsmod | grep algif_aead покажет, есть ли у вас проблема, за десять секунд.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab