fbpx

Kubernetes RBACにおけるNode/Proxy権限からの権限昇格 #aqua #コンテナ #セキュリティ #k8s

この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。

本ブログは「Aqua Security」社の技術ブログで2022年3月3日に公開された「 Privilege Escalation from Node/Proxy Rights in Kubernetes RBAC 」の日本語翻訳です。

Kubernetes RBACにおけるNode/Proxy権限からの権限昇格


Kubernetes の豊富な API と広範な機能の副作用として、ユーザに権限を付与することで、セキュリティに影響を与えるという点が挙げられます。セキュリティアーキテクトは、Kubernetes を使用するプラットフォームを設計する際に、これらの副作用を認識する必要があります。NCC Group の Iain Smart 氏との最近の調査では、Kubernetes の Node/Proxy リソースに権限を付与すると、監査ログや他のセキュリティ制御をバイパスできるような方法が発見されました。

Kubernetes APIサーバプロキシとは

最初に考えるべきは、「Node Proxyとは何か、どのように機能するのか」ということです。Kubernetes API のあまり知られていない機能には、ユーザが API サーバを介して、クラスター内で動作しているワークロードへリクエストをプロキシできる機能があります。この機能は、ユーザがワークロードに直接ネットワーク接続する必要がないため、トラブルシューティングやモニタリングに便利です。しかしこの機能により、ユーザは API サーバを介してワークロードにアクセスできてしまいます。

一般に、このアクセスは Pod と Service の IP アドレスに制限されており、API サーバを一般的なプロキシとして使用できないはずです。しかし、2019 年に Kinvolk 社が指摘したように、API サーバを不正に利用して、ある任意の外部 IP アドレスへのアクセスを許可させることは可能です。

また、Kubernetes には API サーバを経由してクラスターノード上で動作する Service にアクセスできる機能があります。一般に、これらのリクエストは認証なしで行われます。しかし、テスト時に気づいたのは、Kubelet API へのアクセスは認証情報付きで行われるということでした。つまり Node/Proxy権限を持つユーザは、ノード上のすべての Pod でコマンドを実行するなど、基本的に Kubelet API が許可するあらゆることが実行できます。

Kubelet API と直接通信する

さらにドキュメントを読んだり、協力的な Kubernetes コミュニティのメンバーに尋ねたりした結果、この(誤った)使い方が他にもあることに気づきました。それは、Node/Proxy のロールベースアクセス制御(RBAC)権限は、Kubelet API でも直接使用されるため、これらの権限を持つユーザは Kubelet に直接通信し、API サーバをバイパスできることが判明しました。

セキュリティアーキテクチャの観点から、これはいくつかの深刻な結果をもたらす可能性があります。

  • Kubelet API は Kubernetes の監査をサポートしていないため、この API を使用して行われたアクションを適切に監査できないでしょう。
  • Kubelet API へのアクセスは Kubernetes の Admission Controller をバイパスするため、その権限を持つユーザは、他の方法では阻止されるアクションをすり抜けられる可能性があります。

ここでは、実際のデモでその様子をご紹介します。まず、Node/Proxy権限のみを持つ ClusterRole を作成します。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: "2022-01-07T11:48:17Z"
  name: nodeproxy
  uid: 01b56e4a-6109-43d9-92e8-14013c0054ed
rules:
  - apiGroups:
  - ""
  resources:
  - nodes/proxy
  verbs:
  - get
  - create

次に、ServiceAccount を作成します。

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2022-01-07T11:51:27Z"
  name: nodeproxy
  namespace: default
  uid: a67ae864-a3da-402a-bdff-c181c86dd9b1

次に、その ServiceAccount と ClusterRole を対象とした ClusterRoleBinding リソースを作成します。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: "2022-01-07T11:50:58Z"
  name: nodeproxybinding
  uid: e368c3ac-945f-41d2-a6b1-7caa2eaf8038
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nodeproxy
subjects:
  - kind: ServiceAccount
  name: nodeproxy
  namespace: default

これらの条件が揃えば、ServiceAccount Token を取得し、それを使って Kubelet API と直接通信できます。以下の動画では、Secret の取得、Kubelet API/Pods エンドポイントへアクセス、すべての Pod データが表示できることの確認、Node 上の Pod の 1 つに対して whoami コマンドを実行、root としてコマンドを実行できることを、順に紹介しています。

まとめ


このような権限昇格が可能であることを知った上で、リスクを軽減するためのセキュリティのグッドプラクティスにはどのようなものがあるでしょうか。

  • 明示的に、またはワイルドカード RBAC 権限の一部として、Node/Proxy の権限を誰に与えるかについて、十分に注意してください。
  • これがクラスターにとってリスクとなる場合、Kubelet サービスへのアクセスをファイアウォールで保護することを検討してください。ユーザは Node/Proxy を経由してアクセス可能ですが、そのアクセスは Kubernetes 監査ログに表示されます。
  • Kubelet API への正確なアクセスは監査ログに表示されませんが、Kubelet がユーザの許可を確認する subjectaccessrequest のエントリが存在することになります。Kubelet への直接アクセスを検出する方法についてはこちら をご覧ください。

この投稿では、Kubernetes の RBAC に関連する複雑さの一部を紹介し、ユーザやサービスに使用権を付与する際に最小特権のアプローチをとることが重要である理由を紹介しました。Kubernetes は非常に柔軟でリッチなシステムですが、こうした特性はセキュリティの観点からも影響を及ぼします。

New call-to-action

新規CTA