Автоматическое применение митигации для уязвимости 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
Исходный отчет:
- Технический write-up (Tencent Zhuque Lab / Corvus AI): https://matrix.tencent.com/en/2026/08/06/sctphantom-CVE-2026-64564
- Публичный PoC (LPE под Debian 13, ядро 6.12.95): https://github.com/ethanolgolf/CVE-2026-64564
- Upstream-фикс (mainline): commit
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, поэтому sysctlnet.sctp.addip_enableменять не нужно - является рабочим примитивом побега из контейнера на хост: авторы получили host-root в 6 из 8 попыток, финальный шаг -
call_usermodehelper_exec(), который запускает процесс в initial namespaces хоста - при неудачной эксплуатации завершается «чисто», без
kernel panic, что затрудняет детект - эксплойт-цепочка переиспользует существующий код ядра (data-oriented
commit_creds()), без shellcode и классического ROP
Затронутые технологии:
- Ядро Linux, подсистема
net/sctp(модульsctp), обработкаASCONFвnet/sctp/sm_make_chunk.c - Модуль
sctp_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-сокет до установки блеклиста, чтобы не спровоцировать автозагрузку модуля на ноде, где он еще не загружен - Проверяет, используется ли 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_diag - Выгружает модули - выполняет
rmmodдляsctp_diag, затемsctp(порядок важен:sctp_diagзависит отsctp). Если обнаружены живые SCTP-соединения, выгрузка пропускается, если явно не заданFORCE_APPLY=true - Верифицирует митигацию - проверяет наличие конфигурации, что
modprobe 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/eps- на ноде, где
sctpуже резидентен, 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)"'Если SCTP на ноде используется, DaemonSet по умолчанию не выгружает модуль из памяти, а только ставит блеклист (модуль не вернется после перезагрузки ноды) и пишет предупреждение в логи. Чтобы выгрузить принудительно, оборвав существующие SCTP-соединения, установите в манифесте:
env:
- name: FORCE_APPLY
value: "true"wget https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-sctphantom-mitigation/main/sctphantom-mitigation-daemonset.yamlИли клонировать репозиторий:
git clone https://github.com/yandex-cloud-examples/yc-mk8s-sctphantom-mitigation.git
cd yc-mk8s-sctphantom-mitigationkubectl apply -f sctphantom-mitigation-daemonset.yaml# Проверить статус DaemonSet
kubectl get daemonset -n kube-system cve-2026-64564-fix
# Посмотреть на скольких нодах применен фикс
kubectl get pods -n kube-system -l app=cve-2026-64564-fix -o wide# Логи initContainer (применение фикса)
kubectl logs -n kube-system -l app=cve-2026-64564-fix -c apply-fix
# Логи основного контейнера (мониторинг)
kubectl logs -n kube-system -l app=cve-2026-64564-fix -c monitorkubectl logs -n kube-system -l app=cve-2026-64564-fix -c apply-fix --prefix | grep -E 'PARTIALLY|STILL LOADED|Skipping'=========================================
SCTPhantom (CVE-2026-64564) mitigation for Yandex Managed K8s
Node: demo-ru-central1-a-1
Date: Mon Aug 10 14:00:00 UTC 2026
FORCE_APPLY: false
=========================================
Step 1: Checking modules state before fix...
[LOADED] sctp (refcnt=0) - node is exposed
[UNLOADED] sctp_diag
Step 2: Checking whether SCTP is in use on this node...
✓ No SCTP usage detected (expected: Kubernetes itself does not use SCTP)
Step 3: Applying the mitigation...
Created /etc/modprobe.d/blacklist-sctp.conf
Step 4: Unloading vulnerable modules...
sctp_diag was not loaded (OK)
sctp unloaded
Step 5: Validating the configuration...
Configuration file is in place:
install sctp /bin/false
install sctp_diag /bin/false
blacklist sctp
blacklist sctp_diag
Step 6: Validating that the modules can no longer be loaded...
modprobe sctp_diag is blocked ✓
modprobe sctp is blocked ✓
SCTP socket creation is blocked ✓
Step 7: Validating modules state after fix...
[UNLOADED] sctp_diag ✓
[UNLOADED] sctp ✓
=========================================
✓ CVE-2026-64564 mitigation applied successfully
=========================================
Step 1: Checking modules state before fix...
[UNLOADED] sctp_diag
[LOADED] sctp (refcnt=6) - node is exposed
Step 2: Checking whether SCTP is in use on this node...
sctp is loaded, refcnt=6 (informational only)
✓ No SCTP usage detected (expected: Kubernetes itself does not use SCTP)
Step 4: Unloading vulnerable modules...
sctp_diag was not loaded (OK)
⚠ could not unload sctp (see the note about refcnt below)
Step 6: Validating that the modules can no longer be loaded...
modprobe sctp_diag is blocked ✓
sctp is still resident, skipping the modprobe test
⚠ SCTP socket still available: the sctp module is still resident and could not be unloaded
Step 7: Validating modules state after fix...
[UNLOADED] sctp_diag ✓
[STILL LOADED] sctp (refcnt=6) - WARNING: module could not be unloaded
=========================================
⚠ CVE-2026-64564 mitigation applied PARTIALLY
...
In that case reboot the node or recreate the node group to close the vector.
=========================================
Такую ноду нужно перезагрузить: блеклист уже не даст модулю загрузиться заново.
Наиболее показательная проверка - воспроизвести позицию атакующего: непривилегированный под со сброшенными capabilities, как в цепочке container escape.
NODE=<имя ноды>
kubectl run sctp-check --rm -i --restart=Never --image=python:3-slim \
--overrides="{\"spec\":{\"nodeName\":\"$NODE\",\"containers\":[{\"name\":\"c\",\"image\":\"python:3-slim\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]}},\"command\":[\"python3\",\"-c\",\"import socket\ntry:\n socket.socket(socket.AF_INET, socket.SOCK_STREAM, 132).close()\n print('SCTP REACHABLE -> EXPLOITABLE')\nexcept OSError as e:\n print('SCTP BLOCKED:', e)\"]}]}}"Ожидаемый вывод на защищенной ноде:
SCTP BLOCKED: [Errno 93] Protocol not supported
На незащищенной ноде вывод будет SCTP REACHABLE -> EXPLOITABLE, и сама проверка приведет к автозагрузке модуля sctp на этой ноде (после чего выгрузить его, скорее всего, уже не удастся - см. раздел выше). Не запускайте её на незащищенных нодах без необходимости.
Вы можете проверить состояние ноды вручную. Подключитесь к ноде по SSH и выполните:
# Загружены ли уязвимые модули
lsmod | grep -E '^sctp'
# sctp 447488 0 <- refcount 0, можно выгружать
# Доступен ли SCTP-сокет (основной вектор автозагрузки модуля)
python3 -c 'import socket; socket.socket(socket.AF_INET, socket.SOCK_STREAM, 132); print("SCTP available - VULNERABLE")'
# Если выводит "SCTP available - VULNERABLE" - система уязвима
# Если выдает ошибку - система защищенаВнимание: запуск этой проверки на ноде, где модуль еще не загружен, сам приведет к его автозагрузке. Выполняйте её только после применения митигации либо сознательно.
Проверить конфигурацию:
# Проверить наличие конфигурации блокировки
cat /etc/modprobe.d/blacklist-sctp.conf
# Ожидаемый вывод:
# install sctp /bin/false
# install sctp_diag /bin/false
# blacklist sctp
# blacklist sctp_diagПроверить, что уязвимые модули не загружены:
lsmod | grep -cE '^sctp'
# Ожидаемый вывод: 0Если нужно применить митигацию на обычных хостах, однострочник:
sudo sh -c 'printf "install sctp /bin/false\ninstall sctp_diag /bin/false\nblacklist sctp\nblacklist sctp_diag\n" > /etc/modprobe.d/blacklist-sctp.conf; rmmod sctp_diag 2>/dev/null; rmmod sctp 2>/dev/null; if lsmod | grep -qE "^sctp "; then echo "STILL-LOADED refcnt=$(cat /sys/module/sctp/refcnt)"; else echo "UNLOADED-OK"; fi'Если необходимо удалить DaemonSet:
kubectl delete -f sctphantom-mitigation-daemonset.yamlВажно: Удаление DaemonSet не удалит конфигурационные файлы с нод. Файл /etc/modprobe.d/blacklist-sctp.conf останется на месте и будет продолжать защищать систему.
Для полного удаления фикса с нод нужно подключиться к каждой ноде по SSH и вручную удалить файл:
rm /etc/modprobe.d/blacklist-sctp.confИспользуемые разрешения:
hostPID: true- для доступа к процессам хоста через nsenterprivileged: true- для записи в/etcи выгрузки модулей ядра- Volume mount
/- для доступа к файловой системе хоста
Образ: ubuntu:22.04
Ресурсы:
- Init container: 10m CPU / 64Mi RAM (requests), 200m CPU / 128Mi RAM (limits)
- Monitor container: 5m CPU / 32Mi RAM (requests), 50m CPU / 64Mi RAM (limits)
Namespace: kube-system
Почему в конфиге и install, и blacklist: blacklist блокирует загрузку по alias'у (в том числе автозагрузку при socket(..., IPPROTO_SCTP)), но не мешает явному modprobe sctp. Строка install sctp /bin/false закрывает и этот путь.
Почему митигация - не замена обновлению ядра: блокировка модуля устраняет вектор, но сам баг остается в ядре. Постоянное решение - обновление ядра до исправленной версии (см. таблицу выше) либо обновление образов нод и пересоздание node group.
- ✓ Yandex Managed Kubernetes
- ✓ Ubuntu 20.04
- ✓ Ubuntu 22.04
- ✓ Kubernetes 1.20+
Apache License 2.0
См. LICENSE для подробностей.
При возникновении проблем создайте issue в репозитории.