GitBook: [#2905] No subject
This commit is contained in:
parent
b1f71a3344
commit
b9a919bf04
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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=<jwt_token>'
|
||||
alias kubectl='kubectl --token=<jwt_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=<jwt_token>'
|
||||
|
||||
{% tab title="API" %}
|
||||
```bash
|
||||
curl -v -H "Authorization: Bearer <jwt_token>" \
|
||||
https://<Kubernetes_API_IP>:<port>/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 <a href="create-a-sidecar-proxy-app" id="create-a-sidecar-proxy-app"></a>
|
||||
#### Create a sidecar proxy app <a href="#create-a-sidecar-proxy-app" id="create-a-sidecar-proxy-app"></a>
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user