Abusing Roles/ClusterRoles in Kubernetes
ここでは、潜在的に危険なRolesおよびClusterRolesの構成を見つけることができます。
kubectl api-resources
を使用して、すべてのサポートされているリソースを取得できることを覚えておいてください。
特権昇格
Kubernetesにおいて、異なる権限を持つ別の主体へのアクセスを取得する技術として言及される特権昇格では、基本的に4つの主要な技術があります:
Kubernetesクラスタ内または外部クラウドで、より高い権限を持つ他のユーザー/グループ/SAsを偽装できること
Kubernetesクラスタ内または外部クラウドで、より高い権限を持つSAsを見つけたりアタッチしたりできるようにポッドを作成/パッチ/実行できること
SAsのトークンがシークレットとして保存されているため、シークレットを読み取ることができること
コンテナからノードに脱出できることで、ノードで実行されているコンテナのすべてのシークレット、ノードの資格情報、およびノードが実行されているクラウド内でのノードの権限を盗むことができること
ポッドでポートフォワードを実行できる能力も言及に値する第5の技術であり、そのポッド内の興味深いリソースにアクセスできるかもしれない
任意のリソースまたは動詞へのアクセス(ワイルドカード)
ワイルドカード (*)は、任意のリソースに対する任意の動詞の権限を与えます。管理者によって使用されます。ClusterRole内では、攻撃者がクラスタ内の任意のネームスペースを悪用できることを意味します。
特定の動詞を使用して任意のリソースにアクセス
RBACでは、特定の権限には重大なリスクが伴います:
create
: 任意のクラスタリソースを作成する権限を付与し、特権昇格のリスクがあります。list
: すべてのリソースをリストすることができ、機密データが漏洩する可能性があります。get
: サービスアカウントからシークレットにアクセスすることを許可し、セキュリティ上の脅威となります。
Pod Create - トークンの盗み取り
ポッドを作成する権限を持つ攻撃者は、特権付きサービスアカウントをポッドにアタッチし、トークンを盗み取ってサービスアカウントになりすますことができます。これにより、特権が昇格します
攻撃者にトークンを送信するbootstrap-signer
サービスアカウントのトークンを盗むポッドの例:
Podの作成と脱出
以下は、コンテナが持つことができるすべての特権を示しています:
特権アクセス(保護を無効にし、機能を設定する)
特権を昇格させるのに役立つ名前空間hostIPCとhostPidを無効にする
ノードのクラウド特権を盗むためのアクセスを提供し、ネットワークへのアクセスを向上させるhostNetwork名前空間を無効にする
コンテナ内に**ホストの/**をマウントする
次のコマンドでPodを作成します:
一行から、このツイートといくつかの追加を含めて:
ステルス
おそらく、よりステルスになりたいです。前のテンプレートで言及された特権の一部だけを有効にしてポッドを作成した場合にアクセスできるものを見ることができます:
特権 + hostPID
特権のみ
hostPath
hostPID
hostNetwork
hostIPC
前述の特権を持つポッドの構成を作成/悪用する例は、https://github.com/BishopFox/badPods で見つけることができます
ポッドの作成 - クラウドへの移行
ポッド(および必要に応じてサービスアカウント)を作成できる場合、クラウド環境で特権を取得することができるかもしれません。その後、ポッドまたはサービスアカウントにクラウドロールを割り当て、アクセスすることができます。 さらに、ホストネットワーク名前空間を持つポッドを作成できる場合、ノードインスタンスのIAMロールを盗むことができます。
詳細については、次を確認してください:
Pod Escape Privilegesデプロイメント、デーモンセット、ステートフルセット、レプリケーションコントローラ、レプリカセット、ジョブ、およびクーロンジョブの作成/パッチ
これらの権限を悪用して、前述の例のように新しいポッドを作成し、特権を確立することが可能です。
次のyamlは、デーモンセットを作成し、ポッド内のSAのトークンを外部に持ち出します:
Pods Exec
**pods/exec
**は、ポッド内のシェルでコマンドを実行するために使用されるKubernetesのリソースです。これにより、コンテナ内でコマンドを実行したり、シェルを取得したりすることができます。
したがって、ポッド内に入り、SAのトークンを盗むことが可能であり、特権を持つポッドに入り、ノードに脱出してノード内のすべてのポッドのトークンを盗み、ノードを悪用することができます。
ポートフォワード
この権限は、1つのローカルポートを指定されたポッド内の1つのポートに転送することを可能にします。これは、ポッド内で実行されているアプリケーションを簡単にデバッグできるようにするためのものですが、攻撃者はそれを悪用して、ポッド内の興味深い(例:DB)や脆弱なアプリケーション(Web?)にアクセスすることがあります。
ホスト書き込み可能 /var/log/ エスケープ
この研究で示されているように、ホストの /var/log/
ディレクトリがマウントされた ポッドにアクセスまたは作成 できる場合、コンテナから脱出 できます。
これは基本的に、Kube-API がコンテナのログを取得しようとするとき(kubectl logs <pod>
を使用)、Kubelet サービスの /logs/
エンドポイントを使用してポッドの 0.log
ファイルを要求するためです。
Kubelet サービスは /logs/
エンドポイントを公開しており、これは基本的にコンテナの /var/log
ファイルシステムを公開しています。
したがって、コンテナの /var/log/ フォルダに書き込みアクセス権 がある攻撃者は、次の2つの方法でこの動作を悪用できます:
通常は
/var/logs/pods/namespace_pod_uid/container/0.log
にあるコンテナの0.log
ファイルを/etc/shadow
を指すシンボリックリンク に変更します。その後、次のようにしてホストの shadow ファイルを持ち出すことができます:
攻撃者が**
nodes/log
を読む権限を持つプリンシパルを制御している場合、/host-mounted/var/log/sym
にシンボリックリンクを作成し、https://<gateway>:10250/logs/sym/
にアクセスすると、ホストのルート**ファイルシステムがリストされます(シンボリックリンクを変更するとファイルにアクセスできる場合があります)。
実験室と自動化されたエクスプロイトは https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts
readOnly 保護のバイパス
もし運が良ければ、非常に特権のある CAP_SYS_ADMIN
機能が利用可能であれば、フォルダを単に rw で再マウントすることができます。
hostPathのreadOnly保護をバイパスする
この研究に記載されているように、この保護をバイパスすることが可能です。
次のようにして以前のもののようなエスケープを防ぐことを意図していました。代わりにhostPath マウントを使用せずに、PersistentVolume と PersistentVolumeClaim を使用して、ホストのフォルダをコンテナに書き込みアクセスでマウントします。
特権アカウントのなりすまし
ユーザーなりすまし 権限を持つと、攻撃者は特権アカウントになりすますことができます。
単にkubectl
コマンドでパラメータ --as=<username>
を使用してユーザーになりすまし、または --as-group=<group>
を使用してグループになりすますだけです。
または、REST API を使用します:
シークレットのリスト表示
シークレットのリスト表示権限は、攻撃者が実際にシークレットを読むことを可能にする REST API エンドポイントへのアクセス:
シークレットの読み取り - トークンIDの総当たり攻撃
読み取り権限を持つ攻撃者は、シークレットの正確な名前が必要ですが、より広範なシークレットの一覧表示権限とは異なり、脆弱性がまだ存在します。システム内のデフォルトサービスアカウントは列挙可能であり、それぞれがシークレットに関連付けられています。これらのシークレットは、静的な接頭辞に続くランダムな5文字の英数字トークン(特定の文字を除く)の名前構造を持っています。ソースコードによると、トークンは制限された27文字のセット(bcdfghjklmnpqrstvwxz2456789
)から生成されます。
この制限により、合計可能な組み合わせが14,348,907(27の5乗)に減少します。その結果、攻撃者は時間の経過とともにトークンを推測するために総当たり攻撃を実行し、機密性の高いサービスアカウントへのアクセスによって特権昇格を引き起こす可能性があります。
証明書署名リクエスト
リソースcertificatesigningrequests
内に**create
の動詞がある場合(または少なくともcertificatesigningrequests/nodeClient
にある場合)、新しいノードの新しいCeSRを作成**できます。
ドキュメントによると、これらのリクエストを自動承認することが可能です。その場合、追加の権限は必要ありません。そうでない場合、リクエストを承認できる必要があり、certificatesigningrequests/approval
内の更新とsigners
内の<signerNameDomain>/<signerNamePath>
または<signerNameDomain>/*
でのapprove
が必要です。
必要なすべての権限を持つロールの例は次のとおりです:
したがって、新しいノードCSRが承認されたら、ノードの特別な権限を悪用してシークレットを盗み、特権を昇格させることができます。
この投稿とこの投稿では、GKE K8s TLSブートストラップ構成が自動署名で構成され、新しいK8sノードの資格情報を生成してそれらを悪用して特権を昇格させる方法が悪用されています。 もしあなたが言及された権限を持っている場合、同じことができます。最初の例は、新しいノードがそれにマウントされたコンテナ内のシークレットにアクセスするのを防ぐエラーをバイパスします。なぜなら、ノードはそれにマウントされたコンテナのシークレットにのみアクセスできるからです。
これをバイパスする方法は、単に興味深いシークレットをマウントしたコンテナがあるノード名のノード資格情報を作成することです(ただし、最初の投稿でその方法を確認してください):
AWS EKS aws-auth configmaps
EKS(AWS内にいる必要があります)クラスターのkube-systemネームスペース内の**configmaps
を変更できる主体は、aws-auth configmapを上書きすることでクラスター管理者権限を取得できます。
必要な動詞はupdate
とpatch
です。configmapが作成されていない場合はcreate
**が必要です:
他のアカウントからユーザーにアクセス権を与えるために**aws-auth
を永続化**に使用できます。
ただし、aws --profile other_account eks update-kubeconfig --name <cluster-name>
は異なるアカウントからは機能しません。しかし、実際には aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing
は、クラスターのARNを名前の代わりに入力すると機能します。
kubectl
を機能させるには、被害者のkubeconfigを構成し、aws exec argsに --profile other_account_role
を追加して、kubectlが他のアカウントプロファイルを使用してトークンを取得し、AWSに接続するようにします。
GKEでの昇格
GCPプリンシパルにK8s権限を割り当てる方法は2つあります。いずれの場合も、プリンシパルはクラスターにアクセスするための資格情報を収集するために**container.clusters.get
**権限も必要です。そうでない場合は、独自のkubectl構成ファイルを生成する必要があります(次のリンクを参照)。
K8s APIエンドポイントにアクセスする際に、GCP認証トークンが送信されます。その後、GCPはK8s APIエンドポイントを介して、まずプリンシパル(メールアドレスで)がクラスター内でアクセス権を持っているかどうかを確認し、次にGCP IAMを介してアクセス権を持っているかどうかを確認します。 いずれかがtrueであれば、応答されます。そうでない場合は、GCP IAMを介して権限を付与するようにというエラーが表示されます。
その後、最初の方法はGCP IAMを使用することで、K8s権限にはそれに相当するGCP IAM権限があり、プリンシパルがそれを持っていれば使用できます。
GCP - Container Privesc2番目の方法は、クラスター内でK8s権限を割り当てることで、ユーザーをメールアドレスで識別します(GCPサービスアカウントを含む)。
サービスアカウントトークンの作成
TokenRequests (serviceaccounts/token
を作成できるプリンシパル)。K8s APIエンドポイントにアクセスする際にSAs(ここの情報)。
ephemeralcontainers
**pods/ephemeralcontainers
をupdate
またはpatch
**できるプリンシパルは、他のポッドでコードを実行し、特権のあるsecurityContextを持つephemeralコンテナを追加することで、ノードから脱出する可能性があります。
ValidatingWebhookConfigurationsまたはMutatingWebhookConfigurations
validatingwebhookconfigurations
またはmutatingwebhookconfigurations
の上にcreate
、update
、またはpatch
のいずれかの動詞を持つプリンシパルは、そのようなwebhookconfigurationsの作成が可能になり、特権を昇格することができるかもしれません。
mutatingwebhookconfigurations
の例は、この投稿のこのセクションを参照してください。
昇格
次のセクションで読むことができるように、組み込み特権昇格防止では、プリンシパルは新しい権限を持っていない限り、ロールまたはクラスターロールを更新または作成することはできません。**roles
またはclusterroles
の上にescalate
**動詞を持っている場合は、自分自身にそれらの新しい権限を持たせることなく、新しいロールやクラスターロールを更新/作成できます。
ノードプロキシ
nodes/proxy
サブリソースにアクセス権を持つプリンシパルは、Kubelet APIを介してポッドでコードを実行できます(こちらによる)。このページでKubelet認証に関する詳細情報を確認できます:
Kubelet APIに認証された状態でRCEを取得する例はこちらです](../pentesting-kubernetes-services/#kubelet-rce)。
ポッドの削除 + スケジュールされていないノード
ポッドを削除できるプリンシパル(pods
リソース上のdelete
動詞)、またはポッドを追い出すことができるプリンシパル(pods/eviction
リソース上のcreate
動詞)、またはポッドのステータスを変更できるプリンシパル(pods/status
へのアクセス)および他のノードをスケジュールできるプリンシパル(nodes/status
へのアクセス)またはノードを削除できるプリンシパル(nodes
リソース上のdelete
動詞)が、ポッドを制御できる場合、他のノードからポッドを盗むことができ、それらのポッドのトークンを盗むことができます。それらのポッドは侵害されたノードで実行されます。
サービスの状態(CVE-2020-8554)
services/status
を変更できる主体は、status.loadBalancer.ingress.ip
フィールドを設定して、修正されていないCVE-2020-8554を悪用し、クラスターに対するMiTM攻撃を実行できます。CVE-2020-8554のほとんどの緩和策は、ExternalIPサービスを防ぐだけです(こちらによる)。
ノードとポッドの状態
nodes/status
またはpods/status
に対する**update
またはpatch
**権限を持つ主体は、スケジューリング制約に影響を与えるためにラベルを変更できます。
ビルトイン特権昇格防止
Kubernetesには、特権昇格を防ぐビルトインメカニズムがあります。
このシステムは、ユーザーが役割やロールバインディングを変更して特権を昇格させることを防ぐことを保証します。このルールの強制はAPIレベルで行われ、RBAC認可者が非アクティブであっても保護を提供します。
このルールは、ユーザーが役割を作成または更新できるのは、その役割が持つすべての権限を持っている場合に限ることを規定しています。さらに、ユーザーの既存の権限の範囲は、作成または変更しようとしている役割の範囲と一致している必要があります。ClusterRolesの場合はクラスタ全体、Rolesの場合は同じ名前空間(またはクラスタ全体)に限定されます。
前述のルールには例外があります。主体が**roles
またはclusterroles
に対してescalate
**動詞を持っている場合、その主体は自身に権限がなくても役割やクラスタロールの特権を増やすことができます。
RoleBindings/ClusterRoleBindingsの取得とパッチ
以前はこのテクニックが機能していたようですが、私のテストによると、前のセクションで説明した理由と同じ理由でもう機能していません。すでに権限がない場合、自分自身または別のSAに特権を与えるためにrolebindingを作成/変更することはできません。
Rolebindingsを作成する特権は、ユーザーがサービスアカウントに役割をバインドすることを可能にします。この特権は、ユーザーが危険にさらされたサービスアカウントに管理者特権をバインドすることを許可するため、特権昇格につながる可能性があります。
その他の攻撃
サイドカープロキシアプリ
デフォルトでは、ポッド間の通信には暗号化がありません。相互認証、双方向、ポッド間。
サイドカープロキシアプリを作成
あなたの.yamlを作成
編集して、コメントを外した行を追加してください。
プロキシのログを参照します:
詳細はこちら:https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
悪意のあるアドミッションコントローラ
アドミッションコントローラは、オブジェクトの永続化前にKubernetes APIサーバーへのリクエストをインターセプトしますが、リクエストが認証された後であり、承認された後です。
攻撃者がなんらかの方法でMutationg Admission Controllerを注入できれば、すでに認証されたリクエストを変更できるようになります。潜在的に権限昇格が可能になり、クラスターにより一般的に永続化できるようになります。
例 https://blog.rewanthtammana.com/creating-malicious-admission-controllers:
状態を確認して、準備ができているかどうかを確認します:
その後、新しいポッドをデプロイします:
以下のいずれかのクエリでイメージ名を確認してください。ErrImagePull
エラーが表示される場合:
上の画像で見られるように、nginx
イメージを実行しようとしましたが、最終的に実行されたイメージは rewanthtammana/malicious-image
です。何が起こったのでしょうか!?
技術的詳細
./deploy.sh
スクリプトは、ミューテーティングウェブフックアドミッションコントローラを確立し、その構成行に指定されたように Kubernetes API へのリクエストを変更し、観察される結果に影響を与えます。
最初のコンテナイメージをすべてのポッドでrewanthtammana/malicious-image
に置き換えます。
rewanthtammana/malicious-image
に置き換えます。OPA Gatekeeper バイパス
Kubernetes - OPA Gatekeeper bypassベストプラクティス
サービスアカウントトークンの自動マウントの無効化
ポッドとサービスアカウント: デフォルトでは、ポッドはサービスアカウントトークンをマウントします。セキュリティを強化するために、Kubernetesはこの自動マウント機能の無効化を許可しています。
適用方法: Kubernetesバージョン1.6以降では、サービスアカウントまたはポッドの構成で
automountServiceAccountToken: false
を設定します。
RoleBindings/ClusterRoleBindings での制限付きユーザー割り当て
選択的な包含: RoleBindingsまたはClusterRoleBindingsには必要なユーザーのみが含まれるようにします。不要なユーザーを定期的に監査して削除し、セキュリティを強化します。
クラスタ全体のロールよりも名前空間固有のロールを使用
Roles vs. ClusterRoles: クラスタ全体に適用されるClusterRolesとClusterRoleBindingsではなく、名前空間固有の権限にはRolesとRoleBindingsを使用することをお勧めします。このアプローチはより細かい制御を提供し、権限のスコープを制限します。
自動化ツールの使用
参考文献
Last updated