Перейти к содержимому
Владислав Павлович — Системный администратор Linux — Обозреватель Интернета
CVE-2026-98432: уязвимость в TCP ядра Linux — проверка и временная защита — Блог

CVE-2026-98432: уязвимость в TCP ядра Linux — проверка и временная защита

#linux#security#kernel#network

В конце октября клиенты массово пошли в тикеты с одним и тем же вопросом: «Мне нужно что-то делать с CVE-2026-98432? Если да — сделаете?». За пару дней я разобрал этот вопрос на десятках серверов — от свежих Ubuntu 24.04 до CentOS 6 с ядром, собранным руками ещё в 2015-м. Собрал всё в одну статью: что за дыра, кого касается, как проверить сервер и как закрыть её, пока нет патча.

Важно!
Статус патчей у дистрибутивов меняется буквально каждый день. Всё, что написано про «есть фикс / нет фикса» — актуально на 3 ноября 2026. Перед работой проверяйте трекер своего дистрибутива (ссылки в конце).

1. Что за уязвимость

CVE-2026-98432 — use-after-free в коде TCP-хендшейка IPv4 ядра Linux. Баг живёт в ядре начиная с версии 4.4. Kernel CVE team опубликовала CVE 15 октября и оценила её в 9.8 из 10: атака по сети, без авторизации, без каких-либо действий со стороны пользователя.

Коротко о механике:

  • Когда приходит SYN с IPv4-опциями (Record Route или Timestamp), ядро сохраняет эти опции вместе с полуоткрытым соединением.
  • Когда хендшейк завершается, указатель на опции передаётся новому сокету без копирования — обе структуры смотрят в одну и ту же память.
  • Если в этот момент другое ядро процессора обрабатывает повторный SYN для того же соединения, оно может прочитать уже освобождённую память.

Фикс в апстриме простой — коммит Эрика Дюмазе ipv4: free inet_opt and ireq_opt after an RCU grace period заменяет два kfree() на kfree_rcu().

Что важно для практики:

  • IPv6 не затронут — там опции копируются.
  • Обычный трафик IP-опций не несёт. Без специально сформированного пакета баг не триггерится.
  • Есть второй путь атаки — через net.ipv4.tcp_migrate_req=1 или eBPF-программы типа sk_reuseport. По умолчанию он закрыт.

2. Почему шум именно сейчас

Об уязвимости сообщил исследователь Anthropic Xinyang Ge, а 27 октября Anthropic рассказала, что их модель написала рабочий эксплойт удалённого root для этой уязвимости. Эксплойт работал против сервера с MPTCP-слушателем (Multipath TCP). Сам эксплойт не опубликован, атак «в дикой природе» на момент написания не зафиксировано, в каталоге CISA KEV уязвимости нет.

После этого хостеры начали рассылать уведомления, клиенты — писать в поддержку, а поддержка — гуглить. Отсюда и поток тикетов.

Про MPTCP

В статьях пишут, что эксплойт работает только при наличии MPTCP. Это полуправда:

  • Публичная демонстрация действительно использовала MPTCP-слушатель.
  • Сам баг — в обычном IPv4 TCP. В описании CVE про MPTCP ни слова.

MPTCP-слушатели встречаются чаще, чем кажется: начиная с Go 1.24 программы на Go слушают через MPTCP по умолчанию, если ядро это разрешает (net.mptcp.enabled = 1). На Debian 12 и Ubuntu 26.04 он включён из коробки, а вот в AlmaLinux (и RHEL-семействе в целом) MPTCP по умолчанию выключен.

Совет
Отключение MPTCP — полезная мера, но не замена патчу. Блокировать нужно сам триггер — пакеты с IP-опциями.

3. Кто уязвим

Дистрибутив Статус (на 3 ноября) Исправленная версия / адвизори
Debian 12 bookworm Исправлено linux 6.1.190-1 (DLA-4841-1), linux-6.12 6.12.113-1~deb12u1 (DLA-4850-1)
Debian 13 trixie Исправлено 6.12.113-1 (DSA-6568-1) и новее
Debian sid Исправлено 7.2.10-1 и новее
RHEL 9 Исправлено 1 ноября RHSA-2026:93412
RHEL 10 Исправлено 1 ноября RHSA-2026:93413
RHEL 8 Частично RHSA-2026:94303 для 8.8 SAP / TUS (3 ноября), остальные потоки — смотреть на странице Red Hat
RHEL 9 kernel-rt Ещё уязвимо —
AlmaLinux 8 Исправлено 2 ноября kernel-4.18.0-553.182.1.el8_10
AlmaLinux 9 Исправлено 2 ноября kernel-5.14.0-687.64.1.el9_8
AlmaLinux 10 Исправлено 2 ноября kernel-6.12.0-211.72.1.el10_2
Ubuntu 26.10 Уязвимо, фикс в работе ожидается 7.3.0-10.10
Ubuntu 26.04 LTS Уязвимо, фикс в работе ожидается 7.0.0-43.43
Ubuntu 24.04 LTS Уязвимо, фикс в работе ожидается 6.8.0-149.149
Ubuntu 22.04 LTS Уязвимо, фикс в работе ожидается 5.15.0-203.213
Ubuntu 20.04 / 18.04 / 16.04 Уязвимо, работа над фиксом не начата —
Oracle Linux (UEK), SUSE Исправлено для большинства релизов —
Amazon Linux 2023 Частично (kernel6.12 и kernel6.18) —

Отдельно стоит отметить AlmaLinux: команда бэкпортировала фикс из stable-веток ядра сама и выпустила ядра раньше Red Hat — 30 октября в testing, 2 ноября в основной репозиторий.

С Ubuntu ситуация хуже всего: на 3 ноября ни для одного релиза исправленного ядра нет. Для облачных и специальных ядер (linux-aws, linux-azure, linux-gcp, linux-kvm, HWE) — свои строки в трекере и свои номера версий, проверяйте именно свой вариант.

Red Hat поначалу оценивал уязвимость как Important, но затем поднял до Critical, 9.8 — тот же балл, что у kernel CVE team.

Если собираете ядро сами — фикс есть в 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10 и всех 7.3+ (апстрим-коммит e3f33b0a1d89, попал в 7.3-rc7).

Частные случаи из тикетов

Ядро старше 4.4 — не уязвимо. Попался CentOS 6 с ванильным ядром 3.17.0. Бага там нет — он появился позже. Но радоваться нечему: ядро 3.17 не получает исправлений с 2015 года, и дыр в нём хватает и без этой CVE.

Важно!
Для штатных ядер дистрибутивов (например, 2.6.32-xxx.el6 или 4.18.0-xxx.el8) номер версии ни о чём не говорит. Red Hat и Canonical бэкпортят код в старые ядра, поэтому смотреть нужно в changelog пакета, а не на uname -r.

OpenVZ / LXC контейнеры. Ядро общее с нодой. Внутри контейнера ничего не исправить — проверять и обновлять нужно ноду.

Сервер только что перезагружали «из-за CVE». Перезагрузка на то же самое ядро ничего не даёт. На Ubuntu 20.04 клиент перезагрузился на 5.4.0-216 — фикса там нет.

4. Как проверить сервер

Версия ядра и наличие фикса

Debian / Ubuntu — ищем CVE в changelog работающего ядра:

script.sh - Блокнот
uname -r
zgrep -c CVE-2026-98432 /usr/share/doc/linux-modules-$(uname -r)/changelog.Debian.gz

RHEL / AlmaLinux / Rocky:

script.sh - Блокнот
uname -r
rpm -q --changelog kernel-core-$(uname -r) | grep -c CVE-2026-98432

Если результат больше 0 — работающее ядро уже исправлено.

Есть ли фикс в репозитории

script.sh - Блокнот
# Debian / Ubuntu
apt update && apt list --upgradable 2>/dev/null | grep linux-image

# RHEL / AlmaLinux / Rocky
dnf updateinfo list --cve CVE-2026-98432

MPTCP и второй путь атаки

script.sh - Блокнот
# 1 — приложения могут открывать MPTCP-сокеты
sysctl net.mptcp.enabled

# Список MPTCP-слушателей и процессов
ss -lnMp

# Должно быть 0
sysctl net.ipv4.tcp_migrate_req

Не было ли уже попыток

script.sh - Блокнот
dmesg -T | grep -iE 'ip_options_build|inet_sock_destruct|tcp_v4_reqsk_destructor'

Если в логе ядра есть oops или KASAN-репорты с этими функциями — это уже инцидент. Сохраните логи и посмотрите на подозрительные процессы и исходящие соединения, прежде чем просто патчить.

5. Если фикс есть — обновляемся

script.sh - Блокнот
# Debian / Ubuntu
apt update && apt full-upgrade

# RHEL / AlmaLinux / Rocky
dnf clean metadata && dnf upgrade

reboot

После перезагрузки обязательно проверьте uname -r — пока сервер не перезагружен, работает старое ядро.

Совет
Если dnf не видит новое ядро — дело, скорее всего, в зеркале. Большинство зеркал синхронизируются раз в несколько часов, просто повторите позже.

6. Если фикса нет — блокируем триггер

Пока дистрибутив не выпустил ядро, закрываем уязвимость на уровне файрвола: дропаем входящие IPv4 TCP-пакеты с IP-опциями. Эту же меру рекомендует Red Hat.

Логика простая: IPv4-заголовок без опций всегда 20 байт, то есть поле hdrlength равно 5 (оно считается в 4-байтовых словах). Всё, что больше 5 — пакет с опциями.

nftables (Debian 10+, Ubuntu 20.04+, RHEL/Alma 8+)

script.sh - Блокнот
nft -f - <<'EOF'
add table ip cve_2026_98432
delete table ip cve_2026_98432
table ip cve_2026_98432 {
    chain pre {
        type filter hook prerouting priority -300; policy accept;
        meta l4proto tcp ip hdrlength > 5 counter drop
    }
}
EOF

Это вариант из блога AlmaLinux: его можно запускать сколько угодно раз — таблица пересоздаётся, а не дублируется. Если nft нет — apt install nftables или dnf install nftables.

У Canonical в трекере свой вариант: таблица inet, хук input с приоритетом -310, а для сохранения после перезагрузки — include "/etc/cve-2026-98432.nft" в /etc/nftables.conf. Разница в том, что input фильтрует только трафик к самому хосту, а prerouting — ещё и транзитный, и трафик, который идёт в контейнеры через хост. Для обычного веб-сервера оба варианта рабочие. Сама Canonical честно пишет: правило снижает риск, но не исключает эксплуатацию полностью.

Проверка (счётчик показывает, сколько пакетов уже отброшено):

script.sh - Блокнот
nft list table ip cve_2026_98432

Почему отдельная таблица: она живёт сама по себе и не пересекается с ufw, firewalld или правилами, которые генерируют ISPmanager и FastPanel. Панель перезапишет свои цепочки — наша таблица останется. priority -300 — правило срабатывает до conntrack.

iptables (CentOS 7 и всё старое)

script.sh - Блокнот
iptables -t raw -I PREROUTING -p tcp -m u32 --u32 "0>>24&0xF=6:15" -j DROP
iptables -t raw -L PREROUTING -n -v

0>>24&0xF — это поле IHL из первого байта заголовка, 6:15 — длина заголовка больше 20 байт.

Отключаем MPTCP

script.sh - Блокнот
echo 'net.mptcp.enabled = 0' > /etc/sysctl.d/90-mptcp.conf
sysctl -w net.mptcp.enabled=0

Важно!
Этот параметр запрещает только новые MPTCP-сокеты. Уже открытые слушатели продолжат работать через MPTCP — сервисы из ss -lnMp нужно перезапустить. Для Go-приложений есть отдельный рубильник: переменная окружения GODEBUG=multipathtcp=0.

7. Чтобы правило пережило перезагрузку

Правило nft, добавленное командами, пропадёт после ребута. Самый надёжный способ — отдельный systemd-юнит.

Файл правила /etc/cve-2026-98432.nft:

readme.txt - Блокнот
table ip cve_2026_98432
delete table ip cve_2026_98432
table ip cve_2026_98432 {
  chain pre {
    type filter hook prerouting priority -300; policy accept;
    meta l4proto tcp ip hdrlength gt 5 counter drop
  }
}

Первые две строки — трюк для идемпотентности: таблица создаётся пустой и сразу удаляется, поэтому файл можно применять повторно без ошибки «table exists».

Юнит /etc/systemd/system/cve-2026-98432.service:

config.ini - Блокнот
[Unit]
Description=CVE-2026-98432 mitigation (drop IPv4 TCP with IP options)
After=network-pre.target nftables.service firewalld.service
PartOf=nftables.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/nft -f /etc/cve-2026-98432.nft
ExecStop=/usr/sbin/nft delete table ip cve_2026_98432

[Install]
WantedBy=multi-user.target nftables.service
script.sh - Блокнот
systemctl daemon-reload
systemctl enable --now cve-2026-98432

PartOf и WantedBy=nftables.service нужны, чтобы правило поднималось заново после systemctl restart nftables — иначе рестарт файрвола его снесёт.

Для CentOS 7 с iptables проще сохранить правила штатно:

script.sh - Блокнот
service iptables save

Совет
service iptables save сохраняет всё текущее состояние, включая правила, которые кто-то добавил руками «на время». Перед сохранением посмотрите iptables-save и сравните с /etc/sysconfig/iptables.

На системах без systemd (CentOS 6 и подобные) подойдёт и @reboot в crontab root.

8. Побочные эффекты

  • На сайты, SSH, почту и базы правило не влияет — нормальный трафик IP-опций не содержит. RFC 7126 вообще рекомендует роутерам дропать пакеты с Record Route и Timestamp.
  • IPv6, UDP и ICMP не затрагиваются.
  • Правило защищает сам хост и контейнеры, трафик в которые идёт через него (по умолчанию так у Docker и Podman). Трафик между контейнерами на одном хосте может его обходить.
  • Не ставьте правило на сетях с CIPSO / NetLabel (SELinux labeled networking) — там IP-опции используются штатно.
  • Если сервер маршрутизирует трафик для других машин, транзитные TCP-пакеты с опциями тоже будут отброшены.

9. Когда выйдет патч

  1. Обновляем ядро, перезагружаемся.
  2. Проверяем changelog работающего ядра (раздел 4).
  3. Снимаем правило:
script.sh - Блокнот
systemctl disable --now cve-2026-98432
rm -f /etc/systemd/system/cve-2026-98432.service /etc/cve-2026-98432.nft
systemctl daemon-reload

Отключённый MPTCP можно оставить — на обычном веб-сервере он не нужен.

Заключение

Порядок действий на любом сервере:

  • Ядро старше 4.4 или контейнер → эта CVE не про вас (но про контейнер — спросите хостера про ноду).
  • Фикс есть в репозитории → обновиться и перезагрузиться.
  • Фикса нет → правило nft/iptables + отключить MPTCP + сделать правило постоянным.
  • Вышел фикс → обновиться, перезагрузиться, снять правило.

Правило файрвола снижает риск, но не убирает баг из ядра. Это временная мера, а не решение.

Список литературы

cve-2026-98432-uiazvimost-v-tcp-iadra-linux-proverka-i-vremennaia-zashchita.md
11 мин
Просмотров: 1

Комментарии (0)

Комментариев пока нет. Будьте первым!

Оставить комментарий
Готово
Интернет