
DaemonSet для митигации уязвимости CVE-2026-64564 (SCTPhantom)
Автоматическое применение митигации для уязвимости CVE-2026-64564 (SCTPhantom) в Linux kernel на всех worker-нодах Yandex Managed Kubernetes кластера.
Идентификатор CVE (CVE ID): CVE-2026-64564
Ссылка на CVE: https://nvd.nist.gov/vuln/detail/CVE-2026-64564
Исходный отчет:
9b2854f86f0b в net/sctp/sm_make_chunk.cКраткое описание:
SCTPhantom - это use-after-free в подсистеме SCTP Dynamic Address Reconfiguration (ASCONF, RFC 5061) ядра Linux, позволяющий непривилегированному локальному пользователю получить права суперпользователя (root).
Корневая причина - расхождение идентичностей при обработке ASCONF-чанка: проверка операции DEL-IP выполняется против адреса источника IPv4-пакета (S), а дальнейшая обработка использует transport, выбранный через Address Parameter (L). Из-за этого упорядоченная последовательность
[ Address Parameter L ] [ DEL-IP L ] [ DEL-IP 0.0.0.0 ]
проходит проверку и удаляет transport(L), после чего wildcard-операция DEL-IP 0.0.0.0 переиспользует уже освобожденный указатель как «сохраняемый путь». В результате asoc->peer.primary_path и asoc->peer.active_path остаются висячими указателями на освобожденный struct sctp_transport, а последующий вызов getsockopt(SCTP_STATUS) разыменовывает их.
Уязвимая логика была внесена в Linux 2.6.25 (2007 год, commit 42e30bf3463c), то есть присутствует в ядре около 18 лет.
Атака:
CAP_NET_ADMIN и CAP_SYS_ADMIN, работает при активном default seccomp-профиле; ASCONF и AUTH включаются per-socket через SCTP_ASCONF_SUPPORTED / SCTP_AUTH_SUPPORTED, поэтому sysctl net.sctp.addip_enable менять не нужноcall_usermodehelper_exec(), который запускает процесс в initial namespaces хостаkernel panic, что затрудняет детектcommit_creds()), без shellcode и классического ROPЗатронутые технологии:
net/sctp (модуль sctp), обработка ASCONF в net/sctp/sm_make_chunk.csctp_diag (зависит от sctp), используется для инспекции SCTP-сокетовУязвимость эксплуатируется только при доступности SCTP: если модуль sctp не загружен и его автозагрузка заблокирована, вектор недоступен.
Подтвержденные авторами цели (получен root):
| Дистрибутив | Ядро |
|---|---|
| Research kernel | Linux 7.2-rc2 |
| OpenCloudOS-family | 6.6.119 |
| Debian 13 | 6.12.95+deb13-amd64 |
| Rocky Linux 9 / RHEL 9 | 5.14 vendor kernel (при загруженном модуле sctp) |
| Ubuntu 24.04 | 6.8.0-134-generic |
Исправленные версии ядра:
| Ветка | Первая исправленная версия | Stable-фикс |
|---|---|---|
| 6.6.y | 6.6.148 | fedeb4468987 |
| 6.12.y | 6.12.101 | 74e8f3e7114f |
| 6.18.y | 6.18.42 | 85aca407c560 |
| 7.1.y | 7.1.6 | d136b29bf91d |
| mainline | 7.2-rc5 | 9b2854f86f0b |
Вендорные ядра могут содержать бэкпорт фикса при более старой версии в строке версии - сама версия ядра не является достаточным признаком уязвимости, ориентируйтесь на advisory или исходники вендора.
Вектор атаки и уровень опасности согласно CVSS v.4.0:
Базовая оценка: 8.5 (HIGH)
Вектор: CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
DaemonSet автоматически на каждой worker ноде кластера:
sctp и sctp_diag, и с каким refcnt. Проверка намеренно пассивная: DaemonSet не открывает SCTP-сокет до установки блеклиста, чтобы не спровоцировать автозагрузку модуля на ноде, где он еще не загруженrefcnt модуля и живые записи в /proc/net/sctp/assocs и /proc/net/sctp/eps. Сам Kubernetes SCTP не использует, но пользовательская нагрузка может объявлять protocol: SCTP в Service/Pod/etc/modprobe.d/blacklist-sctp.conf с правилами install и blacklist для sctp и sctp_diagrmmod для sctp_diag, затем sctp (порядок важен: sctp_diag зависит от sctp). Если обнаружены живые SCTP-соединения, выгрузка пропускается, если явно не задан FORCE_APPLY=truemodprobe sctp отклоняется, и что создание SCTP-сокета (socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) больше не проходитМитигация состоит из двух независимых частей, и на части нод применяется только одна из них.
1. Блеклист (применяется всегда, надежно). После создания /etc/modprobe.d/blacklist-sctp.conf модуль sctp больше не может быть загружен - ни автоматически при socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP), ни явным modprobe. Это закрывает вектор на нодах, где модуль еще не был загружен (типичное состояние: SCTP не используется Kubernetes и загружается только по требованию).
2. Выгрузка модуля из памяти (не всегда возможна). Если sctp уже был загружен, выгрузить его чаще всего не получится. На проверенных нодах Yandex Managed Kubernetes (Ubuntu 22.04, ядро 5.15.0-181-generic) свежезагруженный и никем не используемый модуль sctp уже имеет refcnt=6 при пустом списке holders и пустых /proc/net/sctp/{assocs,eps}, и rmmod возвращает ERROR: Module sctp is in use. Счетчик со временем не уменьшается.
Отсюда два следствия:
refcnt не является признаком использования SCTP - DaemonSet выводит его только информационно, а решение о выгрузке принимает по живым записям в /proc/net/sctp/assocs и /proc/net/sctp/epssctp уже резидентен, DaemonSet честно сообщает ⚠ mitigation applied PARTIALLY. Блеклист там уже стоит (после перезагрузки модуль не вернется), но до перезагрузки нода остается уязвимой. Для полного закрытия вектора такие ноды нужно перезагрузить или пересоздать node groupНайти такие ноды после раскатки:
kubectl logs -n kube-system -l app=cve-2026-64564-fix -c apply-fix --prefix | grep -E 'PARTIALLY|STILL LOADED'
Важно: митигация полностью отключает SCTP на ноде.
Kubernetes и сетевые плагины (Cilium, Calico) SCTP для собственной работы не используют, поэтому для абсолютного большинства кластеров митигация безопасна. Однако если в кластере есть нагрузка, использующая SCTP (например, телеком-приложения, VoIP/сигнализация SS7/Diameter, Service или NetworkPolicy с protocol: SCTP), её трафик перестанет работать.
Проверить, есть ли такие объекты в кластере, перед раскаткой:
# Service / Pod с protocol: SCTP
kubectl get svc -A -o json | jq -r '.items[] | select(.spec.ports[]?.protocol=="SCTP") | "\(.metadata.namespace)/\(.metadata.name)"'
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[].ports[]?.protocol=="SCTP") | "\(.metadata.namespace)/\(.metadata.name)"'
# NetworkPolicy с protocol: SCTP
kubectl get netpol -A -o json | jq -r '.items[] | select((.spec.ingress[]?.ports[]?.protocol=="SCTP") or (.spec.egress[]?.ports[]?.protocol=="SCTP")) | "\(.metadata.namespace)/\(.metadata.name)"'