
DaemonSet للتخفيف من الثغرة الأمنية CVE-2026-64564 (SCTPhantom)
التطبيق التلقائي للتخفيف من الثغرة CVE-2026-64564 (SCTPhantom) في نواة Linux على جميع عقد 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).
السبب الجذري هو تباين الهويات عند معالجة chunk من نوع 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، ويعمل مع تفعيل ملف seccomp الافتراضي؛ يتم تمكين ASCONF وAUTH لكل socket عبر SCTP_ASCONF_SUPPORTED / SCTP_AUTH_SUPPORTED، لذلك لا حاجة لتغيير sysctl net.sctp.addip_enablecall_usermodehelper_exec() التي تشغّل عملية في مساحات الأسماء الأولية للمضيفkernel panic، مما يصعّب الاكتشافcommit_creds())، دون shellcode أو ROP تقليديالتقنيات المتأثرة:
net/sctp (الوحدة sctp)، معالجة ASCONF في net/sctp/sm_make_chunk.csctp_diag (تعتمد على sctp)، تُستخدم لفحص SCTP socketsيمكن استغلال الثغرة فقط عند توفر SCTP: إذا لم تكن الوحدة sctp محمّلة وتم حظر تحميلها التلقائي، يكون المتجه غير متاح.
الأهداف المؤكدة من قبل المؤلفين (تم الحصول على root):
| التوزيعة | النواة |
|---|---|
إصدارات النواة المصححة:
قد تحتوي نواة البائعين على backport للإصلاح مع إصدار أقدم في سطر الإصدار - إصدار النواة بحد ذاته ليس مؤشرًا كافيًا على الثغرة، اعتمد على 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 socket قبل تطبيق القائمة السوداء، حتى لا يستدعي التحميل التلقائي للوحدة على عقدة لم تُحمَّل فيها الوحدة بعد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يتكون التخفيف من جزأين مستقلين، وعلى بعض العقد يُطبَّق جزء واحد فقط.
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)"'
إذا كان 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.
=========================================
يجب إعادة تشغيل هذه العقدة: لن تسمح القائمة السوداء للوحدة بالتحميل مرة أخرى.
أكثر الفحوصات دلالةً هي محاكاة موقف المهاجم: Pod غير مميز مع إسقاط جميع 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 وتفريغ وحدات النواة/ - للوصول إلى نظام ملفات المضيفالصورة: ubuntu:22.04
الموارد:
Namespace: kube-system
لماذا يحتوي الإعداد على كل من install وblacklist: يمنع blacklist التحميل عبر alias (بما في ذلك التحميل التلقائي عند 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 |
rmmodsctp_diagsctpsctp_diagsctpFORCE_APPLY=truemodprobe sctp مرفوض، وأن إنشاء SCTP socket (socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) لم يعد ينجح