
DaemonSet zur Mitigation der Schwachstelle CVE-2026-64564 (SCTPhantom)
Automatische Anwendung der Mitigation für die Schwachstelle CVE-2026-64564 (SCTPhantom) im Linux-Kernel auf allen Worker-Knoten des Yandex Managed Kubernetes Clusters.
CVE-Kennung (CVE-ID): CVE-2026-64564
Link zum CVE: https://nvd.nist.gov/vuln/detail/CVE-2026-64564
Ursprünglicher Bericht:
9b2854f86f0b in net/sctp/sm_make_chunk.cKurzbeschreibung:
SCTPhantom ist ein Use-after-Free in dem Linux-Kernel-Subsystem SCTP Dynamic Address Reconfiguration (ASCONF, RFC 5061), das einem unprivilegierten lokalen Benutzer ermöglicht, Superuser-Rechte (root) zu erlangen.
Die Grundursache ist ein Identitätskonflikt bei der Verarbeitung des ASCONF-Chunks: Die Prüfung der DEL-IP-Operation erfolgt gegen die Quelladresse des IPv4-Pakets (S), während die weitere Verarbeitung den über den Address Parameter (L) gewählten transport verwendet. Dadurch passiert die geordnete Sequenz
[ Address Parameter L ] [ DEL-IP L ] [ DEL-IP 0.0.0.0 ]
die Prüfung und löscht transport(L), woraufhin die Wildcard-Operation DEL-IP 0.0.0.0 den bereits freigegebenen Zeiger als „gespeicherten Pfad" wiederverwendet. Infolgedessen bleiben asoc->peer.primary_path und asoc->peer.active_path hängende Zeiger auf den freigegebenen struct sctp_transport, und ein anschließender Aufruf von getsockopt(SCTP_STATUS) dereferenziert sie.
Die anfällige Logik wurde in Linux 2.6.25 eingeführt (2007, Commit 42e30bf3463c), ist also seit etwa 18 Jahren im Kernel vorhanden.
Angriff:
CAP_NET_ADMIN und CAP_SYS_ADMIN, funktioniert mit aktivem Standard-Seccomp-Profil; ASCONF und AUTH werden pro Socket über SCTP_ASCONF_SUPPORTED / SCTP_AUTH_SUPPORTED aktiviert, daher muss der Sysctl net.sctp.addip_enable nicht geändert werdencall_usermodehelper_exec(), das einen Prozess in den initialen Namespaces des Hosts startetkernel panic, was die Erkennung erschwertcommit_creds()), ohne Shellcode und klassisches ROPBetroffene Technologien:
net/sctp (Modul sctp), Verarbeitung von ASCONF in net/sctp/sm_make_chunk.csctp_diag (hängt von sctp ab), wird zur Inspektion von SCTP-Sockets verwendetDie Schwachstelle ist nur ausnutzbar, wenn SCTP verfügbar ist: Wenn das Modul sctp nicht geladen und dessen Autoload blockiert ist, ist der Vektor nicht verfügbar.
Von den Autoren bestätigte Ziele (Root erlangt):
| Distribution | Kernel |
|---|---|
| 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 (bei geladenem Modul sctp) |
| Ubuntu 24.04 | 6.8.0-134-generic |
Korrigierte Kernel-Versionen:
| Branch | Erste korrigierte Version | Stable-Fix |
|---|---|---|
| 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 |
Vendor-Kernel können einen Backport des Fixes bei einer älteren Versionsnummer enthalten – die Kernel-Version allein ist kein hinreichendes Indiz für die Schwachstelle; orientieren Sie sich an den Advisories oder den Quellen des Vendors.
Angriffsvektor und Gefährdungsgrad gemäß CVSS v.4.0:
Basisscore: 8.5 (HIGH)
Vektor: 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
Der DaemonSet führt auf jedem Worker-Knoten des Clusters automatisch Folgendes aus:
sctp und sctp_diag geladen sind und mit welchem refcnt. Die Prüfung ist bewusst passiv: Der DaemonSet öffnet keinen SCTP-Socket, bevor die Blacklist eingerichtet ist, um das Laden des Moduls auf einem Knoten, auf dem es noch nicht geladen ist, nicht auszulösen.refcnt des Moduls und die aktiven Einträge in /proc/net/sctp/assocs und /proc/net/sctp/eps. Kubernetes selbst nutzt SCTP nicht, aber eine benutzerdefinierte Workload kann protocol: SCTP in Service/Pod deklarieren./etc/modprobe.d/blacklist-sctp.conf mit install- und blacklist-Regeln für sctp und sctp_diag.rmmod für sctp_diag und dann für sctp aus (die Reihenfolge ist wichtig: sctp_diag hängt von sctp ab). Wenn aktive SCTP-Verbindungen erkannt werden, wird das Entladen übersprungen, sofern nicht explizit FORCE_APPLY=true gesetzt ist.modprobe sctp abgelehnt wird und ob das Erstellen eines SCTP-Sockets (socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) nicht mehr möglich ist.Die Mitigation besteht aus zwei unabhängigen Teilen, und auf einigen Knoten wird nur einer von ihnen angewendet.
1. Blacklist (wird immer zuverlässig angewendet). Nach der Erstellung von /etc/modprobe.d/blacklist-sctp.conf kann das Modul sctp nicht mehr geladen werden – weder automatisch bei socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP) noch durch explizites modprobe. Dies schließt den Vektor auf Knoten, auf denen das Modul noch nicht geladen war (typischer Zustand: SCTP wird von Kubernetes nicht verwendet und nur bei Bedarf geladen).
2. Entladen des Moduls aus dem Speicher (nicht immer möglich). Wenn sctp bereits geladen ist, lässt es sich meist nicht entladen. Auf getesteten Yandex Managed Kubernetes-Knoten (Ubuntu 22.04, Kernel 5.15.0-181-generic) hat ein frisch geladenes und von niemandem verwendetes Modul sctp bereits refcnt=6 bei leerer Holder-Liste und leeren /proc/net/sctp/{assocs,eps}, und rmmod gibt ERROR: Module sctp is in use zurück. Der Zähler nimmt mit der Zeit nicht ab.
Daraus ergeben sich zwei Konsequenzen:
refcnt ist kein Indikator für die SCTP-Nutzung – der DaemonSet gibt ihn nur informativ aus und entscheidet über das Entladen anhand der aktiven Einträge in /proc/net/sctp/assocs und /proc/net/sctp/eps.sctp bereits resident ist, meldet der DaemonSet ehrlich ⚠ mitigation applied PARTIALLY. Die Blacklist ist dort bereits aktiv (nach einem Neustart wird das Modul nicht zurückkehren), aber bis zum Neustart bleibt der Knoten verwundbar. Um den Vektor vollständig zu schließen, müssen solche Knoten neu gestartet oder die Node-Gruppe neu erstellt werden.Solche Knoten nach dem Rollout finden:
kubectl logs -n kube-system -l app=cve-2026-64564-fix -c apply-fix --prefix | grep -E 'PARTIALLY|STILL LOADED'
Wichtig: Die Mitigation deaktiviert SCTP auf dem Knoten vollständig.
Kubernetes und Netzwerk-Plugins (Cilium, Calico) verwenden SCTP nicht für den eigenen Betrieb, daher ist die Mitigation für die allermeisten Cluster unbedenklich. Wenn es jedoch im Cluster eine Workload gibt, die SCTP verwendet (z.B. Telekom-Anwendungen, VoIP/Signalisierung SS7/Diameter, Service oder NetworkPolicy mit protocol: SCTP), wird deren Datenverkehr nicht mehr funktionieren.
Prüfen, ob solche Objekte im Cluster vorhanden sind, bevor Sie den Rollout durchführen:
# 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)"'
Wenn SCTP auf dem Knoten verwendet wird, entlädt der DaemonSet das Modul standardmäßig nicht aus dem Speicher, sondern setzt nur die Blacklist (das Modul kehrt nach einem Neustart des Knotens nicht zurück) und schreibt eine Warnung in die Logs. Um das Entladen zu erzwingen und vorhandene SCTP-Verbindungen abzubrechen, setzen Sie im Manifest:
env:
- name: FORCE_APPLY
value: "true"
wget https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-sctphantom-mitigation/main/sctphantom-mitigation-daemonset.yaml
Oder das Repository klonen:
git clone https://github.com/yandex-cloud-examples/yc-mk8s-sctphantom-mitigation.git
cd yc-mk8s-sctphantom-mitigation
kubectl 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 monitor
kubectl 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.
=========================================
Ein solcher Knoten muss neu gestartet werden: Die Blacklist verhindert bereits, dass das Modul erneut geladen wird.
Der aussagekräftigste Test ist, die Position des Angreifers zu reproduzieren: ein unprivilegierter Pod mit entfernten Capabilities, wie in der Container-Escape-Kette.
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)\"]}]}}"
Erwartete Ausgabe auf einem geschützten Knoten:
SCTP BLOCKED: [Errno 93] Protocol not supported
Auf einem ungeschützten Knoten lautet die Ausgabe SCTP REACHABLE -> EXPLOITABLE, und der Test selbst führt dazu, dass das Modul sctp auf diesem Knoten automatisch geladen wird (danach lässt es sich wahrscheinlich nicht mehr entladen – siehe Abschnitt oben). Führen Sie ihn nicht ohne Notwendigkeit auf ungeschützten Knoten aus.
Sie können den Zustand des Knotens manuell überprüfen. Stellen Sie per SSH eine Verbindung zum Knoten her und führen Sie Folgendes aus:
# Загружены ли уязвимые модули
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" - система уязвима
# Если выдает ошибку - система защищена
Achtung: Das Ausführen dieser Prüfung auf einem Knoten, auf dem das Modul noch nicht geladen ist, führt selbst zu dessen Autoload. Führen Sie sie nur nach der Anwendung der Mitigation oder bewusst durch.
Konfiguration prüfen:
# Проверить наличие конфигурации блокировки
cat /etc/modprobe.d/blacklist-sctp.conf
# Ожидаемый вывод:
# install sctp /bin/false
# install sctp_diag /bin/false
# blacklist sctp
# blacklist sctp_diag
Prüfen, dass die verwundbaren Module nicht geladen sind:
lsmod | grep -cE '^sctp'
# Ожидаемый вывод: 0
Wenn Sie die Mitigation auf normalen Hosts anwenden möchten, hier ein Einzeiler:
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'
Falls das DaemonSet entfernt werden muss:
kubectl delete -f sctphantom-mitigation-daemonset.yaml
Wichtig: Das Löschen des DaemonSet entfernt nicht die Konfigurationsdateien von den Knoten. Die Datei /etc/modprobe.d/blacklist-sctp.conf bleibt bestehen und schützt das System weiterhin.
Um den Fix vollständig von den Knoten zu entfernen, müssen Sie sich per SSH mit jedem Knoten verbinden und die Datei manuell löschen:
rm /etc/modprobe.d/blacklist-sctp.conf
Verwendete Berechtigungen:
hostPID: true – für den Zugriff auf die Host-Prozesse über nsenterprivileged: true – zum Schreiben nach /etc und zum Entladen von Kernel-Modulen/ – für den Zugriff auf das Host-DateisystemImage: ubuntu:22.04
Ressourcen:
Namespace: kube-system
Warum in der Konfiguration sowohl install als auch blacklist: blacklist blockiert das Laden über den Alias (einschließlich des Autoloads bei socket(..., IPPROTO_SCTP)), verhindert aber nicht das explizite modprobe sctp. Die Zeile install sctp /bin/false schließt auch diesen Weg.
Warum die Mitigation kein Ersatz für ein Kernel-Update ist: Das Blockieren des Moduls beseitigt den Vektor, aber der Fehler selbst bleibt im Kernel. Die dauerhafte Lösung ist ein Update des Kernels auf eine korrigierte Version (siehe Tabelle oben) oder das Aktualisieren der Node-Images und das Neuerstellen der Node-Gruppe.
Apache License 2.0
Siehe LICENSE für Details.
Bei Problemen erstellen Sie bitte ein Issue im Repository.