Назад

2026/11/10

Kyverno CVE-2026-124440: когда механизм политик становится обходным путём к правам администратора кластера

В Kyverno 1.19.1 арендатор с правом создавать политики в своём пространстве имён может стать администратором кластера. Суть обхода и что проверить до обновления.

Многие команды используют Kyverno, чтобы изолировать арендаторов Kubernetes друг от друга. Он проверяет каждый объект на соответствие политикам до того, как API-сервер его сохранит, и может разрешить владельцам пространств имён писать собственные политики для своего пространства имён. CVE-2026-124440, опубликованная 8 ноября 2026 года, показывает, как такое делегирование может дать сбой. В Kyverno 1.19.1 арендатор, которому разрешено создавать политики только в собственном пространстве имён, может заставить Kyverno действовать за его пределами и шаг за шагом получить права администратора кластера.

Исправление доступно с 20 октября в Kyverno 1.19.2. Кластеры, пропустившие этот выпуск, по-прежнему уязвимы. В этой статье разбирается, что пошло не так, как работает повышение привилегий и что проверить в собственных кластерах.

Главное

  • CVE-2026-124440 (рекомендация GitHub GHSA-39w8-hv5g-f73w) затрагивает Kyverno 1.19.1. Уязвимость исправлена в 1.19.2. В записи CVE ей присвоена оценка 9.4 по CVSS 4.0 и 9.9 по CVSS 3.1.
  • Атакующему достаточно права создать Kyverno Policy уровня пространства имён в собственном пространстве имён.
  • Вызов apiCall из политики выполняется от имени ServiceAccount контроллера допуска Kyverno, который может читать другие пространства имён и создавать admission-вебхуки на уровне всего кластера. Этот путь ведёт к правам администратора кластера.
  • Обходного решения в рекомендации не указано. Обновитесь до 1.19.2, затем проверьте, кто может создавать политики и какие вебхуки существуют.
  • В изученных нами источниках не сообщается об эксплуатации уязвимости в реальных атаках.

Что должно было делать ограничение по пространству имён

Политики Kyverno могут получать данные из Kubernetes API во время оценки запроса. Эта функция называется apiCall: правило указывает urlPath, Kyverno обращается к API-серверу, и результат используется в правиле. Вызов выполняется от имени собственного ServiceAccount Kyverno, а не с правами автора политики.

Для кластерных ClusterPolicy, которые пишут администраторы платформы, это ожидаемое поведение. Для Policy уровня пространства имён, создание которых может быть разрешено арендаторам, это риск. Более ранние рекомендации (GHSA-c5qq-7g2q-cpqp и GHSA-5qq8-67g6-4h2w) показали, что Policy уровня пространства имён может через apiCall читать другие пространства имён или записывать объекты уровня кластера. В Kyverno 1.19.1, выпущенной 10 сентября 2026 года, появилось «ограничение по пространству имён» (namespace clamp): перед выполнением вызова Kyverno проверяет, что путь не выходит за пределы собственного пространства имён политики.

Где проверка и действие расходятся

Ограничение в 1.19.1 проверяло не ту строку, которую отправляло. Согласно рекомендации, оно декодировало процентное кодирование в urlPath, нормализовало результат (так что сегменты .. разрешались) и проверяло пространство имён в этой очищенной копии. Сам же запрос затем отправлялся с исходным, необработанным путём.

Это работает, пока декодирование проходит успешно. Но если путь содержит некорректную процентную escape-последовательность, например одиночный % в строке запроса в конце пути, декодирование завершается ошибкой. В этом случае код 1.19.1 переходил к проверке необработанной, всё ещё закодированной строки. У API-сервера такого запасного варианта нет. Он полностью декодирует путь и маршрутизирует запрос. В результате ограничение видит собственное пространство имён арендатора, а API-сервер видит закодированные сегменты .., которые выводят из него в другое пространство имён или к коллекции уровня кластера.

В рекомендации подчёркивается, что речь идёт о целом классе входных данных, а не об одной полезной нагрузке. Блокировка одной конкретной строки проблему не устранит. Надёжное исправление состоит в том, чтобы проверять и выполнять в точности один и тот же путь.

Именно это делает 1.19.2. Судя по нашему анализу исходного кода 1.19.2, Kyverno теперь строит одну каноническую форму пути, отклоняет пути, которые не удаётся привести к канонической форме, проверяет пространство имён по этой форме и отправляет на API-сервер ту же самую форму. Родственная проблема, исправленная в том же выпуске, CVE-2026-122310 (GHSA-3xfv-vq8x-qhg4), использовала то же расхождение между проверкой очищенного пути и необработанным запросом, скрывая сегменты ../ за # или ?. Это отдельная CVE с собственной записью.

Цепочка повышения привилегий шаг за шагом

Автор отчёта продемонстрировал цепочку на Kubernetes 1.31 с Kyverno 1.19.1, установленным из стандартного Helm-чарта со значениями по умолчанию.

  1. Создать Policy уровня пространства имён. Единственная привилегия арендатора — создание policies.kyverno.io в собственном пространстве имён. Политика содержит apiCall, путь которого проходит ограничение, но маршрутизируется в другое место.
  2. Запустить её. Создание любого обычного объекта, подпадающего под политику, например ConfigMap в пространстве имён арендатора, заставляет Kyverno оценить правило и выполнить вызов от имени ServiceAccount своего контроллера допуска.
  3. Читать данные в других пространствах имён. Тем же приёмом можно читать объекты в других пространствах имён, включая Secrets, если развёртыванию Kyverno разрешено их читать.
  4. Создать вебхук на уровне кластера. ServiceAccount может создавать MutatingWebhookConfiguration и ValidatingWebhookConfiguration, поэтому арендатор может зарегистрировать собственный вебхук, который затем перехватывает и переписывает запросы на допуск во всех пространствах имён.
  5. Получить права администратора кластера. В рекомендации описано, как с помощью такого вебхука изменять поды, создаваемые в kube-system, и уже оттуда выдать арендатору права cluster-admin. Итог — полная потеря конфиденциальности, целостности и доступности.

Никаких действий пользователя не требуется: вебхук срабатывает при обычной активности в кластере.

Кого это затрагивает

В записи CVE Kyverno 1.19.1 указана как уязвимая, а 1.19.2 — как неуязвимая. В версиях до 1.19.1 именно этого обхода нет, потому что в них вообще нет ограничения по пространству имён. Однако они подвержены более ранним уязвимостям, которые это ограничение должно было устранить, поэтому оставаться на старом выпуске — не безопасная альтернатива. Риск наиболее высок там, где владельцам пространств имён, CI-конвейерам или порталам самообслуживания разрешено создавать Kyverno Policy.

Kyverno 1.19.2 вышла 20 октября 2026 года, и в её примечаниях к выпуску перечислены 24 рекомендации по безопасности GitHub: 9 критических, 14 с высоким и 1 со средним уровнем опасности. Несколько из них касаются проверки путей API и ограничения рамками пространства имён. Эта рекомендация была опубликована тремя днями позже, 23 октября, но и в ней, и в записи CVE исправленной версией названа 1.19.2. У каждой рекомендации свой идентификатор, поэтому сопоставляйте их по одной, а не считайте весь набор одной CVE.

Что проверить в собственных кластерах

Сначала выясните, какая версия Kyverno действительно запущена, а не какая указана в вашем Git-репозитории:

kubectl get deployments -n kyverno -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.template.spec.containers[*].image}{"\n"}{end}'

Если хотя бы у одного образа тег v1.19.1, запланируйте обновление до 1.19.2 прямо сейчас. Затем проверьте четыре вещи:

  • Кто может создавать Policy уровня пространства имён. Проверьте учётные данные арендаторов напрямую и найдите роли, предоставляющие права на policies.kyverno.io, включая агрегированные ClusterRole, которые добавляют права во встроенные роли admin и edit.
  • Существующие политики, использующие apiCall. Составьте их список и проверьте каждый urlPath, особенно пути, содержащие %, .., ? или #.
  • Конфигурации вебхуков. Сравните список с ожидаемым. Kyverno создаёт собственные вебхуки, поэтому обращайте внимание на незнакомые имена и недавнее время создания.
  • Журналы аудита. Ищите запросы от ServiceAccount контроллера допуска Kyverno, которые создают конфигурации вебхуков или читают Secrets вне привычного для него шаблона.
kubectl auth can-i create policies.kyverno.io -n team-a --as=system:serviceaccount:team-a:default
kubectl get policies.kyverno.io -A -o json | jq -r '.items[] | select([.spec.rules[]?.context[]? | select(.apiCall)] | length > 0) | "\(.metadata.namespace)/\(.metadata.name)"'
kubectl get mutatingwebhookconfigurations,validatingwebhookconfigurations -o custom-columns=NAME:.metadata.name,CREATED:.metadata.creationTimestamp

Замените team-a на собственные пространства имён и учётные записи арендаторов. Если на кластере, где работала версия 1.19.1, вы обнаружите вебхук, появление которого не можете объяснить, считайте это возможным инцидентом: сохраните журналы аудита, прежде чем что-либо удалять.

Более общий урок: проверяйте того, кто обеспечивает соблюдение правил

Контроллеры допуска, механизмы политик и операторы часто оказываются самыми привилегированными компонентами кластера. Им нужны широкие права для выполнения своей работы, а арендаторы взаимодействуют с ними каждый день. Это делает их привлекательной целью. В данном случае модель мультиарендности держалась на одной проверке, и чтобы её сломать, хватило одного шага декодирования, который проверка и запрос обрабатывали по-разному.

Для частных облаков и мультиарендных платформ Kubernetes полезны три привычки. Считайте механизмы политик частью поверхности атаки и следите за их выпусками безопасности так же внимательно, как за версией Kubernetes. Выдавайте их ServiceAccount только необходимые права, например не разрешайте чтение Secret, если ни одна политика этого не требует. И проверяйте, к каким функциям арендаторы получают доступ через делегирование, потому что функция, работающая с привилегиями платформы, превращает ввод арендатора в действие платформы.

Источники