
DaemonSet per la mitigazione della vulnerabilità CVE-2026-64564 (SCTPhantom)
Applicazione automatica della mitigazione per la vulnerabilità CVE-2026-64564 (SCTPhantom) nel kernel Linux su tutti i worker node del cluster Yandex Managed Kubernetes.
Identificatore CVE (CVE ID): CVE-2026-64564
Link CVE: https://nvd.nist.gov/vuln/detail/CVE-2026-64564
Report originale:
9b2854f86f0b in net/sctp/sm_make_chunk.cBreve descrizione:
SCTPhantom è un use-after-free nella sottosistema SCTP Dynamic Address Reconfiguration (ASCONF, RFC 5061) del kernel Linux che consente a un utente locale non privilegiato di ottenere i privilegi di superutente (root).
La causa principale è la divergenza delle identità nell'elaborazione del chunk ASCONF: il controllo dell'operazione DEL-IP viene eseguito contro l'indirizzo sorgente del pacchetto IPv4 (S), mentre l'elaborazione successiva utilizza il transport selezionato tramite l'Address Parameter (L). Di conseguenza, la sequenza ordinata
[ Address Parameter L ] [ DEL-IP L ] [ DEL-IP 0.0.0.0 ]
supera il controllo e rimuove transport(L), dopodiché l'operazione wildcard DEL-IP 0.0.0.0 riutilizza il puntatore già liberato come "percorso preservato". Di conseguenza asoc->peer.primary_path e asoc->peer.active_path restano puntatori dangling a una struct sctp_transport liberata, e la successiva chiamata getsockopt(SCTP_STATUS) li dereferenzia.
La logica vulnerabile è stata introdotta in Linux 2.6.25 (2007, commit 42e30bf3463c), quindi è presente nel kernel da circa 18 anni.
Attacco:
CAP_NET_ADMIN e CAP_SYS_ADMIN, funziona con il profilo seccomp predefinito attivo; ASCONF e AUTH vengono abilitati per-socket tramite SCTP_ASCONF_SUPPORTED / SCTP_AUTH_SUPPORTED, quindi non è necessario modificare il sysctl net.sctp.addip_enablecall_usermodehelper_exec(), che avvia un processo nei namespace iniziali dell'hostkernel panic, il che rende difficile il rilevamentocommit_creds() data-oriented), senza shellcode e senza ROP classicoTecnologie interessate:
net/sctp (modulo sctp), elaborazione di ASCONF in net/sctp/sm_make_chunk.csctp_diag (dipende da sctp), usato per l'ispezione dei socket SCTPLa vulnerabilità è sfruttabile solo se SCTP è disponibile: se il modulo sctp non è caricato e il suo caricamento automatico è bloccato, il vettore non è disponibile.
Obiettivi confermati dagli autori (root ottenuta):
| Distribuzione | Kernel |
|---|
Versioni del kernel corrette:
I kernel vendor possono contenere un backport del fix con una versione più vecchia nella stringa di versione: la versione del kernel da sola non è un indicatore sufficiente di vulnerabilità; fare riferimento all'advisory o ai sorgenti del vendor.
Vettore d'attacco e livello di pericolosità secondo CVSS v.4.0:
Punteggio base: 8.5 (HIGH)
Vettore: 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
Il DaemonSet, automaticamente su ogni worker node del cluster:
sctp e sctp_diag sono caricati e con quale refcnt. Il controllo è volutamente passivo: il DaemonSet non apre socket SCTP prima di impostare la blacklist, per non provocare il caricamento automatico del modulo su un nodo dove non è ancora caricatorefcnt del modulo e le voci attive in /proc/net/sctp/assocs e /proc/net/sctp/eps. Kubernetes stesso non usa SCTP, ma i carichi di lavoro utente possono dichiarare protocol: SCTP in Service/Pod/etc/modprobe.d/blacklist-sctp.conf con le regole install e blacklist per sctp e sctp_diagLa mitigazione è composta da due parti indipendenti e su alcuni nodi viene applicata solo una di esse.
1. Blacklist (applicata sempre, in modo affidabile). Dopo la creazione di /etc/modprobe.d/blacklist-sctp.conf, il modulo sctp non può più essere caricato - né automaticamente con socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP), né con modprobe esplicito. Questo chiude il vettore sui nodi in cui il modulo non era ancora stato caricato (stato tipico: SCTP non è usato da Kubernetes e viene caricato solo su richiesta).
2. Scaricamento del modulo dalla memoria (non sempre possibile). Se sctp è già stato caricato, nella maggior parte dei casi non sarà possibile scaricarlo. Sui nodi Yandex Managed Kubernetes testati (Ubuntu 22.04, kernel 5.15.0-181-generic), un modulo sctp appena caricato e non utilizzato da nessuno ha già refcnt=6 con lista holders vuota e /proc/net/sctp/{assocs,eps} vuoti, e rmmod restituisce ERROR: Module sctp is in use. Il contatore non diminuisce nel tempo.
Da qui due conseguenze:
refcnt non è un indicatore dell'uso di SCTP: il DaemonSet lo mostra solo a scopo informativo e decide sullo scaricamento in base alle voci attive in /proc/net/sctp/assocs e /proc/net/sctp/epssctp è già residente, il DaemonSet segnala onestamente ⚠ mitigation applied PARTIALLY. La blacklist è già presente (dopo il riavvio il modulo non tornerà), ma fino al riavvio il nodo rimane vulnerabile. Per chiudere completamente il vettore, questi nodi devono essere riavviati oppure si deve ricreare il node groupPer trovare questi nodi dopo il rollout:
kubectl logs -n kube-system -l app=cve-2026-64564-fix -c apply-fix --prefix | grep -E 'PARTIALLY|STILL LOADED'
Importante: la mitigazione disattiva completamente SCTP sul nodo.
Kubernetes e i plugin di rete (Cilium, Calico) non usano SCTP per il proprio funzionamento, quindi per la stragrande maggioranza dei cluster la mitigazione è sicura. Tuttavia, se nel cluster sono presenti carichi di lavoro che usano SCTP (ad esempio applicazioni telecom, VoIP/segnale SS7/Diameter, Service o NetworkPolicy con protocol: SCTP), il loro traffico smetterà di funzionare.
Per verificare se nel cluster esistono tali oggetti, prima del rollout:
# 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)"'
Se SCTP viene utilizzato sul nodo, il DaemonSet per impostazione predefinita non scarica il modulo dalla memoria, ma applica solo la blacklist (il modulo non tornerà dopo il riavvio del nodo) e scrive un avviso nei log. Per forzare lo scaricamento, interrompendo le connessioni SCTP esistenti, imposta nel manifest:
env:
- name: FORCE_APPLY
value: "true"
wget https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-sctphantom-mitigation/main/sctphantom-mitigation-daemonset.yaml
Oppure clonare il repository:
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.
=========================================
Tale nodo deve essere riavviato: la blacklist non consentirà più al modulo di essere caricato di nuovo.
La verifica più indicativa è riprodurre la posizione dell'attaccante: un pod non privilegiato con capabilities rimosse, come nella catena di 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)\"]}]}}"
Output atteso su un nodo protetto:
SCTP BLOCKED: [Errno 93] Protocol not supported
Su un nodo non protetto l'output sarà SCTP REACHABLE -> EXPLOITABLE e la verifica stessa provocherà il caricamento automatico del modulo sctp su quel nodo (dopodiché, molto probabilmente, non sarà più possibile scaricarlo - vedi la sezione precedente). Non eseguirla su nodi non protetti senza necessità.
Puoi verificare manualmente lo stato del nodo. Collegati al nodo via SSH ed esegui:
# Загружены ли уязвимые модули
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" - система уязвима
# Если выдает ошибку - система защищена
Attenzione: eseguire questa verifica su un nodo in cui il modulo non è ancora caricato ne provocherà il caricamento automatico. Eseguila solo dopo aver applicato la mitigazione oppure consapevolmente.
Verificare la configurazione:
# Проверить наличие конфигурации блокировки
cat /etc/modprobe.d/blacklist-sctp.conf
# Ожидаемый вывод:
# install sctp /bin/false
# install sctp_diag /bin/false
# blacklist sctp
# blacklist sctp_diag
Verificare che i moduli vulnerabili non siano caricati:
lsmod | grep -cE '^sctp'
# Ожидаемый вывод: 0
Se devi applicare la mitigazione su host normali, one-liner:
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'
Se è necessario rimuovere il DaemonSet:
kubectl delete -f sctphantom-mitigation-daemonset.yaml
Importante: la rimozione del DaemonSet non rimuoverà i file di configurazione dai nodi. Il file /etc/modprobe.d/blacklist-sctp.conf rimarrà al suo posto e continuerà a proteggere il sistema.
Per rimuovere completamente il fix dai nodi, è necessario connettersi a ciascun nodo via SSH ed eliminare manualmente il file:
rm /etc/modprobe.d/blacklist-sctp.conf
Permessi utilizzati:
hostPID: true - per l'accesso ai processi host tramite nsenterprivileged: true - per la scrittura in /etc e lo scaricamento dei moduli del kernel/ - per l'accesso al filesystem dell'hostImmagine: ubuntu:22.04
Risorse:
Namespace: kube-system
Perché nella configurazione ci sono sia install che blacklist: blacklist blocca il caricamento tramite alias (incluso il caricamento automatico con socket(..., IPPROTO_SCTP)), ma non impedisce un modprobe sctp esplicito. La riga install sctp /bin/false chiude anche questa via.
Perché la mitigazione non sostituisce l'aggiornamento del kernel: il blocco del modulo elimina il vettore, ma il bug stesso rimane nel kernel. La soluzione permanente è l'aggiornamento del kernel a una versione corretta (vedi tabella sopra) oppure l'aggiornamento delle immagini dei nodi e la ricreazione del node group.
Apache License 2.0
Vedi LICENSE per i dettagli.
In caso di problemi, apri una issue nel repository.
| 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 (con modulo sctp caricato) |
| Ubuntu 24.04 | 6.8.0-134-generic |
| Ramo | Prima versione corretta | Fix stabile |
|---|
| 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 |
rmmod per sctp_diag, poi sctp (l'ordine è importante: sctp_diag dipende da sctp). Se vengono rilevate connessioni SCTP attive, lo scaricamento viene saltato, a meno che non sia impostato esplicitamente FORCE_APPLY=truemodprobe sctp venga rifiutato e che la creazione di un socket SCTP (socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) non riesca più