
CVE-2026-64564(SCTPhantom) 취약점 완화를 위한 DaemonSet
Yandex Managed Kubernetes 클러스터의 모든 worker 노드에서 Linux kernel의 CVE-2026-64564(SCTPhantom) 취약점에 대한 완화를 자동으로 적용합니다.
CVE 식별자(CVE ID): CVE-2026-64564
CVE 링크: https://nvd.nist.gov/vuln/detail/CVE-2026-64564
원본 보고서:
net/sctp/sm_make_chunk.c의 commit 9b2854f86f0b간단한 설명:
SCTPhantom은 Linux 커널의 SCTP Dynamic Address Reconfiguration(ASCONF, RFC 5061) 하위 시스템에 존재하는 use-after-free 취약점으로, 권한이 없는 로컬 사용자가 슈퍼유저(root) 권한을 얻을 수 있습니다.
근본 원인은 ASCONF 청크 처리 시 신원(identity) 불일치입니다. DEL-IP 연산의 검증은 IPv4 패킷의 소스 주소(S)를 기준으로 수행되지만, 이후 처리는 Address Parameter(L)로 선택된 transport를 사용합니다. 이로 인해 다음과 같은 순차 시퀀스가
[ Address Parameter L ] [ DEL-IP L ] [ DEL-IP 0.0.0.0 ]
검증을 통과하여 transport(L)을 삭제하고, 이후 wildcard 연산 DEL-IP 0.0.0.0이 이미 해제된 포인터를 "유지 경로(saved path)"로 재사용합니다. 그 결과 asoc->peer.primary_path와 asoc->peer.active_path는 해제된 struct sctp_transport를 가리키는 dangling 포인터로 남게 되며, 이후 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를 통해 per-socket으로 활성화되므로 sysctl net.sctp.addip_enable을 변경할 필요가 없습니다call_usermodehelper_exec()입니다kernel panic 없이 "깨끗하게" 종료되므로 탐지가 어렵습니다commit_creds())를 재사용합니다영향을 받는 기술:
net/sctp 하위 시스템(sctp 모듈), net/sctp/sm_make_chunk.c의 ASCONF 처리sctp_diag(sctp에 의존), SCTP 소켓 검사에 사용됨이 취약점은 SCTP를 사용할 수 있을 때만 악용됩니다. sctp 모듈이 로드되지 않고 자동 로드가 차단되어 있으면 해당 공격 벡터는 사용할 수 없습니다.
저자가 확인한 대상(root 획득):
| 배포판 | 커널 |
|---|---|
| Research kernel |
수정된 커널 버전:
벤더 커널은 버전 문자열이 더 오래된 경우에도 수정 사항을 백포트(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이 클러스터의 각 worker 노드에서 자동으로 수행하는 작업:
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 연결이 감지되면 가 명시적으로 설정되지 않은 한 언로드를 건너뜁니다완화는 두 개의 독립적인 부분으로 구성되며, 일부 노드에는 그중 하나만 적용됩니다.
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를 반환합니다. 이 카운터는 시간이 지나도 줄어들지 않습니다.
이로부터 두 가지 결론이 도출됩니다:
refcnt는 SCTP 사용 여부의 기준이 아닙니다. DaemonSet은 이를 정보 제공 목적으로만 출력하며, 언로드 여부는 /proc/net/sctp/assocs와 /proc/net/sctp/eps의 활성 레코드를 기준으로 결정합니다sctp가 이미 상주(resident) 상태인 노드에서 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
일반 호스트에 완화를 적용해야 한다면 다음 원라이너(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'
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는 alias 기반 로드(socket(..., IPPROTO_SCTP) 호출 시 자동 로드 포함)를 차단하지만, 명시적인 modprobe sctp는 막지 못합니다. install sctp /bin/false 줄이 이 경로까지 차단합니다.
완화가 커널 업데이트의 대체 수단이 아닌 이유: 모듈 차단은 공격 벡터를 제거하지만 버그 자체는 커널에 남아 있습니다. 영구적인 해결책은 커널을 수정된 버전으로 업데이트(위 표 참조)하거나, 노드 이미지를 업데이트하고 node group을 다시 생성하는 것입니다.
Apache License 2.0
자세한 내용은 LICENSE를 참조하세요.
문제가 발생하면 리포지토리에 issue를 생성하세요.
| 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 |
rmmodsctpsctp_diagsctpFORCE_APPLY=truemodprobe sctp가 거부되는지, SCTP 소켓 생성(socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP))이 더 이상 성공하지 않는지 확인합니다