TGViewer
A young Max’s notebook A young Max’s notebook @youngmaxnotes · 149 subscribers
Post #122 284
У вашего мониторинга могут быть права на RCE. И вы сами их выдали

Залез читать изменения Kubernetes 1.36 и наткнулся на прекрасное.

У ServiceAccount вашего Prometheus, log collector или monitoring agent может быть такое правило:
resources: ["nodes/proxy"]
verbs: ["get"]

Выглядит безобидно.
Ну get же. Read-only. Просто почитать метрики и разойтись.

На деле этого права может хватить, чтобы выполнить команду в любом контейнере на доступной ноде.
Да, get.
Да, RCE.
Ага, Kubernetes moment.

Как мы вообще сюда пришли


У kubelet есть HTTPS API, обычно на порту 10250. Через него можно получать метрики, статистику, логи, список Pod — и делать exec в контейнеры.

Исторически почти все эти endpoint’ы авторизовывались через один широкий ресурс — nodes/proxy.

То есть monitoring agent, которому нужно было только сходить в /metrics, получал то же право, через которое можно добраться до /exec.
Но становится ещё веселее.

Для установки WebSocket-соединения используется HTTP GET. Kubelet сопоставлял этот запрос с RBAC-глаголом get и не выполнял дополнительную проверку на create перед началом интерактивной операции.

В результате ServiceAccount с get nodes/proxy и сетевым доступом к kubelet API мог открыть /exec и выполнять команды внутри контейнеров.
Kubernetes SIG Auth и SIG Node прямо называют nodes/proxy возможностью уровня node superuser.

Важная оговорка
Это не означает, что любой установленный Prometheus автоматически уязвим.
Должны совпасть два условия:
— у ServiceAccount есть get на nodes/proxy;
— из workload можно достучаться до kubelet API на ноде.
Но для агентов, которые собирают данные напрямую с kubelet, второй пункт вполне может быть частью архитектуры.
И если такой агент или его токен скомпрометируют, blast radius будет немного больше, чем «сломался один дашборд».

Но ведь Kubernetes 1.36 это исправил?
И да, и нет. :)

В 1.36 KubeletFineGrainedAuthz стал GA и всегда включён. Вместо широкого nodes/proxy теперь можно выдавать точечные права:
nodes/metrics для /metrics/*;
nodes/stats для /stats/*;
nodes/log для /logs/*;
nodes/pods для списка Pod.
Например:
resources: ["nodes/metrics", "nodes/stats"]
verbs: ["get"]

Но апгрейд не удаляет старые разрешения.
Для обратной совместимости kubelet продолжает принимать nodes/proxy. Поэтому кластер может быть на свежей версии, все Pod зелёные, а старый blast radius никуда не делся.
Совместимость бережно сохранила не только ваши интеграции, но и лишние права. Очень заботливо.

Что я бы проверил прямо сейчас
1. Найти все ClusterRole с nodes/proxy:
kubectl get clusterroles -o json | jq -r '
.items[]
| select(any(.rules[]?;
(.resources // []) | index("nodes/proxy")))
| .metadata.name'

2. Посмотреть, к каким ServiceAccount они привязаны. Особенно внимательно — monitoring, logging, security и разные node-level DaemonSet.

3. Проверить конкретный ServiceAccount
kubectl auth can-i get nodes/proxy \
--as=system:serviceaccount:<namespace>:<serviceaccount>

4. Понять, какие kubelet endpoint’ы агент реально использует, и заменить nodes/proxy на минимальный набор nodes/metrics, nodes/stats, nodes/log или nodes/pods.
Не выдавайте весь набор «на всякий случай». Мы именно так сюда и приехали.
5. Проверить scrape и сбор логов на canary, удалить старое право и запретить новые workload-binding’и с nodes/proxy через admission policy. Доступ к 10250 тоже стоит ограничить на сетевом уровне.
Только не удаляйте разрешение вслепую из системных ролей: оно легитимно нужно некоторым компонентам Kubernetes. Нас интересуют обычные workload’ы, которым его выдали ради observability.

Главный вывод тут даже не про kubelet.
get — это название операции, а не гарантия безопасности.
Если ресурс называется proxy, вы разрешаете не чтение объекта. Вы открываете туннель к чужому API.
А что можно сделать внутри этого туннеля — RBAC-глагол вам уже не расскажет.

А у вас monitoring ServiceAccount всё ещё живут с nodes/proxy или вы уже перешли на fine-grained RBAC?
#kubernetes #security #sre
  • 🤪 3
More from @youngmaxnotes
  1. Sep 12, 2026Агенту разрешают расследовать, но не разрешают чинить. Почему граница именно здесь???? В н…
  2. Sep 3, 2026Самый опасный деплой 2026 года - тот, который никто не считал деплоем Залез перечитывать б…
  3. Sep 2, 2026Инциденты, метрики и спасенный прод на DevOops 2026 Вы, возможно, знаете, а может, и нет,…
  4. Aug 6, 2026Встречаемся на ПерфКонф #12? ДА! Вы, возможно, знаете, а может, и нет, но я очень люблю уч…
  5. Jul 27, 2026SRE Mind map Просто оставлю это тут: https://jtprogru.github.io/The-Way-of-SRE/mindmap/ За…
  6. Jul 20, 2026Выгоревший сотрудник — не сломанный ресурс, который нужно перезапустить. Иногда сломана са…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →