
CVE-2026-64564 (SCTPhantom) の脆弱性を緩和するための DaemonSet
Yandex Managed Kubernetes クラスターのすべてのワーカーノード上の Linux kernel における脆弱性 CVE-2026-64564 (SCTPhantom) の緩和策を自動適用します。
CVE 識別子 (CVE ID): CVE-2026-64564
CVE へのリンク: https://nvd.nist.gov/vuln/detail/CVE-2026-64564
元のレポート:
9b2854f86f0b (net/sctp/sm_make_chunk.c 内)概要:
SCTPhantom は、Linux カーネルの SCTP Dynamic Address Reconfiguration (ASCONF、RFC 5061) サブシステムにおける use-after-free であり、非特権のローカルユーザーがスーパーユーザー (root) 権限を取得できるようにするものです。
根本原因は、ASCONF チャンクの処理における識別情報の不一致です。DEL-IP 操作の検証は IPv4 パケットの送信元アドレス (S) に対して行われますが、その後の処理では Address Parameter (L) を介して選択された transport が使用されます。そのため、次の順序付けられたシーケンスは
[ Address Parameter L ] [ DEL-IP L ] [ DEL-IP 0.0.0.0 ]
検証を通過して transport(L) を削除し、その後ワイルドカード操作 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 は不要で、デフォルトの seccomp プロファイルが有効な状態でも動作します。ASCONF と AUTH は 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)、net/sctp/sm_make_chunk.c での ASCONF 処理sctp_diag (sctp に依存)。SCTP ソケットの検査に使用されますこの脆弱性は SCTP が利用可能な場合にのみ悪用可能です。モジュール sctp がロードされておらず、その自動ロードがブロックされている場合、攻撃ベクトルは利用できません。
著者らが確認した対象 (root 取得済み):
| ディストリビューション | カーネル |
|---|---|
修正済みカーネルバージョン:
ベンダーカーネルは、バージョン文字列が古くてもフィックスのバックポートを含む場合があります。カーネルのバージョンだけでは脆弱性の有無を判断するのに十分ではないため、ベンダーの 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 はクラスターの各ワーカーノードで自動的に:
sctp と sctp_diag がロードされているか、refcnt がいくつかを確認します。このチェックは意図的にパッシブです。DaemonSet は、モジュールがまだロードされていないノードで自動ロードを誘発しないよう、ブラックリストを設定するまで SCTP ソケットを開きませんrefcnt と /proc/net/sctp/assocs および /proc/net/sctp/eps の生存エントリを分析します。Kubernetes 自体は SCTP を使用しませんが、ユーザーのワークロードが Service/Pod で protocol: SCTP を宣言する場合がありますsctp と sctp_diag に対する install および blacklist ルールを含む /etc/modprobe.d/blacklist-sctp.conf を作成しますsctp_diag、次に の順で を実行します (順序が重要: は に依存します)。生存中の SCTP 接続が検出された場合は、 が明示的に設定されていない限り、アンロードはスキップされます緩和策は 2 つの独立した部分で構成されており、一部のノードではそのうちの 1 つだけが適用されます。
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 でも、holders リストが空で /proc/net/sctp/{assocs,eps} が空の状態で既に refcnt=6 となっており、rmmod は ERROR: Module sctp is in use を返します。このカウンタは時間が経っても減少しません。
これには 2 つの帰結があります:
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 シグナリング、protocol: SCTP を持つ Service または NetworkPolicy) がある場合、そのトラフィックは動作しなくなります。
適用前に、クラスター内にそのようなオブジェクトが存在するか確認するには:
# 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-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.
=========================================
そのようなノードは再起動する必要があります。ブラックリストにより、モジュールが再びロードされることはありません。
最もわかりやすい確認方法は、攻撃者の立場を再現することです。container escape チェーンと同様に、capabilities をすべて破棄した非特権 Pod を使用します。
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 - nsenter を介してホストのプロセスにアクセスするためprivileged: true - /etc への書き込みとカーネルモジュールのアンロードのため/ - ホストのファイルシステムへのアクセスのためイメージ: ubuntu:22.04
リソース:
Namespace: kube-system
設定に install と blacklist の両方がある理由: blacklist はエイリアスによるロード (socket(..., IPPROTO_SCTP) 時の自動ロードを含む) をブロックしますが、明示的な modprobe sctp は妨げません。install sctp /bin/false 行がその経路も塞ぎます。
緩和策がカーネル更新の代替にならない理由: モジュールのブロックは攻撃ベクトルを排除しますが、バグ自体はカーネルに残ります。恒久的な解決策は、カーネルを修正済みバージョン (上記の表を参照) に更新するか、ノードイメージを更新して node group を再作成することです。
Apache License 2.0
詳細は LICENSE を参照してください。
問題が発生した場合は、リポジトリに issue を作成してください。
| 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 |
sctprmmodsctp_diagsctpFORCE_APPLY=truemodprobe sctp が拒否されること、および SCTP ソケットの作成 (socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) がもはや成功しないことを確認します