From b9a919bf04e3bdbd6cf348f0e301694f32946366 Mon Sep 17 00:00:00 2001 From: CPol Date: Tue, 21 Dec 2021 21:58:59 +0000 Subject: [PATCH] GitBook: [#2905] No subject --- SUMMARY.md | 2 +- cloud-security/gcp-security/README.md | 16 +-- .../enumeration-from-a-pod.md | 98 +++++++++++++------ 3 files changed, 78 insertions(+), 38 deletions(-) diff --git a/SUMMARY.md b/SUMMARY.md index 90a940c0..376fbbaf 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -211,7 +211,7 @@ * [Scanner and Fax](pentesting/pentesting-printers/scanner-and-fax.md) * [Pentesting SAP](pentesting/pentesting-sap.md) * [Pentesting Kubernetes](pentesting/pentesting-kubernetes/README.md) - * [Enumeration from a Pod](pentesting/pentesting-kubernetes/enumeration-from-a-pod.md) + * [Kubernetes Enumeration](pentesting/pentesting-kubernetes/enumeration-from-a-pod.md) * [Hardening Roles/ClusterRoles](pentesting/pentesting-kubernetes/hardening-roles-clusterroles.md) * [Pentesting Kubernetes from the outside](pentesting/pentesting-kubernetes/pentesting-kubernetes-from-the-outside.md) * [7/tcp/udp - Pentesting Echo](pentesting/7-tcp-udp-pentesting-echo.md) diff --git a/cloud-security/gcp-security/README.md b/cloud-security/gcp-security/README.md index 679fb616..7bd9f3ea 100644 --- a/cloud-security/gcp-security/README.md +++ b/cloud-security/gcp-security/README.md @@ -17,6 +17,14 @@ Organization A virtual machine (called a Compute Instance) is a resource. A resource resides in a project, probably alongside other Compute Instances, storage buckets, etc. +### **IAM Policies, Bindings and Memberships** + +In GCP there are different ways to grant a principal access over a resource: + +* **Memberships**: You set **principals as members of roles** **without restrictions** over the role or the principals. You can put a user as a member of a role and then put a group as a member of the same role and also set those principals (user and group) as member of other roles. +* **Bindings**: Several **principals can be binded to a role**. Those **principals can still be binded or be members of other roles**. However, if a principal which isn’t binded to the role is set as **member of a binded role**, the next time the **binding is applied, the membership will disappear**. +* **Policies**: A policy is **authoritative**, it indicates roles and principals and then, **those principals cannot have more roles and those roles cannot have more principals** unless that policy is modified (not even in other policies, bindings or memberships). Therefore, when a role or principal is specified in policy all its privileges are **limited by that policy**. Obviously, this can be bypassed in case the principal is given the option to modify the policy or privilege escalation permissions (like create a new principal and bind him a new role). + ### **IAM Roles** There are **three types** of roles in IAM: @@ -70,14 +78,6 @@ gcloud compute instances get-iam-policy [INSTANCE] --zone [ZONE] The IAM policies indicates the permissions principals has over resources via roles which ara assigned granular permissions. Organization policies **restrict how those service can be used or which features are enabled disabled**. This helps in order to improve the least privilege of each resource in the gcp environment. -### **Terraform IAM Policies, Bindings and Memberships** - -As defined by terraform in [https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google\_project\_iam](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google\_project\_iam) using terraform with GCP there are different ways to grant a principal access over a resource: - -* **Memberships**: You set **principals as members of roles** **without restrictions** over the role or the principals. You can put a user as a member of a role and then put a group as a member of the same role and also set those principals (user and group) as member of other roles. -* **Bindings**: Several **principals can be binded to a role**. Those **principals can still be binded or be members of other roles**. However, if a principal which isn’t binded to the role is set as **member of a binded role**, the next time the **binding is applied, the membership will disappear**. -* **Policies**: A policy is **authoritative**, it indicates roles and principals and then, **those principals cannot have more roles and those roles cannot have more principals** unless that policy is modified (not even in other policies, bindings or memberships). Therefore, when a role or principal is specified in policy all its privileges are **limited by that policy**. Obviously, this can be bypassed in case the principal is given the option to modify the policy or privilege escalation permissions (like create a new principal and bind him a new role). - ### **Service accounts** Virtual machine instances are usually **assigned a service account**. Every GCP project has a [default service account](https://cloud.google.com/compute/docs/access/service-accounts#default\_service\_account), and this will be assigned to new Compute Instances unless otherwise specified. Administrators can choose to use either a custom account or no account at all. This service account **can be used by any user or application on the machine** to communicate with the Google APIs. You can run the following command to see what accounts are available to you: diff --git a/pentesting/pentesting-kubernetes/enumeration-from-a-pod.md b/pentesting/pentesting-kubernetes/enumeration-from-a-pod.md index b29fb658..1ec757bc 100644 --- a/pentesting/pentesting-kubernetes/enumeration-from-a-pod.md +++ b/pentesting/pentesting-kubernetes/enumeration-from-a-pod.md @@ -1,20 +1,38 @@ -# Enumeration from a Pod +# Kubernetes Enumeration -In a situation where you have managed to break into a Kubernetes Pod you could start enumerating the kubernetes environment from within. +## Kubernetes Tokens -## Service Account Tokens +If you have compromised access to a machine the user may have access to some Kubernetes platform. The token is usually located in a file pointed by the **env var `KUBECONFIG`** or **inside `~/.kube`**. + +In this folder you might find config files with **tokens and configurations to connect to the API server**. In this folder you can also find a cache folder with information previously retrieved. + +If you have compromised a pod inside a kubernetes environment, there are other places where you can find tokens and information about the current K8 env: + +### Service Account Tokens Before continuing, if you don't know what is a service in Kubernetes I would suggest you to [**follow this link and read at least the information about Kubernetes architecture**](./#architecture)**.** +Taken from the Kubernetes [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server): + +_“When you create a pod, if you do not specify a service account, it is automatically assigned the_ default _service account in the same namespace.”_ + **ServiceAccount** is an object managed by Kubernetes and used to provide an identity for processes that run in a pod.\ Every service account has a secret related to it and this secret contains a bearer token. This is a JSON Web Token (JWT), a method for representing claims securely between two parties. -Usually in the directory `/run/secrets/kubernetes.io/serviceaccount` or `/var/run/secrets/kubernetes.io/serviceaccount` you can find the files: +Usually **one** of the directories: + +* `/run/secrets/kubernetes.io/serviceaccount` +* `/var/run/secrets/kubernetes.io/serviceaccount` +* `/secrets/kubernetes.io/serviceaccount` + +contain the files: * **ca.crt**: It's the ca certificate to check kubernetes communications * **namespace**: It indicates the current namespace * **token**: It contains the **service token** of the current pod. +Now that you have the token, you can find the API server inside the environment variable **`KUBECONFIG`**. For more info run `(env | set) | grep -i "kuber|kube`**`"`** + The service account token is being signed by the key residing in the file **sa.key** and validated by **sa.pub**. Default location on **Kubernetes**: @@ -25,10 +43,6 @@ Default location on **Minikube**: * /var/lib/localkube/certs -Taken from the Kubernetes [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server): - -_“When you create a pod, if you do not specify a service account, it is automatically assigned the_ default _service account in the same namespace.”_ - ### Hot Pods _**Hot pods are**_ pods containing a privileged service account token. A privileged service account token is a token that has permission to do privileged tasks such as listing secrets, creating pods, etc. @@ -39,18 +53,25 @@ If you don't know what is **RBAC**, [**read this section**](./#cluster-hardening ## Enumeration CheatSheet -To enumerate the environment you can upload the [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binary and use it. Also, using the **service** **token** obtained before you can manually access some endpoints of the **API Server**.\ -In order to find the the IP of the API service check the environment for a variable called `KUBERNETES_SERVICE_HOST`. +In order to enumerate a K8s environment you need a couple of this: + +* A **valid authentication token**. In the previous section we saw where to search for a user token and for a service account token. +* The **address (**_**https://host:port**_**) of the Kubernetes API**. This can be usually found in the environment variables and/or in the kube config file. +* **Optional**: The **ca.crt to verify the API server**. This can be found in the same places the token can be found. This is useful to verify the API server certificate, but using `--insecure-skip-tls-verify` with `kubectl` or `-k` with `curl` you won't need this. + +With those details you can **enumerate kubernetes**. If the **API** for some reason is **accessible** through the **Internet**, you can just download that info and enumerate the platform from your host. + +However, usually the **API server is inside an internal network**, therefore you will need to **create a tunnel** through the compromised machine to access it from your machine, or you can **upload the** [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binary, or use **`curl/wget/anything`** to perform raw HTTP requests to the API server. ### Differences between `list` and `get` verbs -With **`get`** permissions you can access the API: +With **`get`** permissions you can access information of specific assets (_`describe` option in `kubectl`_) API: ``` GET /apis/apps/v1/namespaces/{namespace}/deployments/{name} ``` -If you have the **`list`** permission, you are allowed to execute these API requests: +If you have the **`list`** permission, you are allowed to execute API requests to list a type of asset (_`get` option in `kubectl`_): ```bash #In a namespace @@ -59,7 +80,7 @@ GET /apis/apps/v1/namespaces/{namespace}/deployments GET /apis/apps/v1/deployments ``` -If you have the **`watch`** permission, you are allowed to execute these API requests: +If you have the **`watch`** permission, you are allowed to execute API requests to monitor assets: ``` GET /apis/apps/v1/deployments?watch=true @@ -77,16 +98,35 @@ The following `kubectl` commands indicates just how to list the objects. If you ### Using kubectl -when using kubectl it might come in handy to define a temporary alias, if the token used is different to the one defined in `/run/secrets/kubernetes.io/serviceaccount` or `/var/run/secrets/kubernetes.io/serviceaccount`. +Having the token and the address of the API server you use kubectl or curl to access it as indicated here: ```bash -alias kubectl='kubectl --token=' +alias kubectl='kubectl --token= --server=https://host:port --insecure-skip-tls-verify' ``` -[kubectl cheatsheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/) +You can find an [**official kubectl cheatsheet here**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/). The goal of the following sections is to present in ordered manner different options to enumerate and understand the new K8s you have obtained access to: + +### Get Current Privileges + +{% tabs %} +{% tab title="kubectl" %} +```bash +./kubectl auth can-i --list #Get privileges in general +./kubectl auth can-i --list -n custnamespace #Get privileves in custnamespace +``` +{% endtab %} +{% endtabs %} + +**Once you know which privileges** you have, check the following page to figure out **if you can abuse them** to escalate privileges: + +{% content-ref url="hardening-roles-clusterroles.md" %} +[hardening-roles-clusterroles.md](hardening-roles-clusterroles.md) +{% endcontent-ref %} ### Get namespaces +Kubernetes supports **multiple virtual clusters** backed by the same physical cluster. These virtual clusters are called **namespaces**. + {% tabs %} {% tab title="kubectl" %} ```bash @@ -96,8 +136,8 @@ alias kubectl='kubectl --token=' {% tab title="API" %} ```bash -curl -v -H "Authorization: Bearer " \ -https://:/api/v1/namespaces/ +curl -k -v -H "Authorization: Bearer $TOKEN" \ +https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT_HTTPS/api/v1/namespaces/ ``` {% endtab %} {% endtabs %} @@ -129,23 +169,23 @@ If you can read secrets you can use the following lines to get the privileges re for token in `./kubectl describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; ./kubectl --token $token auth can-i --list; echo; done ``` -### Get Current Privileges +### Get Service Accounts {% tabs %} {% tab title="kubectl" %} ```bash -./kubectl auth can-i --list #Get privileges in general -./kubectl auth can-i --list -n custnamespace #Get privileves in custnamespace +./kubectl get serviceaccounts +``` +{% endtab %} + +{% tab title="API" %} +```bash +curl -k -v -H "Authorization: Bearer $TOKEN" \ +https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT_HTTPS/api/v1/namespaces/{namespace}/serviceaccounts/api/v1/namespaces/ ``` {% endtab %} {% endtabs %} -**Once you know which privileges** you have, check the following page to figure out **if you can abuse them** to escalate privileges: - -{% content-ref url="hardening-roles-clusterroles.md" %} -[hardening-roles-clusterroles.md](hardening-roles-clusterroles.md) -{% endcontent-ref %} - ### Get Current Context {% tabs %} @@ -332,7 +372,7 @@ Information obtained from: [Kubernetes Namespace Breakout using Insecure Host Pa By default there isn't any encryption in the communication between pods .Mutual authentication, two-way, pod to pod. -#### Create a sidecar proxy app +#### Create a sidecar proxy app Create your .yaml @@ -393,7 +433,7 @@ kubectl get svc --all-namespaces ### Scanning -The following Bash script (taken from a [Kubernetes workshop](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md)) will install and scan the IP ranges of the kubernetes cluster: +The following Bash script (taken from a [Kubernetes workshop](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s\_cheatsheet.md)) will install and scan the IP ranges of the kubernetes cluster: ```bash sudo apt-get update