ПублікаціїCVE-2026-31431 (Copy Fail): як Appbox зменшив ризики

CVE-2026-31431 (Copy Fail): як Appbox зменшив ризики

5 хв читання
від rid

Минулого тижня було розкрито серйозну ваду ядра Linux, CVE-2026-31431. Ось як Appbox зменшив ризики та розгорнув виправлення ядра Debian.

CVE-2026-31431 (Copy Fail) - як ми зменшили ризики

Минулого тижня було розкрито серйозну локальну ескалацію привілеїв у ядрі Linux: CVE-2026-31431, відому під назвою "Copy Fail". Вона зачіпає широкий діапазон версій ядра в сучасних дистрибутивах Linux, а публічний експлойт з'явився невдовзі після розкриття.

Хочу прямо пояснити, що сталося, що це означає для Appbox і що ми з цим зробили. Коротко: завдяки тому, як побудовані наші контейнери, застосунки, що працюють із remapping просторів імен користувачів, уже були захищені від перетворення цієї вади на host root ще до розгортання виправлених ядер. Учора (4 травня 2026 року) ми також провели екстрене обслуговування, щоб оновити кожен сервер до виправленого ядра, тож цю помилку тепер повністю усунуто з нашого парку серверів.

Що таке "Copy Fail"?

CVE-2026-31431 - це вада в криптографічному API ядра AF_ALG. Прив'язавшись до конкретного шифру (authencesn(hmac(sha256),cbc(aes))) і зловживаючи тим, як ядро вставляє сторінки в тимчасовий буфер, непривілейований локальний користувач може записувати довільні 4-байтові фрагменти безпосередньо в page cache файлів, які він не має права змінювати, зокрема SUID-бінарників на кшталт /usr/bin/su.

Щойно копію su у page cache перезаписано крихітним шкідливим ELF, наступний запуск виконує код атакувальника як UID 0. Для хоста це кінець гри.

Для суворих технічних подробиць (дизасемблювання shellcode, трасування syscall і всього іншого) чудовим є матеріал Andrea Veri: CVE-2026-31431: Copy Fail vs. rootless containers. Він також продемонстрував - з доказами через eBPF і uid_map - саме те, про що ми поговоримо далі: простори імен користувачів нейтралізують цей експлойт.

Чому застосунки Appbox уже були захищені

Експлойт покладається на те, що setuid(0) справді надає root-доступ на хості. У контейнері з увімкненими просторами імен користувачів це працює не так.

Простори імен користувачів відображають UID-простір контейнера на інший (непривілейований) діапазон UID на хості. Тому, коли експлойт успішно спрацьовує всередині контейнера і setuid(0) повертає успіх, отримана "root" shell відображається на звичайного непривілейованого користувача хоста, а не на справжнього root. Shellcode виконується, prompt змінюється на #, але на хості:

podman     27943  0.0  0.0   2984  2028 pts/1    S+   22:15   0:00 sleep 100

І все. Немає доступу до файлів хоста, немає /etc/shadow, немає root-доступу на хості. Межа простору імен контейнера не дає цьому перетворитися на втечу з правами root на хості.

На рівні платформи кожен Appbox отримує власний Docker daemon, запущений із увімкненим remapping просторів імен користувачів. У псевдокоді це виглядає приблизно так:

start_docker_daemon(
  userns_remap = appbox_id,
  container_namespace = appbox_id
)

Це відображення підкріплене окремим підпорядкованим діапазоном UID/GID на хості:

write "/etc/subuid" -> "<appbox-id>:<host-subuid-start>:65536"
write "/etc/subgid" -> "<appbox-id>:<host-subgid-start>:65536"

Крім того, визначення застосунків усе ще можуть явно перевизначати UsernsMode, коли застосунку потрібна особлива обробка:

container_config = {
  userns_mode: app.userns_mode,
  network_mode: app.network_mode,
  ...
}

Тож точний опис такий: remapping просторів імен користувачів є частиною стандартних налаштувань платформи, а винятки для окремих застосунків задаються явно. Є невелика кількість застосунків, яким потрібні інші налаштування, бо вони надають функціональність, що потребує додаткових можливостей, і такі випадки обробляються окремо.

Інакше кажучи: для застосунків, що працюють зі звичайною remapped-конфігурацією, Copy Fail не міг перетворити компрометацію контейнера на root-доступ до хоста.

Що ми все одно хотіли виправити

Простори імен користувачів зупиняють втечу на хост, але не усувають саму помилку всередині контейнера. Атакувальник усе ще міг піднятися до "container root" у межах застосунку, що, хоч і залишалося ізольованим, усе одно є поганою практикою безпеки. Саме ядро було вразливим, і ми хотіли це усунути.

Щойно ми дізналися про помилку, ми одразу почали оцінювати наш ризик. Хоча remapping просторів імен користувачів уже блокував сторону проблеми, пов'язану з втечею на хост, для нашої звичайної конфігурації застосунків, ми все одно хотіли якнайшвидше прибрати базову помилку ядра.

Що ми зробили вчора

У неділю ввечері ми запланували екстрене обслуговування на понеділок, 4 травня 2026 року - найраніше вікно, у яке могли розгорнути оновлення ядра по всьому парку серверів.

Під час цього вікна:

  • Кожен хост було оновлено за допомогою офіційних пакетів ядра Debian, що містять виправлення "Copy Fail".
  • Мета була проста: повністю прибрати вразливий шлях у ядрі, а не лише покладатися на нашу наявну ізоляцію через простори імен.

Обслуговування завершено. Кожен хост Appbox тепер працює на виправленому ядрі.

Що це означає для вас

  • Вам не потрібно було нічого робити. Ваші застосунки продовжували працювати, а єдиним видимим для клієнтів ефектом могли бути короткі перебої під час вікна обслуговування.
  • Навіть до вчорашнього патча remapping просторів імен користувачів означав, що ця помилка не могла перетворити компрометацію звичайного застосунку на root-доступ до хоста. Саме для таких сценаріїв і існує ця модель ізоляції.
  • Надалі наша політика не змінюється: простори імен користувачів залишаються увімкненими за замовчуванням, а дуже небагато винятків проходять додатковий перегляд безпеки.

Ширший контекст

Це один із тих CVE, де заголовок ("локальна ескалація привілеїв, публічний експлойт, зачеплене кожне сучасне ядро") звучить катастрофічно, і для багатьох середовищ із кількома орендарями це справді було катастрофою. Причина, чому це не стало катастрофою для нас, та сама, через яку ми багато років тому ухвалили архітектурні рішення, що інколи коштують нам частини сумісності: ми запускаємо застосунки з принципом найменших привілеїв, вбудованим у контейнерний рівень, а не прикрученим постфактум.

Захист у глибину справді працює. Помилка на рівні ядра? Її зупинив рівень просторів імен. Помилка на рівні просторів імен? Скидання capabilities і seccomp перехоплюють більшість наслідків. Ми не вдаємо, що будь-який окремий рівень ідеальний, ми просто стежимо, щоб завжди був наступний.

Якщо у вас є запитання щодо цього або щодо конфігурації ваших конкретних застосунків, будь ласка, звертайтеся.


Є запитання? Напишіть нам на support@appbox.co або відкрийте тікет на billing.appbox.co.

rid

rid

Software Engineer | Writer | Designer