Безопасность: Yaml Bomb: пользователь может перезапустить kube-api, отправив configmap

Создайте файл yaml-bomb.yaml:

apiVersion: v1
data:
  a: &a ["web","web","web","web","web","web","web","web","web"]
  b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
  c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
  d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
  e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
  f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
  g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
  h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
  i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
kind: ConfigMap
metadata:
  name: yaml-bomb
  namespace: default

Отправьте запрос на создание ConfigMap в API Kubernetes с помощью cmd kubectl apply -f yaml-bomb.yaml.

kube-api Загрузка ЦП/памяти очень высока, даже позже происходит перезапуск.

Как мы можем предотвратить такую ямл-бомбу?

Ответы

Ответ 1

Это атака на миллиард смеха, и ее можно исправить только в процессоре YAML.

Обратите внимание, что википедия здесь не так, когда говорится

Атака "Миллиард смеха" должна существовать для любого формата файла, который может содержать ссылки, например, эта бомба YAML:

Проблема не в том, что формат файла содержит ссылки; это процессор, расширяющий их. Это противоречит духу спецификации YAML, в которой говорится, что якоря используются для узлов, на которые фактически ссылаются из нескольких мест. В загруженных данных якоря & псевдонимы должны стать множественными ссылками на один и тот же объект, а не расширять псевдоним до копии привязанного узла.

В качестве примера сравните поведение онлайн-парсера PyYAML и онлайн-парсера NimYAML (полное раскрытие: моя работа) при вставке фрагмента кода. PyYAML не будет отвечать из-за загрузки памяти от расширяющихся псевдонимов, в то время как NimYAML не расширяет псевдонимы и, следовательно, отвечает быстро.

Удивительно, что Кубернетес страдает от этой проблемы; Я бы предположил, так как он написан на Go, что они могут правильно обрабатывать ссылки. Вы должны сообщить об ошибке, чтобы исправить это.

Ответ 2

Я мог бы подумать о нескольких возможных мерах по смягчению, хотя, как говорит @flyx, реальное исправление здесь было бы в библиотеке синтаксического анализа YAML, используемой Kubernetes.

Интересно, что выполнение этого в кластере Kubernetes на моей локальной машине показало, что всплеск ЦП был на стороне клиента (это процесс, обрабатывающий процесс kubectl), а не на стороне сервера.

Если бы проблема была на стороне сервера, то возможные меры были бы использовать RBAC, чтобы минимизировать доступ к созданию ConfigMap, и, возможно, использовать контроллер доступа, такой как OPA, для просмотра манифестов до их применения к кластеру.

Вероятно, это следует поднять с помощью группы реагирования на уязвимости безопасности в Kubernetes, чтобы можно было выполнить правильное исправление.

РЕДАКТИРОВАТЬ - я думаю, где проблема проявляется, может быть до используемой версии кластера. Применение на стороне сервера завершено до бета-версии (должно быть включено по умолчанию) в 1.16. Таким образом, в кластере 1.16, возможно, это коснулось бы стороны сервера, а не стороны клиента.

РЕДАКТИРОВАТЬ - просто установите кластер 1.16, по-прежнему показывая загрузку ЦП в качестве клиентской стороны в kubectl...

РЕДАКТИРОВАТЬ - я подал проблему для этого здесь, а также подтвердил, что DoS может быть достигнут на стороне сервера, используя curl вместо kubectl

Окончательное РЕДАКТИРОВАНИЕ - Это было присвоено CVE (CVE-2019-11253) и исправлено в Kubernetes 1. 13+. Исправление также было применено к базовой библиотеке синтаксического анализа YAML здесь, поэтому любые другие программы Go должны быть в порядке, если они используют последнюю версию.